Browse Source
- Add lib/libopus/ (opus v1.6.1 embedded source: CELT 18 .c, SILK 77 .c, SILK float 28 .c, OPUS core 14 .c) - Add lib/opus_codec.h/.c (wrapper: encoder, decoder, raw PCM int16) - Add tests/test_opus_codec.c (7 tests: silence, sine, compression, PLC, null, defaults, multi-frame) - chatgui: AudioRecorder (miniaudio capture, 48kHz mono) - chatgui: VoiceEncoder (PCM→Opus file with custom container) - chatgui: VoicePlayer (Opus→PCM playback via SoundManager) - chatgui: PTT button in InputBar, voice message send/receive in MessageList - chatgui: AudioDeviceSettingsPage (device selection, persisted in ui_state) - chatgui: MessageDelegate voice message rendering (play button + duration) - Update autotools: configure.ac, Makefile.am, src/Makefile.am, tests/Makefile.am - Update CMake: chatgui CMakeLists.txt, libutun CMakeLists.txt (link libopus_internal.a)topo_upd
260 changed files with 72665 additions and 16 deletions
@ -0,0 +1,154 @@
|
||||
noinst_LIBRARIES = libopus_internal.a
|
||||
|
||||
libopus_internal_a_SOURCES = \
|
||||
celt/bands.c \
|
||||
celt/celt.c \
|
||||
celt/celt_encoder.c \
|
||||
celt/celt_decoder.c \
|
||||
celt/celt_lpc.c \
|
||||
celt/cwrs.c \
|
||||
celt/entcode.c \
|
||||
celt/entdec.c \
|
||||
celt/entenc.c \
|
||||
celt/kiss_fft.c \
|
||||
celt/laplace.c \
|
||||
celt/mathops.c \
|
||||
celt/mdct.c \
|
||||
celt/modes.c \
|
||||
celt/pitch.c \
|
||||
celt/quant_bands.c \
|
||||
celt/rate.c \
|
||||
celt/vq.c \
|
||||
silk/CNG.c \
|
||||
silk/code_signs.c \
|
||||
silk/init_decoder.c \
|
||||
silk/decode_core.c \
|
||||
silk/decode_frame.c \
|
||||
silk/decode_parameters.c \
|
||||
silk/decode_indices.c \
|
||||
silk/decode_pulses.c \
|
||||
silk/decoder_set_fs.c \
|
||||
silk/dec_API.c \
|
||||
silk/enc_API.c \
|
||||
silk/encode_indices.c \
|
||||
silk/encode_pulses.c \
|
||||
silk/gain_quant.c \
|
||||
silk/interpolate.c \
|
||||
silk/LP_variable_cutoff.c \
|
||||
silk/NLSF_decode.c \
|
||||
silk/NSQ.c \
|
||||
silk/NSQ_del_dec.c \
|
||||
silk/PLC.c \
|
||||
silk/shell_coder.c \
|
||||
silk/tables_gain.c \
|
||||
silk/tables_LTP.c \
|
||||
silk/tables_NLSF_CB_NB_MB.c \
|
||||
silk/tables_NLSF_CB_WB.c \
|
||||
silk/tables_other.c \
|
||||
silk/tables_pitch_lag.c \
|
||||
silk/tables_pulses_per_block.c \
|
||||
silk/VAD.c \
|
||||
silk/control_audio_bandwidth.c \
|
||||
silk/quant_LTP_gains.c \
|
||||
silk/VQ_WMat_EC.c \
|
||||
silk/HP_variable_cutoff.c \
|
||||
silk/NLSF_encode.c \
|
||||
silk/NLSF_VQ.c \
|
||||
silk/NLSF_unpack.c \
|
||||
silk/NLSF_del_dec_quant.c \
|
||||
silk/process_NLSFs.c \
|
||||
silk/stereo_LR_to_MS.c \
|
||||
silk/stereo_MS_to_LR.c \
|
||||
silk/check_control_input.c \
|
||||
silk/control_SNR.c \
|
||||
silk/init_encoder.c \
|
||||
silk/control_codec.c \
|
||||
silk/A2NLSF.c \
|
||||
silk/ana_filt_bank_1.c \
|
||||
silk/biquad_alt.c \
|
||||
silk/bwexpander_32.c \
|
||||
silk/bwexpander.c \
|
||||
silk/debug.c \
|
||||
silk/decode_pitch.c \
|
||||
silk/inner_prod_aligned.c \
|
||||
silk/lin2log.c \
|
||||
silk/log2lin.c \
|
||||
silk/LPC_analysis_filter.c \
|
||||
silk/LPC_inv_pred_gain.c \
|
||||
silk/table_LSF_cos.c \
|
||||
silk/NLSF2A.c \
|
||||
silk/NLSF_stabilize.c \
|
||||
silk/NLSF_VQ_weights_laroia.c \
|
||||
silk/pitch_est_tables.c \
|
||||
silk/resampler.c \
|
||||
silk/resampler_down2_3.c \
|
||||
silk/resampler_down2.c \
|
||||
silk/resampler_private_AR2.c \
|
||||
silk/resampler_private_down_FIR.c \
|
||||
silk/resampler_private_IIR_FIR.c \
|
||||
silk/resampler_private_up2_HQ.c \
|
||||
silk/resampler_rom.c \
|
||||
silk/sigm_Q15.c \
|
||||
silk/sort.c \
|
||||
silk/sum_sqr_shift.c \
|
||||
silk/stereo_decode_pred.c \
|
||||
silk/stereo_encode_pred.c \
|
||||
silk/stereo_find_predictor.c \
|
||||
silk/stereo_quant_pred.c \
|
||||
silk/LPC_fit.c \
|
||||
silk/float/apply_sine_window_FLP.c \
|
||||
silk/float/corrMatrix_FLP.c \
|
||||
silk/float/encode_frame_FLP.c \
|
||||
silk/float/find_LPC_FLP.c \
|
||||
silk/float/find_LTP_FLP.c \
|
||||
silk/float/find_pitch_lags_FLP.c \
|
||||
silk/float/find_pred_coefs_FLP.c \
|
||||
silk/float/LPC_analysis_filter_FLP.c \
|
||||
silk/float/LTP_analysis_filter_FLP.c \
|
||||
silk/float/LTP_scale_ctrl_FLP.c \
|
||||
silk/float/noise_shape_analysis_FLP.c \
|
||||
silk/float/process_gains_FLP.c \
|
||||
silk/float/regularize_correlations_FLP.c \
|
||||
silk/float/residual_energy_FLP.c \
|
||||
silk/float/warped_autocorrelation_FLP.c \
|
||||
silk/float/wrappers_FLP.c \
|
||||
silk/float/autocorrelation_FLP.c \
|
||||
silk/float/burg_modified_FLP.c \
|
||||
silk/float/bwexpander_FLP.c \
|
||||
silk/float/energy_FLP.c \
|
||||
silk/float/inner_product_FLP.c \
|
||||
silk/float/k2a_FLP.c \
|
||||
silk/float/LPC_inv_pred_gain_FLP.c \
|
||||
silk/float/pitch_analysis_core_FLP.c \
|
||||
silk/float/scale_copy_vector_FLP.c \
|
||||
silk/float/scale_vector_FLP.c \
|
||||
silk/float/schur_FLP.c \
|
||||
silk/float/sort_FLP.c \
|
||||
src/opus.c \
|
||||
src/opus_decoder.c \
|
||||
src/opus_encoder.c \
|
||||
src/extensions.c \
|
||||
src/opus_multistream.c \
|
||||
src/opus_multistream_encoder.c \
|
||||
src/opus_multistream_decoder.c \
|
||||
src/repacketizer.c \
|
||||
src/opus_projection_encoder.c \
|
||||
src/opus_projection_decoder.c \
|
||||
src/mapping_matrix.c \
|
||||
src/analysis.c \
|
||||
src/mlp.c \
|
||||
src/mlp_data.c
|
||||
|
||||
libopus_internal_a_CFLAGS = \
|
||||
-DOPUS_BUILD \
|
||||
-DVAR_ARRAYS \
|
||||
-DUSE_ALLOCA \
|
||||
-DHAVE_ALLOCA_H \
|
||||
-g \
|
||||
-I$(srcdir)/include \
|
||||
-I$(srcdir)/celt \
|
||||
-I$(srcdir)/silk \
|
||||
-I$(srcdir)/silk/float \
|
||||
-I$(srcdir)/silk/fixed \
|
||||
-I$(srcdir)/src \
|
||||
-I$(srcdir)
|
||||
@ -0,0 +1,188 @@
|
||||
/*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 |
||||
|
||||
#ifdef ENABLE_QEXT |
||||
# define S_MUL(a,b) MULT32_32_P31_ovflw(b, a) |
||||
# define S_MUL2(a,b) MULT32_32_P31_ovflw(b, a) |
||||
#else |
||||
# define S_MUL(a,b) MULT16_32_Q15(b, a) |
||||
# define S_MUL2(a,b) MULT16_32_Q16(b, a) |
||||
#endif |
||||
|
||||
# define C_MUL(m,a,b) \ |
||||
do{ (m).r = SUB32_ovflw(S_MUL((a).r,(b).r) , S_MUL((a).i,(b).i)); \
|
||||
(m).i = ADD32_ovflw(S_MUL((a).r,(b).i) , S_MUL((a).i,(b).r)); }while(0) |
||||
|
||||
# define C_MULC(m,a,b) \ |
||||
do{ (m).r = ADD32_ovflw(S_MUL((a).r,(b).r) , S_MUL((a).i,(b).i)); \
|
||||
(m).i = SUB32_ovflw(S_MUL((a).i,(b).r) , S_MUL((a).r,(b).i)); }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_ovflw((a).r,(b).r); (res).i=ADD32_ovflw((a).i,(b).i); \
|
||||
}while(0) |
||||
#define C_SUB( res, a,b)\ |
||||
do {(res).r=SUB32_ovflw((a).r,(b).r); (res).i=SUB32_ovflw((a).i,(b).i); \
|
||||
}while(0) |
||||
#define C_ADDTO( res , a)\ |
||||
do {(res).r = ADD32_ovflw((res).r, (a).r); (res).i = ADD32_ovflw((res).i,(a).i);\
|
||||
}while(0) |
||||
|
||||
#define C_SUBFROM( res , a)\ |
||||
do {(res).r = ADD32_ovflw((res).r,(a).r); (res).i = SUB32_ovflw((res).i,(a).i); \
|
||||
}while(0) |
||||
|
||||
#if defined(OPUS_ARM_INLINE_ASM) |
||||
#include "arm/kiss_fft_armv4.h" |
||||
#endif |
||||
|
||||
#if defined(OPUS_ARM_INLINE_EDSP) |
||||
#include "arm/kiss_fft_armv5e.h" |
||||
#endif |
||||
#if defined(__mips) |
||||
#include "mips/kiss_fft_mipsr1.h" |
||||
#endif |
||||
|
||||
#else /* not FIXED_POINT*/ |
||||
|
||||
# define S_MUL(a,b) ( (a)*(b) ) |
||||
# define S_MUL2(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,400 @@
|
||||
/* 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" |
||||
#include "opus_defines.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 |
||||
|
||||
#if OPUS_GNUC_PREREQ(3, 0) |
||||
#define opus_likely(x) (__builtin_expect(!!(x), 1)) |
||||
#define opus_unlikely(x) (__builtin_expect(!!(x), 0)) |
||||
#else |
||||
#define opus_likely(x) (!!(x)) |
||||
#define opus_unlikely(x) (!!(x)) |
||||
#endif |
||||
|
||||
#define CELT_SIG_SCALE 32768.f |
||||
|
||||
#define CELT_FATAL(str) celt_fatal(str, __FILE__, __LINE__) |
||||
|
||||
#if defined(ENABLE_ASSERTIONS) || defined(ENABLE_HARDENING) |
||||
#ifdef __GNUC__ |
||||
__attribute__((noreturn)) |
||||
#endif |
||||
void celt_fatal(const char *str, const char *file, int line); |
||||
|
||||
#if defined(CELT_C) && !defined(OVERRIDE_celt_fatal) |
||||
#include <stdio.h> |
||||
#include <stdlib.h> |
||||
#ifdef __GNUC__ |
||||
__attribute__((noreturn)) |
||||
#endif |
||||
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); |
||||
#if defined(_MSC_VER) |
||||
_set_abort_behavior( 0, _WRITE_ABORT_MSG); |
||||
#endif |
||||
abort(); |
||||
} |
||||
#endif |
||||
|
||||
#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);}} |
||||
#define MUST_SUCCEED(call) celt_assert((call) == OPUS_OK) |
||||
#else |
||||
#define celt_assert(cond) ((void)(cond)) |
||||
#define celt_assert2(cond, message) ((void)(cond)) |
||||
#define MUST_SUCCEED(call) do {if((call) != OPUS_OK) {RESTORE_STACK; return OPUS_INTERNAL_ERROR;} } while (0) |
||||
#endif |
||||
|
||||
#if defined(ENABLE_ASSERTIONS) |
||||
#define celt_sig_assert(cond) {if (!(cond)) {CELT_FATAL("signal assertion failed: " #cond);}} |
||||
#else |
||||
#define celt_sig_assert(cond) ((void)(cond)) |
||||
#endif |
||||
|
||||
#define IMUL32(a,b) ((a)*(b)) |
||||
|
||||
#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 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 FMIN(a,b) ((a) < (b) ? (a) : (b)) /**< Minimum float value. */ |
||||
#define FMAX(a,b) ((a) > (b) ? (a) : (b)) /**< Maximum float value. */ |
||||
#define UADD32(a,b) ((a)+(b)) |
||||
#define USUB32(a,b) ((a)-(b)) |
||||
#define MAXG(a,b) MAX32(a, b) |
||||
#define MING(a,b) MIN32(a, b) |
||||
|
||||
/* Throughout the code, we use the following scaling for signals:
|
||||
FLOAT: used for float API, normalized to +/-1. |
||||
INT16: used for 16-bit API, normalized to +/- 32768 |
||||
RES: internal Opus resolution, defined as +/-1. in float builds, or either 16-bit or 24-bit int for fixed-point builds |
||||
SIG: internal CELT resolution: defined as +/- 32768. in float builds, or Q27 in fixed-point builds (int16 shifted by 12) |
||||
*/ |
||||
|
||||
|
||||
/* Set this if opus_int64 is a native type of the CPU. */ |
||||
/* Assume that all LP64 architectures have fast 64-bit types; also x86_64
|
||||
(which can be ILP32 for x32) and Win64 (which is LLP64). */ |
||||
#if defined(__x86_64__) || defined(__LP64__) || defined(_WIN64) || defined (__mips) |
||||
#define OPUS_FAST_INT64 1 |
||||
#else |
||||
#define OPUS_FAST_INT64 0 |
||||
#endif |
||||
|
||||
#ifdef FIXED_POINT |
||||
#define ARG_FIXED(arg) , arg |
||||
#else |
||||
#define ARG_FIXED(arg) |
||||
#endif |
||||
|
||||
#define PRINT_MIPS(file) |
||||
|
||||
#ifdef FIXED_POINT |
||||
|
||||
typedef opus_int16 opus_val16; |
||||
typedef opus_int32 opus_val32; |
||||
typedef opus_int64 opus_val64; |
||||
|
||||
typedef opus_val32 celt_sig; |
||||
typedef opus_val32 celt_norm; |
||||
typedef opus_val32 celt_ener; |
||||
typedef opus_val32 celt_glog; |
||||
|
||||
#ifdef ENABLE_RES24 |
||||
typedef opus_val32 opus_res; |
||||
#define RES_SHIFT 8 |
||||
#define SIG2RES(a) PSHR32(a, SIG_SHIFT-RES_SHIFT) |
||||
#define RES2INT16(a) SAT16(PSHR32(a, RES_SHIFT)) |
||||
#define RES2INT24(a) (a) |
||||
#define RES2FLOAT(a) ((1.f/32768.f/256.f)*(a)) |
||||
#define INT16TORES(a) SHL32(EXTEND32(a), RES_SHIFT) |
||||
#define INT24TORES(a) (a) |
||||
#define ADD_RES(a, b) ADD32(a, b) |
||||
#define FLOAT2RES(a) FLOAT2INT24(a) |
||||
#define RES2SIG(a) SHL32((a), SIG_SHIFT-RES_SHIFT) |
||||
#define MULT16_RES_Q15(a,b) MULT16_32_Q15(a,b) |
||||
#define MAX_ENCODING_DEPTH 24 |
||||
#else |
||||
typedef opus_val16 opus_res; |
||||
#define RES_SHIFT 0 |
||||
#define SIG2RES(a) SIG2WORD16(a) |
||||
#define RES2INT16(a) (a) |
||||
#define RES2INT24(a) SHL32(EXTEND32(a), 8) |
||||
#define RES2FLOAT(a) ((1.f/32768.f)*(a)) |
||||
#define INT16TORES(a) (a) |
||||
#define INT24TORES(a) SAT16(PSHR32(a, 8)) |
||||
#define ADD_RES(a, b) SAT16(ADD32((a), (b))); |
||||
#define FLOAT2RES(a) FLOAT2INT16(a) |
||||
#define RES2SIG(a) SHL32(EXTEND32(a), SIG_SHIFT) |
||||
#define MULT16_RES_Q15(a,b) MULT16_16_Q15(a,b) |
||||
#define MAX_ENCODING_DEPTH 16 |
||||
#endif |
||||
|
||||
#define RES2VAL16(a) RES2INT16(a) |
||||
#define INT16TOSIG(a) SHL32(EXTEND32(a), SIG_SHIFT) |
||||
#define INT24TOSIG(a) SHL32(a, SIG_SHIFT-8) |
||||
|
||||
#define NORM_SHIFT 24 |
||||
#ifdef ENABLE_QEXT |
||||
typedef opus_val32 celt_coef; |
||||
#define COEF_ONE Q31ONE |
||||
#define MULT_COEF_32(a, b) MULT32_32_P31(a,b) |
||||
#define MAC_COEF_32_ARM(c, a, b) ADD32((c), MULT32_32_Q32(a,b)) |
||||
#define MULT_COEF(a, b) MULT32_32_Q31(a,b) |
||||
#define MULT_COEF_TAPS(a, b) SHL32(MULT16_16(a,b), 1) |
||||
#define COEF2VAL16(x) EXTRACT16(SHR32(x, 16)) |
||||
#else |
||||
typedef opus_val16 celt_coef; |
||||
#define COEF_ONE Q15ONE |
||||
#define MULT_COEF_32(a, b) MULT16_32_Q15(a,b) |
||||
#define MAC_COEF_32_ARM(a, b, c) MAC16_32_Q16(a,b,c) |
||||
#define MULT_COEF(a, b) MULT16_16_Q15(a,b) |
||||
#define MULT_COEF_TAPS(a, b) MULT16_16_P15(a,b) |
||||
#define COEF2VAL16(x) (x) |
||||
#endif |
||||
|
||||
#define celt_isnan(x) 0 |
||||
|
||||
#define Q15ONE 32767 |
||||
#define Q31ONE 2147483647 |
||||
|
||||
#define SIG_SHIFT 12 |
||||
/* Safe saturation value for 32-bit signals. We need to make sure that we can
|
||||
add two sig values and that the first stages of the MDCT don't cause an overflow. |
||||
The most constraining is the ARM_ASM comb filter where we shift left by one |
||||
and then add two values. Because of that, we use 2^29-1. SIG_SAT must be large |
||||
enough to fit a full-scale high-freq tone through the prefilter and comb filter, |
||||
meaning 1.85*1.75*2^(15+SIG_SHIFT) = 434529895. |
||||
so the limit should be about 2^31*sqrt(.5). */ |
||||
#define SIG_SAT (536870911) |
||||
|
||||
#define NORM_SCALING (1<<NORM_SHIFT) |
||||
|
||||
#define DB_SHIFT 24 |
||||
|
||||
#define EPSILON 1 |
||||
#define VERY_SMALL 0 |
||||
#define VERY_LARGE16 ((opus_val16)32767) |
||||
#define Q15_ONE ((opus_val16)32767) |
||||
|
||||
|
||||
#define ABS16(x) ((x) < 0 ? (-(x)) : (x)) |
||||
#define ABS32(x) ((x) < 0 ? (-(x)) : (x)) |
||||
|
||||
static OPUS_INLINE opus_int16 SAT16(opus_int32 x) { |
||||
return x > 32767 ? 32767 : x < -32768 ? -32768 : (opus_int16)x; |
||||
} |
||||
|
||||
#ifdef FIXED_DEBUG |
||||
#include "fixed_debug.h" |
||||
#else |
||||
|
||||
#include "fixed_generic.h" |
||||
|
||||
#ifdef OPUS_ARM_PRESUME_AARCH64_NEON_INTR |
||||
#include "arm/fixed_arm64.h" |
||||
#elif defined (OPUS_ARM_INLINE_EDSP) |
||||
#include "arm/fixed_armv5e.h" |
||||
#elif defined (OPUS_ARM_INLINE_ASM) |
||||
#include "arm/fixed_armv4.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 opus_val64; |
||||
|
||||
typedef float celt_sig; |
||||
typedef float celt_norm; |
||||
typedef float celt_ener; |
||||
typedef float celt_glog; |
||||
|
||||
typedef float opus_res; |
||||
typedef float celt_coef; |
||||
|
||||
#ifdef FLOAT_APPROX |
||||
/* This code should reliably detect NaN/inf even when -ffast-math is used.
|
||||
Assumes IEEE 754 format. */ |
||||
static OPUS_INLINE int celt_isnan(float x) |
||||
{ |
||||
union {float f; opus_uint32 i;} in; |
||||
in.f = x; |
||||
return ((in.i>>23)&0xFF)==0xFF && (in.i&0x007FFFFF)!=0; |
||||
} |
||||
#else |
||||
#ifdef __FAST_MATH__ |
||||
#error Cannot build libopus with -ffast-math unless FLOAT_APPROX is defined. This could result in crashes on extreme (e.g. NaN) input |
||||
#endif |
||||
#define celt_isnan(x) ((x)!=(x)) |
||||
#endif |
||||
|
||||
#define Q15ONE 1.0f |
||||
#define Q31ONE 1.0f |
||||
#define COEF_ONE 1.0f |
||||
#define COEF2VAL16(x) (x) |
||||
|
||||
#define NORM_SCALING 1.f |
||||
|
||||
#define EPSILON 1e-15f |
||||
#define VERY_SMALL 1e-30f |
||||
#define VERY_LARGE16 1e15f |
||||
#define Q15_ONE ((opus_val16)1.f) |
||||
|
||||
/* This appears to be the same speed as C99's fabsf() but it's more portable. */ |
||||
#define ABS16(x) ((float)fabs(x)) |
||||
#define ABS32(x) ((float)fabs(x)) |
||||
|
||||
#define QCONST16(x,bits) (x) |
||||
#define QCONST32(x,bits) (x) |
||||
#define GCONST(x) (x) |
||||
|
||||
#define NEG16(x) (-(x)) |
||||
#define NEG32(x) (-(x)) |
||||
#define NEG32_ovflw(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 SHR64(a,shift) (a) |
||||
|
||||
#define PSHR(a,shift) (a) |
||||
#define SHR(a,shift) (a) |
||||
#define SHL(a,shift) (a) |
||||
#define SATURATE(x,a) (x) |
||||
#define SATURATE16(x) (x) |
||||
|
||||
#define ROUND16(a,shift) (a) |
||||
#define SROUND16(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 ADD32_ovflw(a,b) ((a)+(b)) |
||||
#define SUB32_ovflw(a,b) ((a)-(b)) |
||||
#define SHL32_ovflw(a,shift) (a) |
||||
#define PSHR32_ovflw(a,shift) (a) |
||||
|
||||
#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_Q16(a,b) ((a)*(b)) |
||||
#define MULT32_32_Q31(a,b) ((a)*(b)) |
||||
#define MULT32_32_P31(a,b) ((a)*(b)) |
||||
#define MULT32_32_P31_ovflw(a,b) ((a)*(b)) |
||||
|
||||
#define MAC16_32_Q15(c,a,b) ((c)+(a)*(b)) |
||||
#define MAC16_32_Q16(c,a,b) ((c)+(a)*(b)) |
||||
#define MAC_COEF_32_ARM(c,a,b) ((c)+(a)*(b)) |
||||
|
||||
#define MULT16_16_Q11_32(a,b) ((a)*(b)) |
||||
#define MULT16_16_Q11(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 MULT_COEF_32(a, b) ((a)*(b)) |
||||
#define MULT_COEF(a, b) ((a)*(b)) |
||||
#define MULT_COEF_TAPS(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 SIG2RES(a) ((1/CELT_SIG_SCALE)*(a)) |
||||
#define RES2INT16(a) FLOAT2INT16(a) |
||||
#define RES2INT24(a) float2int(32768.f*256.f*(a)) |
||||
#define RES2FLOAT(a) (a) |
||||
#define INT16TORES(a) ((a)*(1/CELT_SIG_SCALE)) |
||||
#define INT24TORES(a) ((1.f/32768.f/256.f)*(a)) |
||||
#define ADD_RES(a, b) ADD32(a, b) |
||||
#define FLOAT2RES(a) (a) |
||||
#define RES2SIG(a) (CELT_SIG_SCALE*(a)) |
||||
#define MULT16_RES_Q15(a,b) MULT16_16_Q15(a,b) |
||||
|
||||
#define RES2VAL16(a) (a) |
||||
#define FLOAT2SIG(a) ((a)*CELT_SIG_SCALE) |
||||
#define INT16TOSIG(a) ((float)(a)) |
||||
#define INT24TOSIG(a) ((float)(a)*(1.f/256.f)) |
||||
#define MAX_ENCODING_DEPTH 24 |
||||
|
||||
#endif /* !FIXED_POINT */ |
||||
|
||||
#ifndef GLOBAL_STACK_SIZE |
||||
#ifdef FIXED_POINT |
||||
#define GLOBAL_STACK_SIZE 120000 |
||||
#else |
||||
#define GLOBAL_STACK_SIZE 120000 |
||||
#endif |
||||
#endif |
||||
|
||||
#endif /* ARCH_H */ |
||||
@ -0,0 +1,125 @@
|
||||
/* 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" |
||||
|
||||
opus_int16 bitexact_cos(opus_int16 x); |
||||
int bitexact_log2tan(int isin,int icos); |
||||
|
||||
/** Compute the amplitude (sqrt energy) in each of the bands
|
||||
* @param m Mode data |
||||
* @param X Spectrum |
||||
* @param bandE 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 LM, int arch); |
||||
|
||||
/*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 bandE 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 bandE 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_glog *bandE, int start, |
||||
int end, int M, int downsample, int silence); |
||||
|
||||
#define SPREAD_NONE (0) |
||||
#define SPREAD_LIGHT (1) |
||||
#define SPREAD_NORMAL (2) |
||||
#define SPREAD_AGGRESSIVE (3) |
||||
|
||||
int spreading_decision(const CELTMode *m, const celt_norm *X, int *average, |
||||
int last_decision, int *hf_average, int *tapset_decision, int update_hf, |
||||
int end, int C, int M, const int *spread_weight); |
||||
|
||||
#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 encode flag that indicates whether we're encoding (1) or decoding (0) |
||||
* @param m Mode data |
||||
* @param start First band to process |
||||
* @param end Last band to process + 1 |
||||
* @param X Residual (normalised) |
||||
* @param Y Residual (normalised) for second channel (or NULL for mono) |
||||
* @param collapse_masks Anti-collapse tracking mask |
||||
* @param bandE Square root of the energy for each band |
||||
* @param pulses Bit allocation (per band) for PVQ |
||||
* @param shortBlocks Zero for long blocks, non-zero for short blocks |
||||
* @param spread Amount of spreading to use |
||||
* @param dual_stereo Zero for MS stereo, non-zero for dual stereo |
||||
* @param intensity First band to use intensity stereo |
||||
* @param tf_res Time-frequency resolution change |
||||
* @param total_bits Total number of bits that can be used for the frame (including the ones already spent) |
||||
* @param balance Number of unallocated bits |
||||
* @param en Entropy coder state |
||||
* @param LM log2() of the number of 2.5 subframes in the frame |
||||
* @param codedBands Last band to receive bits + 1 |
||||
* @param seed Random generator seed |
||||
* @param arch Run-time architecture (see opus_select_arch()) |
||||
*/ |
||||
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 shortBlocks, int spread, |
||||
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, |
||||
int complexity, int arch, int disable_inv |
||||
ARG_QEXT(ec_ctx *ext_ec) ARG_QEXT(int *extra_pulses) |
||||
ARG_QEXT(opus_int32 total_ext_bits) ARG_QEXT(const int *cap)); |
||||
|
||||
void anti_collapse(const CELTMode *m, celt_norm *X_, |
||||
unsigned char *collapse_masks, int LM, int C, int size, int start, |
||||
int end, const celt_glog *logE, const celt_glog *prev1logE, |
||||
const celt_glog *prev2logE, const int *pulses, opus_uint32 seed, |
||||
int encode, int arch); |
||||
|
||||
opus_uint32 celt_lcg_rand(opus_uint32 seed); |
||||
|
||||
int hysteresis_decision(opus_val16 val, const opus_val16 *thresholds, const opus_val16 *hysteresis, int N, int prev); |
||||
|
||||
#endif /* BANDS_H */ |
||||
@ -0,0 +1,373 @@
|
||||
/* Copyright (c) 2007-2008 CSIRO
|
||||
Copyright (c) 2007-2010 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 |
||||
|
||||
#define CELT_C |
||||
|
||||
#include "os_support.h" |
||||
#include "mdct.h" |
||||
#include <math.h> |
||||
#include "celt.h" |
||||
#include "pitch.h" |
||||
#include "bands.h" |
||||
#include "modes.h" |
||||
#include "entcode.h" |
||||
#include "quant_bands.h" |
||||
#include "rate.h" |
||||
#include "stack_alloc.h" |
||||
#include "mathops.h" |
||||
#include "float_cast.h" |
||||
#include <stdarg.h> |
||||
#include "celt_lpc.h" |
||||
#include "vq.h" |
||||
|
||||
#ifndef PACKAGE_VERSION |
||||
#define PACKAGE_VERSION "unknown" |
||||
#endif |
||||
|
||||
#if defined(FIXED_POINT) && defined(__mips) |
||||
#include "mips/celt_mipsr1.h" |
||||
#endif |
||||
|
||||
|
||||
int resampling_factor(opus_int32 rate) |
||||
{ |
||||
int ret; |
||||
switch (rate) |
||||
{ |
||||
#ifdef ENABLE_QEXT |
||||
case 96000: |
||||
#endif |
||||
case 48000: |
||||
ret = 1; |
||||
break; |
||||
case 24000: |
||||
ret = 2; |
||||
break; |
||||
case 16000: |
||||
ret = 3; |
||||
break; |
||||
case 12000: |
||||
ret = 4; |
||||
break; |
||||
case 8000: |
||||
ret = 6; |
||||
break; |
||||
default: |
||||
#ifndef CUSTOM_MODES |
||||
celt_assert(0); |
||||
#endif |
||||
ret = 0; |
||||
break; |
||||
} |
||||
return ret; |
||||
} |
||||
|
||||
|
||||
#if !defined(OVERRIDE_COMB_FILTER_CONST) || defined(NON_STATIC_COMB_FILTER_CONST_C) |
||||
/* This version should be faster on ARM */ |
||||
#ifdef OPUS_ARM_ASM |
||||
#ifndef NON_STATIC_COMB_FILTER_CONST_C |
||||
static |
||||
#endif |
||||
void comb_filter_const_c(opus_val32 *y, opus_val32 *x, int T, int N, |
||||
celt_coef g10, celt_coef g11, celt_coef g12) |
||||
{ |
||||
opus_val32 x0, x1, x2, x3, x4; |
||||
int i; |
||||
x4 = SHL32(x[-T-2], 1); |
||||
x3 = SHL32(x[-T-1], 1); |
||||
x2 = SHL32(x[-T], 1); |
||||
x1 = SHL32(x[-T+1], 1); |
||||
for (i=0;i<N-4;i+=5) |
||||
{ |
||||
opus_val32 t; |
||||
x0=SHL32(x[i-T+2],1); |
||||
t = MAC_COEF_32_ARM(x[i], g10, x2); |
||||
t = MAC_COEF_32_ARM(t, g11, ADD32(x1,x3)); |
||||
t = MAC_COEF_32_ARM(t, g12, ADD32(x0,x4)); |
||||
t = SATURATE(t, SIG_SAT); |
||||
y[i] = t; |
||||
x4=SHL32(x[i-T+3],1); |
||||
t = MAC_COEF_32_ARM(x[i+1], g10, x1); |
||||
t = MAC_COEF_32_ARM(t, g11, ADD32(x0,x2)); |
||||
t = MAC_COEF_32_ARM(t, g12, ADD32(x4,x3)); |
||||
t = SATURATE(t, SIG_SAT); |
||||
y[i+1] = t; |
||||
x3=SHL32(x[i-T+4],1); |
||||
t = MAC_COEF_32_ARM(x[i+2], g10, x0); |
||||
t = MAC_COEF_32_ARM(t, g11, ADD32(x4,x1)); |
||||
t = MAC_COEF_32_ARM(t, g12, ADD32(x3,x2)); |
||||
t = SATURATE(t, SIG_SAT); |
||||
y[i+2] = t; |
||||
x2=SHL32(x[i-T+5],1); |
||||
t = MAC_COEF_32_ARM(x[i+3], g10, x4); |
||||
t = MAC_COEF_32_ARM(t, g11, ADD32(x3,x0)); |
||||
t = MAC_COEF_32_ARM(t, g12, ADD32(x2,x1)); |
||||
t = SATURATE(t, SIG_SAT); |
||||
y[i+3] = t; |
||||
x1=SHL32(x[i-T+6],1); |
||||
t = MAC_COEF_32_ARM(x[i+4], g10, x3); |
||||
t = MAC_COEF_32_ARM(t, g11, ADD32(x2,x4)); |
||||
t = MAC_COEF_32_ARM(t, g12, ADD32(x1,x0)); |
||||
t = SATURATE(t, SIG_SAT); |
||||
y[i+4] = t; |
||||
} |
||||
#ifdef CUSTOM_MODES |
||||
for (;i<N;i++) |
||||
{ |
||||
opus_val32 t; |
||||
x0=SHL32(x[i-T+2],1); |
||||
t = MAC_COEF_32_ARM(x[i], g10, x2); |
||||
t = MAC_COEF_32_ARM(t, g11, ADD32(x1,x3)); |
||||
t = MAC_COEF_32_ARM(t, g12, ADD32(x0,x4)); |
||||
t = SATURATE(t, SIG_SAT); |
||||
y[i] = t; |
||||
x4=x3; |
||||
x3=x2; |
||||
x2=x1; |
||||
x1=x0; |
||||
} |
||||
#endif |
||||
} |
||||
#else |
||||
#ifndef NON_STATIC_COMB_FILTER_CONST_C |
||||
static |
||||
#endif |
||||
void comb_filter_const_c(opus_val32 *y, opus_val32 *x, int T, int N, |
||||
celt_coef g10, celt_coef g11, celt_coef g12) |
||||
{ |
||||
opus_val32 x0, x1, x2, x3, x4; |
||||
int i; |
||||
x4 = x[-T-2]; |
||||
x3 = x[-T-1]; |
||||
x2 = x[-T]; |
||||
x1 = x[-T+1]; |
||||
for (i=0;i<N;i++) |
||||
{ |
||||
x0=x[i-T+2]; |
||||
y[i] = x[i] |
||||
+ MULT_COEF_32(g10,x2) |
||||
+ MULT_COEF_32(g11,ADD32(x1,x3)) |
||||
+ MULT_COEF_32(g12,ADD32(x0,x4)); |
||||
#ifdef FIXED_POINT |
||||
/* A bit of bias seems to help here. */ |
||||
y[i] = SUB32(y[i], 1); |
||||
#endif |
||||
y[i] = SATURATE(y[i], SIG_SAT); |
||||
x4=x3; |
||||
x3=x2; |
||||
x2=x1; |
||||
x1=x0; |
||||
} |
||||
|
||||
} |
||||
#endif |
||||
#endif |
||||
|
||||
#ifdef ENABLE_QEXT |
||||
void comb_filter_qext(opus_val32 *y, opus_val32 *x, int T0, int T1, int N, |
||||
opus_val16 g0, opus_val16 g1, int tapset0, int tapset1, |
||||
const celt_coef *window, int overlap, int arch) |
||||
{ |
||||
VARDECL(opus_val32, mem_buf); |
||||
VARDECL(opus_val32, buf); |
||||
celt_coef new_window[120]; |
||||
int s; |
||||
int i; |
||||
int N2; |
||||
int overlap2; |
||||
SAVE_STACK; |
||||
/* Using ALLOC() instead of a regular stack allocation to minimize real stack use when using the pseudostack.
|
||||
This is useful on some embedded systems. */ |
||||
ALLOC(mem_buf, COMBFILTER_MAXPERIOD+960, opus_val32); |
||||
ALLOC(buf, COMBFILTER_MAXPERIOD+960, opus_val32); |
||||
N2 = N/2; |
||||
overlap2=overlap/2; |
||||
/* At 96 kHz, we double the period and the spacing between taps, which is equivalent
|
||||
to creating a mirror image of the filter around 24 kHz. It also means we can process |
||||
the even and odd samples completely independently. */ |
||||
for (s=0;s<2;s++) { |
||||
opus_val32 *yptr; |
||||
for (i=0;i<overlap2;i++) new_window[i] = window[2*i+s]; |
||||
for (i=0;i<COMBFILTER_MAXPERIOD+N2;i++) mem_buf[i] = x[2*i+s-2*COMBFILTER_MAXPERIOD]; |
||||
if (x==y) { |
||||
yptr = mem_buf+COMBFILTER_MAXPERIOD; |
||||
} else { |
||||
for (i=0;i<N2;i++) buf[i] = y[2*i+s]; |
||||
yptr = buf; |
||||
} |
||||
comb_filter(yptr, mem_buf+COMBFILTER_MAXPERIOD, T0, T1, N2, g0, g1, tapset0, tapset1, new_window, overlap2, arch); |
||||
for (i=0;i<N2;i++) y[2*i+s] = yptr[i]; |
||||
} |
||||
RESTORE_STACK; |
||||
return; |
||||
} |
||||
#endif |
||||
|
||||
#ifndef OVERRIDE_comb_filter |
||||
void comb_filter(opus_val32 *y, opus_val32 *x, int T0, int T1, int N, |
||||
opus_val16 g0, opus_val16 g1, int tapset0, int tapset1, |
||||
const celt_coef *window, int overlap, int arch) |
||||
{ |
||||
int i; |
||||
/* printf ("%d %d %f %f\n", T0, T1, g0, g1); */ |
||||
celt_coef g00, g01, g02, g10, g11, g12; |
||||
opus_val32 x0, x1, x2, x3, x4; |
||||
static const opus_val16 gains[3][3] = { |
||||
{QCONST16(0.3066406250f, 15), QCONST16(0.2170410156f, 15), QCONST16(0.1296386719f, 15)}, |
||||
{QCONST16(0.4638671875f, 15), QCONST16(0.2680664062f, 15), QCONST16(0.f, 15)}, |
||||
{QCONST16(0.7998046875f, 15), QCONST16(0.1000976562f, 15), QCONST16(0.f, 15)}}; |
||||
#ifdef ENABLE_QEXT |
||||
if (overlap==240) { |
||||
comb_filter_qext(y, x, T0, T1, N, g0, g1, tapset0, tapset1, window, overlap, arch); |
||||
return; |
||||
} |
||||
#endif |
||||
if (g0==0 && g1==0) |
||||
{ |
||||
/* OPT: Happens to work without the OPUS_MOVE(), but only because the current encoder already copies x to y */ |
||||
if (x!=y) |
||||
OPUS_MOVE(y, x, N); |
||||
return; |
||||
} |
||||
/* When the gain is zero, T0 and/or T1 is set to zero. We need
|
||||
to have then be at least 2 to avoid processing garbage data. */ |
||||
T0 = IMAX(T0, COMBFILTER_MINPERIOD); |
||||
T1 = IMAX(T1, COMBFILTER_MINPERIOD); |
||||
g00 = MULT_COEF_TAPS(g0, gains[tapset0][0]); |
||||
g01 = MULT_COEF_TAPS(g0, gains[tapset0][1]); |
||||
g02 = MULT_COEF_TAPS(g0, gains[tapset0][2]); |
||||
g10 = MULT_COEF_TAPS(g1, gains[tapset1][0]); |
||||
g11 = MULT_COEF_TAPS(g1, gains[tapset1][1]); |
||||
g12 = MULT_COEF_TAPS(g1, gains[tapset1][2]); |
||||
x1 = x[-T1+1]; |
||||
x2 = x[-T1 ]; |
||||
x3 = x[-T1-1]; |
||||
x4 = x[-T1-2]; |
||||
/* If the filter didn't change, we don't need the overlap */ |
||||
if (g0==g1 && T0==T1 && tapset0==tapset1) |
||||
overlap=0; |
||||
for (i=0;i<overlap;i++) |
||||
{ |
||||
celt_coef f; |
||||
x0=x[i-T1+2]; |
||||
f = MULT_COEF(window[i],window[i]); |
||||
y[i] = x[i] |
||||
+ MULT_COEF_32(MULT_COEF((COEF_ONE-f),g00),x[i-T0]) |
||||
+ MULT_COEF_32(MULT_COEF((COEF_ONE-f),g01),ADD32(x[i-T0+1],x[i-T0-1])) |
||||
+ MULT_COEF_32(MULT_COEF((COEF_ONE-f),g02),ADD32(x[i-T0+2],x[i-T0-2])) |
||||
+ MULT_COEF_32(MULT_COEF(f,g10),x2) |
||||
+ MULT_COEF_32(MULT_COEF(f,g11),ADD32(x1,x3)) |
||||
+ MULT_COEF_32(MULT_COEF(f,g12),ADD32(x0,x4)); |
||||
#ifdef FIXED_POINT |
||||
/* A bit of bias seems to help here. */ |
||||
y[i] = SUB32(y[i], 3); |
||||
#endif |
||||
y[i] = SATURATE(y[i], SIG_SAT); |
||||
x4=x3; |
||||
x3=x2; |
||||
x2=x1; |
||||
x1=x0; |
||||
|
||||
} |
||||
if (g1==0) |
||||
{ |
||||
/* OPT: Happens to work without the OPUS_MOVE(), but only because the current encoder already copies x to y */ |
||||
if (x!=y) |
||||
OPUS_MOVE(y+overlap, x+overlap, N-overlap); |
||||
return; |
||||
} |
||||
|
||||
/* Compute the part with the constant filter. */ |
||||
comb_filter_const(y+i, x+i, T1, N-i, g10, g11, g12, arch); |
||||
} |
||||
#endif /* OVERRIDE_comb_filter */ |
||||
|
||||
/* TF change table. Positive values mean better frequency resolution (longer
|
||||
effective window), whereas negative values mean better time resolution |
||||
(shorter effective window). The second index is computed as: |
||||
4*isTransient + 2*tf_select + per_band_flag */ |
||||
const signed char tf_select_table[4][8] = { |
||||
/*isTransient=0 isTransient=1 */ |
||||
{0, -1, 0, -1, 0,-1, 0,-1}, /* 2.5 ms */ |
||||
{0, -1, 0, -2, 1, 0, 1,-1}, /* 5 ms */ |
||||
{0, -2, 0, -3, 2, 0, 1,-1}, /* 10 ms */ |
||||
{0, -2, 0, -3, 3, 0, 1,-1}, /* 20 ms */ |
||||
}; |
||||
|
||||
|
||||
void init_caps(const CELTMode *m,int *cap,int LM,int C) |
||||
{ |
||||
int i; |
||||
for (i=0;i<m->nbEBands;i++) |
||||
{ |
||||
int N; |
||||
N=(m->eBands[i+1]-m->eBands[i])<<LM; |
||||
cap[i] = (m->cache.caps[m->nbEBands*(2*LM+C-1)+i]+64)*C*N>>2; |
||||
} |
||||
} |
||||
|
||||
|
||||
|
||||
const char *opus_strerror(int error) |
||||
{ |
||||
static const char * const error_strings[8] = { |
||||
"success", |
||||
"invalid argument", |
||||
"buffer too small", |
||||
"internal error", |
||||
"corrupted stream", |
||||
"request not implemented", |
||||
"invalid state", |
||||
"memory allocation failed" |
||||
}; |
||||
if (error > 0 || error < -7) |
||||
return "unknown error"; |
||||
else |
||||
return error_strings[-error]; |
||||
} |
||||
|
||||
const char *opus_get_version_string(void) |
||||
{ |
||||
return "libopus " PACKAGE_VERSION |
||||
/* Applications may rely on the presence of this substring in the version
|
||||
string to determine if they have a fixed-point or floating-point build |
||||
at runtime. */ |
||||
#ifdef FIXED_POINT |
||||
"-fixed" |
||||
#endif |
||||
#ifdef FUZZING |
||||
"-fuzzing" |
||||
#endif |
||||
; |
||||
} |
||||
@ -0,0 +1,274 @@
|
||||
/* 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" |
||||
#include "kiss_fft.h" |
||||
|
||||
#ifdef ENABLE_QEXT |
||||
#define ARG_QEXT(arg) , arg |
||||
#else |
||||
#define ARG_QEXT(arg) |
||||
#endif |
||||
|
||||
|
||||
#ifdef ENABLE_DEEP_PLC |
||||
#include "lpcnet.h" |
||||
#endif |
||||
|
||||
#define CELTEncoder OpusCustomEncoder |
||||
#define CELTDecoder OpusCustomDecoder |
||||
#define CELTMode OpusCustomMode |
||||
|
||||
#define QEXT_EXTENSION_ID 124 |
||||
|
||||
#define LEAK_BANDS 19 |
||||
|
||||
typedef struct { |
||||
int valid; |
||||
float tonality; |
||||
float tonality_slope; |
||||
float noisiness; |
||||
float activity; |
||||
float music_prob; |
||||
float music_prob_min; |
||||
float music_prob_max; |
||||
int bandwidth; |
||||
float activity_probability; |
||||
float max_pitch_ratio; |
||||
/* Store as Q6 char to save space. */ |
||||
unsigned char leak_boost[LEAK_BANDS]; |
||||
} AnalysisInfo; |
||||
|
||||
typedef struct { |
||||
int signalType; |
||||
int offset; |
||||
} SILKInfo; |
||||
|
||||
#define celt_check_mode_ptr_ptr(ptr) ((ptr) + ((ptr) - (const CELTMode**)(ptr))) |
||||
|
||||
#define celt_check_analysis_ptr(ptr) ((ptr) + ((ptr) - (const AnalysisInfo*)(ptr))) |
||||
|
||||
#define celt_check_silkinfo_ptr(ptr) ((ptr) + ((ptr) - (const SILKInfo*)(ptr))) |
||||
|
||||
#define celt_check_glog_ptr(ptr) ((ptr) + ((ptr) - (celt_glog*)(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) |
||||
|
||||
#define CELT_SET_TONALITY_REQUEST 10018 |
||||
#define CELT_SET_TONALITY(x) CELT_SET_TONALITY_REQUEST, opus_check_int(x) |
||||
#define CELT_SET_TONALITY_SLOPE_REQUEST 10020 |
||||
#define CELT_SET_TONALITY_SLOPE(x) CELT_SET_TONALITY_SLOPE_REQUEST, opus_check_int(x) |
||||
|
||||
#define CELT_SET_ANALYSIS_REQUEST 10022 |
||||
#define CELT_SET_ANALYSIS(x) CELT_SET_ANALYSIS_REQUEST, celt_check_analysis_ptr(x) |
||||
|
||||
#define OPUS_SET_LFE_REQUEST 10024 |
||||
#define OPUS_SET_LFE(x) OPUS_SET_LFE_REQUEST, opus_check_int(x) |
||||
|
||||
#define OPUS_SET_ENERGY_MASK_REQUEST 10026 |
||||
#define OPUS_SET_ENERGY_MASK(x) OPUS_SET_ENERGY_MASK_REQUEST, celt_check_glog_ptr(x) |
||||
|
||||
#define CELT_SET_SILK_INFO_REQUEST 10028 |
||||
#define CELT_SET_SILK_INFO(x) CELT_SET_SILK_INFO_REQUEST, celt_check_silkinfo_ptr(x) |
||||
|
||||
|
||||
static OPUS_INLINE opus_int32 bits_to_bitrate(opus_int32 bits, opus_int32 Fs, opus_int32 frame_size) { |
||||
return bits*(6*Fs/frame_size)/6; |
||||
} |
||||
|
||||
static OPUS_INLINE opus_int32 bitrate_to_bits(opus_int32 bitrate, opus_int32 Fs, opus_int32 frame_size) { |
||||
return bitrate*6/(6*Fs/frame_size); |
||||
} |
||||
|
||||
/* Encoder stuff */ |
||||
|
||||
int celt_encoder_get_size(int channels); |
||||
|
||||
int celt_encode_with_ec(OpusCustomEncoder * OPUS_RESTRICT st, const opus_res * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes, ec_enc *enc); |
||||
|
||||
int celt_encoder_init(CELTEncoder *st, opus_int32 sampling_rate, int channels, |
||||
int arch); |
||||
|
||||
|
||||
|
||||
/* 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_dred(CELTDecoder * OPUS_RESTRICT st, const unsigned char *data, |
||||
int len, opus_res * OPUS_RESTRICT pcm, int frame_size, ec_dec *dec, int accum |
||||
#ifdef ENABLE_DEEP_PLC |
||||
,LPCNetPLCState *lpcnet |
||||
#endif |
||||
ARG_QEXT(const unsigned char *qext_payload) ARG_QEXT(int qext_payload_len) |
||||
); |
||||
|
||||
int celt_decode_with_ec(OpusCustomDecoder * OPUS_RESTRICT st, const unsigned char *data, |
||||
int len, opus_res * OPUS_RESTRICT pcm, int frame_size, ec_dec *dec, int accum); |
||||
|
||||
#define celt_encoder_ctl opus_custom_encoder_ctl |
||||
#define celt_decoder_ctl opus_custom_decoder_ctl |
||||
|
||||
|
||||
#if defined(CUSTOM_MODES) || defined(ENABLE_OPUS_CUSTOM_API) |
||||
#define OPUS_CUSTOM_NOSTATIC |
||||
#else |
||||
#define OPUS_CUSTOM_NOSTATIC static OPUS_INLINE |
||||
#endif |
||||
|
||||
static const unsigned char trim_icdf[11] = {126, 124, 119, 109, 87, 41, 19, 9, 4, 2, 0}; |
||||
/* Probs: NONE: 21.875%, LIGHT: 6.25%, NORMAL: 65.625%, AGGRESSIVE: 6.25% */ |
||||
static const unsigned char spread_icdf[4] = {25, 23, 2, 0}; |
||||
|
||||
static const unsigned char tapset_icdf[3]={2,1,0}; |
||||
|
||||
#if defined(CUSTOM_MODES) || defined(ENABLE_OPUS_CUSTOM_API) |
||||
static const unsigned char toOpusTable[20] = { |
||||
0xE0, 0xE8, 0xF0, 0xF8, |
||||
0xC0, 0xC8, 0xD0, 0xD8, |
||||
0xA0, 0xA8, 0xB0, 0xB8, |
||||
0x00, 0x00, 0x00, 0x00, |
||||
0x80, 0x88, 0x90, 0x98, |
||||
}; |
||||
|
||||
static const unsigned char fromOpusTable[16] = { |
||||
0x80, 0x88, 0x90, 0x98, |
||||
0x40, 0x48, 0x50, 0x58, |
||||
0x20, 0x28, 0x30, 0x38, |
||||
0x00, 0x08, 0x10, 0x18 |
||||
}; |
||||
|
||||
static OPUS_INLINE int toOpus(unsigned char c) |
||||
{ |
||||
int ret=0; |
||||
if (c<0xA0) |
||||
ret = toOpusTable[c>>3]; |
||||
if (ret == 0) |
||||
return -1; |
||||
else |
||||
return ret|(c&0x7); |
||||
} |
||||
|
||||
static OPUS_INLINE int fromOpus(unsigned char c) |
||||
{ |
||||
if (c<0x80) |
||||
return -1; |
||||
else |
||||
return fromOpusTable[(c>>3)-16] | (c&0x7); |
||||
} |
||||
#endif /* CUSTOM_MODES */ |
||||
|
||||
#define COMBFILTER_MAXPERIOD 1024 |
||||
#define COMBFILTER_MINPERIOD 15 |
||||
|
||||
extern const signed char tf_select_table[4][8]; |
||||
|
||||
#if defined(ENABLE_HARDENING) || defined(ENABLE_ASSERTIONS) |
||||
void validate_celt_decoder(CELTDecoder *st); |
||||
#define VALIDATE_CELT_DECODER(st) validate_celt_decoder(st) |
||||
#else |
||||
#define VALIDATE_CELT_DECODER(st) |
||||
#endif |
||||
|
||||
int resampling_factor(opus_int32 rate); |
||||
|
||||
void celt_preemphasis(const opus_res * OPUS_RESTRICT pcmp, celt_sig * OPUS_RESTRICT inp, |
||||
int N, int CC, int upsample, const opus_val16 *coef, celt_sig *mem, int clip); |
||||
|
||||
void comb_filter(opus_val32 *y, opus_val32 *x, int T0, int T1, int N, |
||||
opus_val16 g0, opus_val16 g1, int tapset0, int tapset1, |
||||
const celt_coef *window, int overlap, int arch); |
||||
|
||||
void init_caps(const CELTMode *m,int *cap,int LM,int C); |
||||
|
||||
#ifdef RESYNTH |
||||
void deemphasis(celt_sig *in[], opus_res *pcm, int N, int C, int downsample, const opus_val16 *coef, celt_sig *mem, int accum); |
||||
void celt_synthesis(const CELTMode *mode, celt_norm *X, celt_sig * out_syn[], |
||||
celt_glog *oldBandE, int start, int effEnd, int C, int CC, int isTransient, |
||||
int LM, int downsample, int silence, int arch ARG_QEXT(const CELTMode *qext_mode) ARG_QEXT(const celt_glog *qext_bandLogE) ARG_QEXT(int qext_end)); |
||||
#endif |
||||
|
||||
#ifdef ENABLE_QEXT |
||||
#define QEXT_SCALE(x) ((qext_scale)*(x)) |
||||
#define QEXT_SCALE2(x, qext_scale) ((qext_scale)*(x)) |
||||
#else |
||||
#define QEXT_SCALE(x) (x) |
||||
#define QEXT_SCALE2(x, qext_scale) (x) |
||||
#endif |
||||
|
||||
#endif /* CELT_H */ |
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,374 @@
|
||||
/* 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" |
||||
#include "pitch.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[CELT_LPC_ORDER]; |
||||
#else |
||||
float *lpc = _lpc; |
||||
#endif |
||||
|
||||
OPUS_CLEAR(lpc, p); |
||||
#ifdef FIXED_POINT |
||||
if (ac[0] != 0) |
||||
#else |
||||
if (ac[0] > 1e-10f) |
||||
#endif |
||||
{ |
||||
for (i = 0; i < p; i++) { |
||||
/* Sum up this iteration's reflection coefficient */ |
||||
opus_val32 rr = 0; |
||||
#if defined (FIXED_POINT) && OPUS_FAST_INT64 |
||||
opus_int64 acc = 0; |
||||
for (j = 0; j < i; j++) |
||||
acc += (opus_int64)(lpc[j]) * (opus_int64)(ac[i - j]); |
||||
rr = (opus_val32)SHR64(acc, 31); |
||||
#else |
||||
for (j = 0; j < i; j++) |
||||
rr += MULT32_32_Q31(lpc[j],ac[i - j]); |
||||
#endif |
||||
rr += SHR32(ac[i + 1],6); |
||||
r = -frac_div32(SHL32(rr,6), error); |
||||
/* Update LPC coefficients and total error */ |
||||
lpc[i] = SHR32(r,6); |
||||
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 |
||||
{ |
||||
/* Convert the int32 lpcs to int16 and ensure there are no wrap-arounds.
|
||||
This reuses the logic in silk_LPC_fit() and silk_bwexpander_32(). Any bug |
||||
fixes should also be applied there. */ |
||||
int iter, idx = 0; |
||||
opus_val32 maxabs, absval, chirp_Q16, chirp_minus_one_Q16; |
||||
|
||||
for (iter = 0; iter < 10; iter++) { |
||||
maxabs = 0; |
||||
for (i = 0; i < p; i++) { |
||||
absval = ABS32(lpc[i]); |
||||
if (absval > maxabs) { |
||||
maxabs = absval; |
||||
idx = i; |
||||
} |
||||
} |
||||
maxabs = PSHR32(maxabs, 13); /* Q25->Q12 */ |
||||
|
||||
if (maxabs > 32767) { |
||||
maxabs = MIN32(maxabs, 163838); |
||||
chirp_Q16 = QCONST32(0.999, 16) - DIV32(SHL32(maxabs - 32767, 14), |
||||
SHR32(MULT32_32_32(maxabs, idx + 1), 2)); |
||||
chirp_minus_one_Q16 = chirp_Q16 - 65536; |
||||
|
||||
/* Apply bandwidth expansion. */ |
||||
for (i = 0; i < p - 1; i++) { |
||||
lpc[i] = MULT32_32_Q16(chirp_Q16, lpc[i]); |
||||
chirp_Q16 += PSHR32(MULT32_32_32(chirp_Q16, chirp_minus_one_Q16), 16); |
||||
} |
||||
lpc[p - 1] = MULT32_32_Q16(chirp_Q16, lpc[p - 1]); |
||||
} else { |
||||
break; |
||||
} |
||||
} |
||||
|
||||
if (iter == 10) { |
||||
/* If the coeffs still do not fit into the 16 bit range after 10 iterations,
|
||||
fall back to the A(z)=1 filter. */ |
||||
OPUS_CLEAR(lpc, p); |
||||
_lpc[0] = 4096; /* Q12 */ |
||||
} else { |
||||
for (i = 0; i < p; i++) { |
||||
_lpc[i] = EXTRACT16(PSHR32(lpc[i], 13)); /* Q25->Q12 */ |
||||
} |
||||
} |
||||
} |
||||
#endif |
||||
} |
||||
|
||||
|
||||
void celt_fir_c( |
||||
const opus_val16 *x, |
||||
const opus_val16 *num, |
||||
opus_val16 *y, |
||||
int N, |
||||
int ord, |
||||
int arch) |
||||
{ |
||||
int i,j; |
||||
VARDECL(opus_val16, rnum); |
||||
SAVE_STACK; |
||||
celt_assert(x != y); |
||||
ALLOC(rnum, ord, opus_val16); |
||||
for(i=0;i<ord;i++) |
||||
rnum[i] = num[ord-i-1]; |
||||
for (i=0;i<N-3;i+=4) |
||||
{ |
||||
opus_val32 sum[4]; |
||||
sum[0] = SHL32(EXTEND32(x[i ]), SIG_SHIFT); |
||||
sum[1] = SHL32(EXTEND32(x[i+1]), SIG_SHIFT); |
||||
sum[2] = SHL32(EXTEND32(x[i+2]), SIG_SHIFT); |
||||
sum[3] = SHL32(EXTEND32(x[i+3]), SIG_SHIFT); |
||||
#if defined(OPUS_CHECK_ASM) && defined(FIXED_POINT) |
||||
{ |
||||
opus_val32 sum_c[4]; |
||||
memcpy(sum_c, sum, sizeof(sum_c)); |
||||
xcorr_kernel_c(rnum, x+i-ord, sum_c, ord); |
||||
#endif |
||||
xcorr_kernel(rnum, x+i-ord, sum, ord, arch); |
||||
#if defined(OPUS_CHECK_ASM) && defined(FIXED_POINT) |
||||
celt_assert(memcmp(sum, sum_c, sizeof(sum)) == 0); |
||||
} |
||||
#endif |
||||
y[i ] = SROUND16(sum[0], SIG_SHIFT); |
||||
y[i+1] = SROUND16(sum[1], SIG_SHIFT); |
||||
y[i+2] = SROUND16(sum[2], SIG_SHIFT); |
||||
y[i+3] = SROUND16(sum[3], SIG_SHIFT); |
||||
} |
||||
for (;i<N;i++) |
||||
{ |
||||
opus_val32 sum = SHL32(EXTEND32(x[i]), SIG_SHIFT); |
||||
for (j=0;j<ord;j++) |
||||
sum = MAC16_16(sum,rnum[j],x[i+j-ord]); |
||||
y[i] = SROUND16(sum, SIG_SHIFT); |
||||
} |
||||
RESTORE_STACK; |
||||
} |
||||
|
||||
void celt_iir(const opus_val32 *_x, |
||||
const opus_val16 *den, |
||||
opus_val32 *_y, |
||||
int N, |
||||
int ord, |
||||
opus_val16 *mem, |
||||
int arch) |
||||
{ |
||||
#ifdef SMALL_FOOTPRINT |
||||
int i,j; |
||||
(void)arch; |
||||
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] = SROUND16(sum, SIG_SHIFT); |
||||
_y[i] = sum; |
||||
} |
||||
#else |
||||
int i,j; |
||||
VARDECL(opus_val16, rden); |
||||
VARDECL(opus_val16, y); |
||||
SAVE_STACK; |
||||
|
||||
celt_assert((ord&3)==0); |
||||
ALLOC(rden, ord, opus_val16); |
||||
ALLOC(y, N+ord, opus_val16); |
||||
for(i=0;i<ord;i++) |
||||
rden[i] = den[ord-i-1]; |
||||
for(i=0;i<ord;i++) |
||||
y[i] = -mem[ord-i-1]; |
||||
for(;i<N+ord;i++) |
||||
y[i]=0; |
||||
for (i=0;i<N-3;i+=4) |
||||
{ |
||||
/* Unroll by 4 as if it were an FIR filter */ |
||||
opus_val32 sum[4]; |
||||
sum[0]=_x[i]; |
||||
sum[1]=_x[i+1]; |
||||
sum[2]=_x[i+2]; |
||||
sum[3]=_x[i+3]; |
||||
#if defined(OPUS_CHECK_ASM) && defined(FIXED_POINT) |
||||
{ |
||||
opus_val32 sum_c[4]; |
||||
memcpy(sum_c, sum, sizeof(sum_c)); |
||||
xcorr_kernel_c(rden, y+i, sum_c, ord); |
||||
#endif |
||||
xcorr_kernel(rden, y+i, sum, ord, arch); |
||||
#if defined(OPUS_CHECK_ASM) && defined(FIXED_POINT) |
||||
celt_assert(memcmp(sum, sum_c, sizeof(sum)) == 0); |
||||
} |
||||
#endif |
||||
/* Patch up the result to compensate for the fact that this is an IIR */ |
||||
y[i+ord ] = -SROUND16(sum[0],SIG_SHIFT); |
||||
_y[i ] = sum[0]; |
||||
sum[1] = MAC16_16(sum[1], y[i+ord ], den[0]); |
||||
y[i+ord+1] = -SROUND16(sum[1],SIG_SHIFT); |
||||
_y[i+1] = sum[1]; |
||||
sum[2] = MAC16_16(sum[2], y[i+ord+1], den[0]); |
||||
sum[2] = MAC16_16(sum[2], y[i+ord ], den[1]); |
||||
y[i+ord+2] = -SROUND16(sum[2],SIG_SHIFT); |
||||
_y[i+2] = sum[2]; |
||||
|
||||
sum[3] = MAC16_16(sum[3], y[i+ord+2], den[0]); |
||||
sum[3] = MAC16_16(sum[3], y[i+ord+1], den[1]); |
||||
sum[3] = MAC16_16(sum[3], y[i+ord ], den[2]); |
||||
y[i+ord+3] = -SROUND16(sum[3],SIG_SHIFT); |
||||
_y[i+3] = sum[3]; |
||||
} |
||||
for (;i<N;i++) |
||||
{ |
||||
opus_val32 sum = _x[i]; |
||||
for (j=0;j<ord;j++) |
||||
sum -= MULT16_16(rden[j],y[i+j]); |
||||
y[i+ord] = SROUND16(sum,SIG_SHIFT); |
||||
_y[i] = sum; |
||||
} |
||||
for(i=0;i<ord;i++) |
||||
mem[i] = _y[N-i-1]; |
||||
RESTORE_STACK; |
||||
#endif |
||||
} |
||||
|
||||
int _celt_autocorr( |
||||
const opus_val16 *x, /* in: [0...n-1] samples x */ |
||||
opus_val32 *ac, /* out: [0...lag-1] ac values */ |
||||
const celt_coef *window, |
||||
int overlap, |
||||
int lag, |
||||
int n, |
||||
int arch |
||||
) |
||||
{ |
||||
opus_val32 d; |
||||
int i, k; |
||||
int fastN=n-lag; |
||||
int shift; |
||||
const opus_val16 *xptr; |
||||
VARDECL(opus_val16, xx); |
||||
SAVE_STACK; |
||||
ALLOC(xx, n, opus_val16); |
||||
celt_assert(n>0); |
||||
celt_assert(overlap>=0); |
||||
if (overlap == 0) |
||||
{ |
||||
xptr = x; |
||||
} else { |
||||
for (i=0;i<n;i++) |
||||
xx[i] = x[i]; |
||||
for (i=0;i<overlap;i++) |
||||
{ |
||||
opus_val16 w = COEF2VAL16(window[i]); |
||||
xx[i] = MULT16_16_Q15(x[i],w); |
||||
xx[n-i-1] = MULT16_16_Q15(x[n-i-1],w); |
||||
} |
||||
xptr = xx; |
||||
} |
||||
shift=0; |
||||
#ifdef FIXED_POINT |
||||
{ |
||||
opus_val32 ac0; |
||||
int ac0_shift = celt_ilog2(n + (n>>4)); |
||||
ac0 = 1+(n<<7); |
||||
if (n&1) ac0 += SHR32(MULT16_16(xptr[0],xptr[0]),ac0_shift); |
||||
for(i=(n&1);i<n;i+=2) |
||||
{ |
||||
ac0 += SHR32(MULT16_16(xptr[i],xptr[i]),ac0_shift); |
||||
ac0 += SHR32(MULT16_16(xptr[i+1],xptr[i+1]),ac0_shift); |
||||
} |
||||
/* Consider the effect of rounding-to-nearest when scaling the signal. */ |
||||
ac0 += SHR32(ac0,7); |
||||
|
||||
shift = celt_ilog2(ac0)-30+ac0_shift+1; |
||||
shift = (shift)/2; |
||||
if (shift>0) |
||||
{ |
||||
for(i=0;i<n;i++) |
||||
xx[i] = PSHR32(xptr[i], shift); |
||||
xptr = xx; |
||||
} else |
||||
shift = 0; |
||||
} |
||||
#endif |
||||
celt_pitch_xcorr(xptr, xptr, ac, fastN, lag+1, arch); |
||||
for (k=0;k<=lag;k++) |
||||
{ |
||||
for (i = k+fastN, d = 0; i < n; i++) |
||||
d = MAC16_16(d, xptr[i], xptr[i-k]); |
||||
ac[k] += d; |
||||
} |
||||
#ifdef FIXED_POINT |
||||
shift = 2*shift; |
||||
if (shift<=0) |
||||
ac[0] += SHL32((opus_int32)1, -shift); |
||||
if (ac[0] < 268435456) |
||||
{ |
||||
int shift2 = 29 - EC_ILOG(ac[0]); |
||||
for (i=0;i<=lag;i++) |
||||
ac[i] = SHL32(ac[i], shift2); |
||||
shift -= shift2; |
||||
} else if (ac[0] >= 536870912) |
||||
{ |
||||
int shift2=1; |
||||
if (ac[0] >= 1073741824) |
||||
shift2++; |
||||
for (i=0;i<=lag;i++) |
||||
ac[i] = SHR32(ac[i], shift2); |
||||
shift += shift2; |
||||
} |
||||
#endif |
||||
|
||||
RESTORE_STACK; |
||||
return shift; |
||||
} |
||||
@ -0,0 +1,66 @@
|
||||
/* 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 CELT_LPC_H |
||||
#define CELT_LPC_H |
||||
|
||||
#include "arch.h" |
||||
#include "cpu_support.h" |
||||
|
||||
#if defined(OPUS_X86_MAY_HAVE_SSE4_1) |
||||
#include "x86/celt_lpc_sse.h" |
||||
#endif |
||||
|
||||
#define CELT_LPC_ORDER 24 |
||||
|
||||
void _celt_lpc(opus_val16 *_lpc, const opus_val32 *ac, int p); |
||||
|
||||
void celt_fir_c( |
||||
const opus_val16 *x, |
||||
const opus_val16 *num, |
||||
opus_val16 *y, |
||||
int N, |
||||
int ord, |
||||
int arch); |
||||
|
||||
#if !defined(OVERRIDE_CELT_FIR) |
||||
#define celt_fir(x, num, y, N, ord, arch) \ |
||||
(celt_fir_c(x, num, y, N, ord, arch)) |
||||
#endif |
||||
|
||||
void celt_iir(const opus_val32 *x, |
||||
const opus_val16 *den, |
||||
opus_val32 *y, |
||||
int N, |
||||
int ord, |
||||
opus_val16 *mem, |
||||
int arch); |
||||
|
||||
int _celt_autocorr(const opus_val16 *x, opus_val32 *ac, |
||||
const celt_coef *window, int overlap, int lag, int n, int arch); |
||||
|
||||
#endif /* CELT_LPC_H */ |
||||
@ -0,0 +1,72 @@
|
||||
/* Copyright (c) 2010 Xiph.Org Foundation
|
||||
* Copyright (c) 2013 Parrot */ |
||||
/*
|
||||
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 CPU_SUPPORT_H |
||||
#define CPU_SUPPORT_H |
||||
|
||||
#include "opus_types.h" |
||||
#include "opus_defines.h" |
||||
|
||||
#if defined(OPUS_HAVE_RTCD) && \ |
||||
(defined(OPUS_ARM_ASM) || defined(OPUS_ARM_MAY_HAVE_NEON_INTR)) |
||||
#include "arm/armcpu.h" |
||||
|
||||
/* We currently support 5 ARM variants:
|
||||
* arch[0] -> ARMv4 |
||||
* arch[1] -> ARMv5E |
||||
* arch[2] -> ARMv6 |
||||
* arch[3] -> NEON |
||||
* arch[4] -> NEON+DOTPROD |
||||
*/ |
||||
#define OPUS_ARCHMASK 7 |
||||
|
||||
#elif defined(OPUS_HAVE_RTCD) && \ |
||||
((defined(OPUS_X86_MAY_HAVE_SSE) && !defined(OPUS_X86_PRESUME_SSE)) || \
|
||||
(defined(OPUS_X86_MAY_HAVE_SSE2) && !defined(OPUS_X86_PRESUME_SSE2)) || \
|
||||
(defined(OPUS_X86_MAY_HAVE_SSE4_1) && !defined(OPUS_X86_PRESUME_SSE4_1)) || \
|
||||
(defined(OPUS_X86_MAY_HAVE_AVX2) && !defined(OPUS_X86_PRESUME_AVX2))) |
||||
|
||||
#include "x86/x86cpu.h" |
||||
/* We currently support 5 x86 variants:
|
||||
* arch[0] -> non-sse |
||||
* arch[1] -> sse |
||||
* arch[2] -> sse2 |
||||
* arch[3] -> sse4.1 |
||||
* arch[4] -> avx |
||||
*/ |
||||
#define OPUS_ARCHMASK 7 |
||||
int opus_select_arch(void); |
||||
|
||||
#else |
||||
#define OPUS_ARCHMASK 0 |
||||
|
||||
static OPUS_INLINE int opus_select_arch(void) |
||||
{ |
||||
return 0; |
||||
} |
||||
#endif |
||||
#endif |
||||
@ -0,0 +1,719 @@
|
||||
/* 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" |
||||
|
||||
#if defined(CUSTOM_MODES) || defined(ENABLE_QEXT) |
||||
#define CWRS_EXTRA_ROWS |
||||
#endif |
||||
|
||||
#if defined(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 |
||||
|
||||
/*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 |
||||
https://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 |
||||
}*/ |
||||
|
||||
#if !defined(SMALL_FOOTPRINT) |
||||
|
||||
/*U(N,K) = U(K,N) := N>0?K>0?U(N-1,K)+U(N,K-1)+U(N-1,K-1):0:K>0?1:0*/ |
||||
# define CELT_PVQ_U(_n,_k) (CELT_PVQ_U_ROW[IMIN(_n,_k)][IMAX(_n,_k)]) |
||||
/*V(N,K) := U(N,K)+U(N,K+1) = the number of PVQ codewords for a band of size N
|
||||
with K pulses allocated to it.*/ |
||||
# define CELT_PVQ_V(_n,_k) (CELT_PVQ_U(_n,_k)+CELT_PVQ_U(_n,(_k)+1)) |
||||
|
||||
/*For each V(N,K) supported, we will access element U(min(N,K+1),max(N,K+1)).
|
||||
Thus, the number of entries in row I is the larger of the maximum number of |
||||
pulses we will ever allocate for a given N=I (K=128, or however many fit in |
||||
32 bits, whichever is smaller), plus one, and the maximum N for which |
||||
K=I-1 pulses fit in 32 bits. |
||||
The largest band size in an Opus Custom mode is 208. |
||||
Otherwise, we can limit things to the set of N which can be achieved by |
||||
splitting a band from a standard Opus mode: 176, 144, 96, 88, 72, 64, 48, |
||||
44, 36, 32, 24, 22, 18, 16, 8, 4, 2).*/ |
||||
#if defined(CWRS_EXTRA_ROWS) |
||||
static const opus_uint32 CELT_PVQ_U_DATA[1488]={ |
||||
#else |
||||
static const opus_uint32 CELT_PVQ_U_DATA[1272]={ |
||||
#endif |
||||
/*N=0, K=0...176:*/ |
||||
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
||||
#if defined(CWRS_EXTRA_ROWS) |
||||
/*...208:*/ |
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
||||
0, 0, 0, 0, 0, 0, |
||||
#endif |
||||
/*N=1, K=1...176:*/ |
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
||||
#if defined(CWRS_EXTRA_ROWS) |
||||
/*...208:*/ |
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
||||
1, 1, 1, 1, 1, 1, |
||||
#endif |
||||
/*N=2, K=2...176:*/ |
||||
3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, |
||||
43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63, 65, 67, 69, 71, 73, 75, 77, 79, |
||||
81, 83, 85, 87, 89, 91, 93, 95, 97, 99, 101, 103, 105, 107, 109, 111, 113, |
||||
115, 117, 119, 121, 123, 125, 127, 129, 131, 133, 135, 137, 139, 141, 143, |
||||
145, 147, 149, 151, 153, 155, 157, 159, 161, 163, 165, 167, 169, 171, 173, |
||||
175, 177, 179, 181, 183, 185, 187, 189, 191, 193, 195, 197, 199, 201, 203, |
||||
205, 207, 209, 211, 213, 215, 217, 219, 221, 223, 225, 227, 229, 231, 233, |
||||
235, 237, 239, 241, 243, 245, 247, 249, 251, 253, 255, 257, 259, 261, 263, |
||||
265, 267, 269, 271, 273, 275, 277, 279, 281, 283, 285, 287, 289, 291, 293, |
||||
295, 297, 299, 301, 303, 305, 307, 309, 311, 313, 315, 317, 319, 321, 323, |
||||
325, 327, 329, 331, 333, 335, 337, 339, 341, 343, 345, 347, 349, 351, |
||||
#if defined(CWRS_EXTRA_ROWS) |
||||
/*...208:*/ |
||||
353, 355, 357, 359, 361, 363, 365, 367, 369, 371, 373, 375, 377, 379, 381, |
||||
383, 385, 387, 389, 391, 393, 395, 397, 399, 401, 403, 405, 407, 409, 411, |
||||
413, 415, |
||||
#endif |
||||
/*N=3, K=3...176:*/ |
||||
13, 25, 41, 61, 85, 113, 145, 181, 221, 265, 313, 365, 421, 481, 545, 613, |
||||
685, 761, 841, 925, 1013, 1105, 1201, 1301, 1405, 1513, 1625, 1741, 1861, |
||||
1985, 2113, 2245, 2381, 2521, 2665, 2813, 2965, 3121, 3281, 3445, 3613, 3785, |
||||
3961, 4141, 4325, 4513, 4705, 4901, 5101, 5305, 5513, 5725, 5941, 6161, 6385, |
||||
6613, 6845, 7081, 7321, 7565, 7813, 8065, 8321, 8581, 8845, 9113, 9385, 9661, |
||||
9941, 10225, 10513, 10805, 11101, 11401, 11705, 12013, 12325, 12641, 12961, |
||||
13285, 13613, 13945, 14281, 14621, 14965, 15313, 15665, 16021, 16381, 16745, |
||||
17113, 17485, 17861, 18241, 18625, 19013, 19405, 19801, 20201, 20605, 21013, |
||||
21425, 21841, 22261, 22685, 23113, 23545, 23981, 24421, 24865, 25313, 25765, |
||||
26221, 26681, 27145, 27613, 28085, 28561, 29041, 29525, 30013, 30505, 31001, |
||||
31501, 32005, 32513, 33025, 33541, 34061, 34585, 35113, 35645, 36181, 36721, |
||||
37265, 37813, 38365, 38921, 39481, 40045, 40613, 41185, 41761, 42341, 42925, |
||||
43513, 44105, 44701, 45301, 45905, 46513, 47125, 47741, 48361, 48985, 49613, |
||||
50245, 50881, 51521, 52165, 52813, 53465, 54121, 54781, 55445, 56113, 56785, |
||||
57461, 58141, 58825, 59513, 60205, 60901, 61601, |
||||
#if defined(CWRS_EXTRA_ROWS) |
||||
/*...208:*/ |
||||
62305, 63013, 63725, 64441, 65161, 65885, 66613, 67345, 68081, 68821, 69565, |
||||
70313, 71065, 71821, 72581, 73345, 74113, 74885, 75661, 76441, 77225, 78013, |
||||
78805, 79601, 80401, 81205, 82013, 82825, 83641, 84461, 85285, 86113, |
||||
#endif |
||||
/*N=4, K=4...176:*/ |
||||
63, 129, 231, 377, 575, 833, 1159, 1561, 2047, 2625, 3303, 4089, 4991, 6017, |
||||
7175, 8473, 9919, 11521, 13287, 15225, 17343, 19649, 22151, 24857, 27775, |
||||
30913, 34279, 37881, 41727, 45825, 50183, 54809, 59711, 64897, 70375, 76153, |
||||
82239, 88641, 95367, 102425, 109823, 117569, 125671, 134137, 142975, 152193, |
||||
161799, 171801, 182207, 193025, 204263, 215929, 228031, 240577, 253575, |
||||
267033, 280959, 295361, 310247, 325625, 341503, 357889, 374791, 392217, |
||||
410175, 428673, 447719, 467321, 487487, 508225, 529543, 551449, 573951, |
||||
597057, 620775, 645113, 670079, 695681, 721927, 748825, 776383, 804609, |
||||
833511, 863097, 893375, 924353, 956039, 988441, 1021567, 1055425, 1090023, |
||||
1125369, 1161471, 1198337, 1235975, 1274393, 1313599, 1353601, 1394407, |
||||
1436025, 1478463, 1521729, 1565831, 1610777, 1656575, 1703233, 1750759, |
||||
1799161, 1848447, 1898625, 1949703, 2001689, 2054591, 2108417, 2163175, |
||||
2218873, 2275519, 2333121, 2391687, 2451225, 2511743, 2573249, 2635751, |
||||
2699257, 2763775, 2829313, 2895879, 2963481, 3032127, 3101825, 3172583, |
||||
3244409, 3317311, 3391297, 3466375, 3542553, 3619839, 3698241, 3777767, |
||||
3858425, 3940223, 4023169, 4107271, 4192537, 4278975, 4366593, 4455399, |
||||
4545401, 4636607, 4729025, 4822663, 4917529, 5013631, 5110977, 5209575, |
||||
5309433, 5410559, 5512961, 5616647, 5721625, 5827903, 5935489, 6044391, |
||||
6154617, 6266175, 6379073, 6493319, 6608921, 6725887, 6844225, 6963943, |
||||
7085049, 7207551, |
||||
#if defined(CWRS_EXTRA_ROWS) |
||||
/*...208:*/ |
||||
7331457, 7456775, 7583513, 7711679, 7841281, 7972327, 8104825, 8238783, |
||||
8374209, 8511111, 8649497, 8789375, 8930753, 9073639, 9218041, 9363967, |
||||
9511425, 9660423, 9810969, 9963071, 10116737, 10271975, 10428793, 10587199, |
||||
10747201, 10908807, 11072025, 11236863, 11403329, 11571431, 11741177, |
||||
11912575, |
||||
#endif |
||||
/*N=5, K=5...176:*/ |
||||
321, 681, 1289, 2241, 3649, 5641, 8361, 11969, 16641, 22569, 29961, 39041, |
||||
50049, 63241, 78889, 97281, 118721, 143529, 172041, 204609, 241601, 283401, |
||||
330409, 383041, 441729, 506921, 579081, 658689, 746241, 842249, 947241, |
||||
1061761, 1186369, 1321641, 1468169, 1626561, 1797441, 1981449, 2179241, |
||||
2391489, 2618881, 2862121, 3121929, 3399041, 3694209, 4008201, 4341801, |
||||
4695809, 5071041, 5468329, 5888521, 6332481, 6801089, 7295241, 7815849, |
||||
8363841, 8940161, 9545769, 10181641, 10848769, 11548161, 12280841, 13047849, |
||||
13850241, 14689089, 15565481, 16480521, 17435329, 18431041, 19468809, |
||||
20549801, 21675201, 22846209, 24064041, 25329929, 26645121, 28010881, |
||||
29428489, 30899241, 32424449, 34005441, 35643561, 37340169, 39096641, |
||||
40914369, 42794761, 44739241, 46749249, 48826241, 50971689, 53187081, |
||||
55473921, 57833729, 60268041, 62778409, 65366401, 68033601, 70781609, |
||||
73612041, 76526529, 79526721, 82614281, 85790889, 89058241, 92418049, |
||||
95872041, 99421961, 103069569, 106816641, 110664969, 114616361, 118672641, |
||||
122835649, 127107241, 131489289, 135983681, 140592321, 145317129, 150160041, |
||||
155123009, 160208001, 165417001, 170752009, 176215041, 181808129, 187533321, |
||||
193392681, 199388289, 205522241, 211796649, 218213641, 224775361, 231483969, |
||||
238341641, 245350569, 252512961, 259831041, 267307049, 274943241, 282741889, |
||||
290705281, 298835721, 307135529, 315607041, 324252609, 333074601, 342075401, |
||||
351257409, 360623041, 370174729, 379914921, 389846081, 399970689, 410291241, |
||||
420810249, 431530241, 442453761, 453583369, 464921641, 476471169, 488234561, |
||||
500214441, 512413449, 524834241, 537479489, 550351881, 563454121, 576788929, |
||||
590359041, 604167209, 618216201, 632508801, |
||||
#if defined(CWRS_EXTRA_ROWS) |
||||
/*...208:*/ |
||||
647047809, 661836041, 676876329, 692171521, 707724481, 723538089, 739615241, |
||||
755958849, 772571841, 789457161, 806617769, 824056641, 841776769, 859781161, |
||||
878072841, 896654849, 915530241, 934702089, 954173481, 973947521, 994027329, |
||||
1014416041, 1035116809, 1056132801, 1077467201, 1099123209, 1121104041, |
||||
1143412929, 1166053121, 1189027881, 1212340489, 1235994241, |
||||
#endif |
||||
/*N=6, K=6...96:*/ |
||||
1683, 3653, 7183, 13073, 22363, 36365, 56695, 85305, 124515, 177045, 246047, |
||||
335137, 448427, 590557, 766727, 982729, 1244979, 1560549, 1937199, 2383409, |
||||
2908411, 3522221, 4235671, 5060441, 6009091, 7095093, 8332863, 9737793, |
||||
11326283, 13115773, 15124775, 17372905, 19880915, 22670725, 25765455, |
||||
29189457, 32968347, 37129037, 41699767, 46710137, 52191139, 58175189, |
||||
64696159, 71789409, 79491819, 87841821, 96879431, 106646281, 117185651, |
||||
128542501, 140763503, 153897073, 167993403, 183104493, 199284183, 216588185, |
||||
235074115, 254801525, 275831935, 298228865, 322057867, 347386557, 374284647, |
||||
402823977, 433078547, 465124549, 499040399, 534906769, 572806619, 612825229, |
||||
655050231, 699571641, 746481891, 795875861, 847850911, 902506913, 959946283, |
||||
1020274013, 1083597703, 1150027593, 1219676595, 1292660325, 1369097135, |
||||
1449108145, 1532817275, 1620351277, 1711839767, 1807415257, 1907213187, |
||||
2011371957, 2120032959, |
||||
#if defined(CWRS_EXTRA_ROWS) |
||||
/*...109:*/ |
||||
2233340609U, 2351442379U, 2474488829U, 2602633639U, 2736033641U, 2874848851U, |
||||
3019242501U, 3169381071U, 3325434321U, 3487575323U, 3655980493U, 3830829623U, |
||||
4012305913U, |
||||
#endif |
||||
/*N=7, K=7...54*/ |
||||
8989, 19825, 40081, 75517, 134245, 227305, 369305, 579125, 880685, 1303777, |
||||
1884961, 2668525, 3707509, 5064793, 6814249, 9041957, 11847485, 15345233, |
||||
19665841, 24957661, 31388293, 39146185, 48442297, 59511829, 72616013, |
||||
88043969, 106114625, 127178701, 151620757, 179861305, 212358985, 249612805, |
||||
292164445, 340600625, 395555537, 457713341, 527810725, 606639529, 695049433, |
||||
793950709, 904317037, 1027188385, 1163673953, 1314955181, 1482288821, |
||||
1667010073, 1870535785, 2094367717, |
||||
#if defined(CWRS_EXTRA_ROWS) |
||||
/*...60:*/ |
||||
2340095869U, 2609401873U, 2904062449U, 3225952925U, 3577050821U, 3959439497U, |
||||
#endif |
||||
/*N=8, K=8...37*/ |
||||
48639, 108545, 224143, 433905, 795455, 1392065, 2340495, 3800305, 5984767, |
||||
9173505, 13726991, 20103025, 28875327, 40754369, 56610575, 77500017, |
||||
104692735, 139703809, 184327311, 240673265, 311207743, 398796225, 506750351, |
||||
638878193, 799538175, 993696769, 1226990095, 1505789553, 1837271615, |
||||
2229491905U, |
||||
#if defined(CWRS_EXTRA_ROWS) |
||||
/*...40:*/ |
||||
2691463695U, 3233240945U, 3866006015U, |
||||
#endif |
||||
/*N=9, K=9...28:*/ |
||||
265729, 598417, 1256465, 2485825, 4673345, 8405905, 14546705, 24331777, |
||||
39490049, 62390545, 96220561, 145198913, 214828609, 312193553, 446304145, |
||||
628496897, 872893441, 1196924561, 1621925137, 2173806145U, |
||||
#if defined(CWRS_EXTRA_ROWS) |
||||
/*...29:*/ |
||||
2883810113U, |
||||
#endif |
||||
/*N=10, K=10...24:*/ |
||||
1462563, 3317445, 7059735, 14218905, 27298155, 50250765, 89129247, 152951073, |
||||
254831667, 413442773, 654862247, 1014889769, 1541911931, 2300409629U, |
||||
3375210671U, |
||||
/*N=11, K=11...19:*/ |
||||
8097453, 18474633, 39753273, 81270333, 158819253, 298199265, 540279585, |
||||
948062325, 1616336765, |
||||
#if defined(CWRS_EXTRA_ROWS) |
||||
/*...20:*/ |
||||
2684641785U, |
||||
#endif |
||||
/*N=12, K=12...18:*/ |
||||
45046719, 103274625, 224298231, 464387817, 921406335, 1759885185, |
||||
3248227095U, |
||||
/*N=13, K=13...16:*/ |
||||
251595969, 579168825, 1267854873, 2653649025U, |
||||
/*N=14, K=14:*/ |
||||
1409933619 |
||||
}; |
||||
|
||||
#if defined(CWRS_EXTRA_ROWS) |
||||
static const opus_uint32 *const CELT_PVQ_U_ROW[15]={ |
||||
CELT_PVQ_U_DATA+ 0,CELT_PVQ_U_DATA+ 208,CELT_PVQ_U_DATA+ 415, |
||||
CELT_PVQ_U_DATA+ 621,CELT_PVQ_U_DATA+ 826,CELT_PVQ_U_DATA+1030, |
||||
CELT_PVQ_U_DATA+1233,CELT_PVQ_U_DATA+1336,CELT_PVQ_U_DATA+1389, |
||||
CELT_PVQ_U_DATA+1421,CELT_PVQ_U_DATA+1441,CELT_PVQ_U_DATA+1455, |
||||
CELT_PVQ_U_DATA+1464,CELT_PVQ_U_DATA+1470,CELT_PVQ_U_DATA+1473 |
||||
}; |
||||
#else |
||||
static const opus_uint32 *const CELT_PVQ_U_ROW[15]={ |
||||
CELT_PVQ_U_DATA+ 0,CELT_PVQ_U_DATA+ 176,CELT_PVQ_U_DATA+ 351, |
||||
CELT_PVQ_U_DATA+ 525,CELT_PVQ_U_DATA+ 698,CELT_PVQ_U_DATA+ 870, |
||||
CELT_PVQ_U_DATA+1041,CELT_PVQ_U_DATA+1131,CELT_PVQ_U_DATA+1178, |
||||
CELT_PVQ_U_DATA+1207,CELT_PVQ_U_DATA+1226,CELT_PVQ_U_DATA+1240, |
||||
CELT_PVQ_U_DATA+1248,CELT_PVQ_U_DATA+1254,CELT_PVQ_U_DATA+1257 |
||||
}; |
||||
#endif |
||||
|
||||
#if defined(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; |
||||
for(k=1;k<=_maxk;k++)_bits[k]=log2_frac(CELT_PVQ_V(_n,k),_frac); |
||||
} |
||||
#endif |
||||
|
||||
static opus_uint32 icwrs(int _n,const int *_y){ |
||||
opus_uint32 i; |
||||
int j; |
||||
int k; |
||||
celt_assert(_n>=2); |
||||
j=_n-1; |
||||
i=_y[j]<0; |
||||
k=abs(_y[j]); |
||||
do{ |
||||
j--; |
||||
i+=CELT_PVQ_U(_n-j,k); |
||||
k+=abs(_y[j]); |
||||
if(_y[j]<0)i+=CELT_PVQ_U(_n-j,k+1); |
||||
} |
||||
while(j>0); |
||||
return i; |
||||
} |
||||
|
||||
void encode_pulses(const int *_y,int _n,int _k,ec_enc *_enc){ |
||||
celt_assert(_k>0); |
||||
ec_enc_uint(_enc,icwrs(_n,_y),CELT_PVQ_V(_n,_k)); |
||||
} |
||||
|
||||
static opus_val32 cwrsi(int _n,int _k,opus_uint32 _i,int *_y){ |
||||
opus_uint32 p; |
||||
int s; |
||||
int k0; |
||||
opus_int16 val; |
||||
opus_val32 yy=0; |
||||
celt_assert(_k>0); |
||||
celt_assert(_n>1); |
||||
while(_n>2){ |
||||
opus_uint32 q; |
||||
/*Lots of pulses case:*/ |
||||
if(_k>=_n){ |
||||
const opus_uint32 *row; |
||||
row=CELT_PVQ_U_ROW[_n]; |
||||
/*Are the pulses in this dimension negative?*/ |
||||
p=row[_k+1]; |
||||
s=-(_i>=p); |
||||
_i-=p&s; |
||||
/*Count how many pulses were placed in this dimension.*/ |
||||
k0=_k; |
||||
q=row[_n]; |
||||
if(q>_i){ |
||||
celt_sig_assert(p>q); |
||||
_k=_n; |
||||
do p=CELT_PVQ_U_ROW[--_k][_n]; |
||||
while(p>_i); |
||||
} |
||||
else for(p=row[_k];p>_i;p=row[_k])_k--; |
||||
_i-=p; |
||||
val=(k0-_k+s)^s; |
||||
*_y++=val; |
||||
yy=MAC16_16(yy,val,val); |
||||
} |
||||
/*Lots of dimensions case:*/ |
||||
else{ |
||||
/*Are there any pulses in this dimension at all?*/ |
||||
p=CELT_PVQ_U_ROW[_k][_n]; |
||||
q=CELT_PVQ_U_ROW[_k+1][_n]; |
||||
if(p<=_i&&_i<q){ |
||||
_i-=p; |
||||
*_y++=0; |
||||
} |
||||
else{ |
||||
/*Are the pulses in this dimension negative?*/ |
||||
s=-(_i>=q); |
||||
_i-=q&s; |
||||
/*Count how many pulses were placed in this dimension.*/ |
||||
k0=_k; |
||||
do p=CELT_PVQ_U_ROW[--_k][_n]; |
||||
while(p>_i); |
||||
_i-=p; |
||||
val=(k0-_k+s)^s; |
||||
*_y++=val; |
||||
yy=MAC16_16(yy,val,val); |
||||
} |
||||
} |
||||
_n--; |
||||
} |
||||
/*_n==2*/ |
||||
p=2*_k+1; |
||||
s=-(_i>=p); |
||||
_i-=p&s; |
||||
k0=_k; |
||||
_k=(_i+1)>>1; |
||||
if(_k)_i-=2*_k-1; |
||||
val=(k0-_k+s)^s; |
||||
*_y++=val; |
||||
yy=MAC16_16(yy,val,val); |
||||
/*_n==1*/ |
||||
s=-(int)_i; |
||||
val=(_k+s)^s; |
||||
*_y=val; |
||||
yy=MAC16_16(yy,val,val); |
||||
return yy; |
||||
} |
||||
|
||||
opus_val32 decode_pulses(int *_y,int _n,int _k,ec_dec *_dec){ |
||||
return cwrsi(_n,_k,ec_dec_uint(_dec,CELT_PVQ_V(_n,_k)),_y); |
||||
} |
||||
|
||||
#else /* 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 OPUS_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 OPUS_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; |
||||
/*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); |
||||
return _u[_k]+_u[_k+1]; |
||||
} |
||||
|
||||
/*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 opus_val32 cwrsi(int _n,int _k,opus_uint32 _i,int *_y,opus_uint32 *_u){ |
||||
int j; |
||||
opus_int16 val; |
||||
opus_val32 yy=0; |
||||
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; |
||||
val=(yj+s)^s; |
||||
_y[j]=val; |
||||
yy=MAC16_16(yy,val,val); |
||||
uprev(_u,_k+2,0); |
||||
} |
||||
while(++j<_n); |
||||
return yy; |
||||
} |
||||
|
||||
/*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 OPUS_INLINE opus_uint32 icwrs1(const int *_y,int *_k){ |
||||
*_k=abs(_y[0]); |
||||
return _y[0]<0; |
||||
} |
||||
|
||||
/*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 OPUS_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; |
||||
} |
||||
|
||||
#if defined(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; |
||||
VARDECL(opus_uint32,u); |
||||
opus_uint32 nc; |
||||
SAVE_STACK; |
||||
celt_assert(_k>0); |
||||
ALLOC(u,_k+2U,opus_uint32); |
||||
i=icwrs(_n,_k,&nc,_y,u); |
||||
ec_enc_uint(_enc,i,nc); |
||||
RESTORE_STACK; |
||||
} |
||||
|
||||
opus_val32 decode_pulses(int *_y,int _n,int _k,ec_dec *_dec){ |
||||
VARDECL(opus_uint32,u); |
||||
int ret; |
||||
SAVE_STACK; |
||||
celt_assert(_k>0); |
||||
ALLOC(u,_k+2U,opus_uint32); |
||||
ret = cwrsi(_n,_k,ec_dec_uint(_dec,ncwrs_urow(_n,_k,u)),_y,u); |
||||
RESTORE_STACK; |
||||
return ret; |
||||
} |
||||
|
||||
#endif /* SMALL_FOOTPRINT */ |
||||
@ -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); |
||||
|
||||
opus_val32 decode_pulses(int *_y, int N, int K, ec_dec *dec); |
||||
|
||||
#endif /* CWRS_H */ |
||||
@ -0,0 +1,91 @@
|
||||
/* 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 OPUS_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) |
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1910) |
||||
# include <intrin0.h> /* Improve compiler throughput. */ |
||||
#else |
||||
# include <intrin.h> |
||||
#endif |
||||
/*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,153 @@
|
||||
/* 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 |
||||
|
||||
#if 1 |
||||
/* This is a faster version of ec_tell_frac() that takes advantage
|
||||
of the low (1/8 bit) resolution to use just a linear function |
||||
followed by a lookup to determine the exact transition thresholds. */ |
||||
opus_uint32 ec_tell_frac(ec_ctx *_this){ |
||||
static const unsigned correction[8] = |
||||
{35733, 38967, 42495, 46340, |
||||
50535, 55109, 60097, 65535}; |
||||
opus_uint32 nbits; |
||||
opus_uint32 r; |
||||
int l; |
||||
unsigned b; |
||||
nbits=_this->nbits_total<<BITRES; |
||||
l=EC_ILOG(_this->rng); |
||||
r=_this->rng>>(l-16); |
||||
b = (r>>12)-8; |
||||
b += r>correction[b]; |
||||
l = (l<<3)+b; |
||||
return nbits-l; |
||||
} |
||||
#else |
||||
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; |
||||
} |
||||
#endif |
||||
|
||||
#ifdef USE_SMALL_DIV_TABLE |
||||
/* Result of 2^32/(2*i+1), except for i=0. */ |
||||
const opus_uint32 SMALL_DIV_TABLE[129] = { |
||||
0xFFFFFFFF, 0x55555555, 0x33333333, 0x24924924, |
||||
0x1C71C71C, 0x1745D174, 0x13B13B13, 0x11111111, |
||||
0x0F0F0F0F, 0x0D79435E, 0x0C30C30C, 0x0B21642C, |
||||
0x0A3D70A3, 0x097B425E, 0x08D3DCB0, 0x08421084, |
||||
0x07C1F07C, 0x07507507, 0x06EB3E45, 0x06906906, |
||||
0x063E7063, 0x05F417D0, 0x05B05B05, 0x0572620A, |
||||
0x05397829, 0x05050505, 0x04D4873E, 0x04A7904A, |
||||
0x047DC11F, 0x0456C797, 0x04325C53, 0x04104104, |
||||
0x03F03F03, 0x03D22635, 0x03B5CC0E, 0x039B0AD1, |
||||
0x0381C0E0, 0x0369D036, 0x03531DEC, 0x033D91D2, |
||||
0x0329161F, 0x03159721, 0x03030303, 0x02F14990, |
||||
0x02E05C0B, 0x02D02D02, 0x02C0B02C, 0x02B1DA46, |
||||
0x02A3A0FD, 0x0295FAD4, 0x0288DF0C, 0x027C4597, |
||||
0x02702702, 0x02647C69, 0x02593F69, 0x024E6A17, |
||||
0x0243F6F0, 0x0239E0D5, 0x02302302, 0x0226B902, |
||||
0x021D9EAD, 0x0214D021, 0x020C49BA, 0x02040810, |
||||
0x01FC07F0, 0x01F44659, 0x01ECC07B, 0x01E573AC, |
||||
0x01DE5D6E, 0x01D77B65, 0x01D0CB58, 0x01CA4B30, |
||||
0x01C3F8F0, 0x01BDD2B8, 0x01B7D6C3, 0x01B20364, |
||||
0x01AC5701, 0x01A6D01A, 0x01A16D3F, 0x019C2D14, |
||||
0x01970E4F, 0x01920FB4, 0x018D3018, 0x01886E5F, |
||||
0x0183C977, 0x017F405F, 0x017AD220, 0x01767DCE, |
||||
0x01724287, 0x016E1F76, 0x016A13CD, 0x01661EC6, |
||||
0x01623FA7, 0x015E75BB, 0x015AC056, 0x01571ED3, |
||||
0x01539094, 0x01501501, 0x014CAB88, 0x0149539E, |
||||
0x01460CBC, 0x0142D662, 0x013FB013, 0x013C995A, |
||||
0x013991C2, 0x013698DF, 0x0133AE45, 0x0130D190, |
||||
0x012E025C, 0x012B404A, 0x01288B01, 0x0125E227, |
||||
0x01234567, 0x0120B470, 0x011E2EF3, 0x011BB4A4, |
||||
0x01194538, 0x0116E068, 0x011485F0, 0x0112358E, |
||||
0x010FEF01, 0x010DB20A, 0x010B7E6E, 0x010953F3, |
||||
0x01073260, 0x0105197F, 0x0103091B, 0x01010101 |
||||
}; |
||||
#endif |
||||
@ -0,0 +1,152 @@
|
||||
/* 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" |
||||
#include "opus_defines.h" |
||||
|
||||
#if !defined(_entcode_H) |
||||
# define _entcode_H (1) |
||||
# include <limits.h> |
||||
# include <stddef.h> |
||||
# include "ecintrin.h" |
||||
|
||||
extern const opus_uint32 SMALL_DIV_TABLE[129]; |
||||
|
||||
#ifdef OPUS_ARM_ASM |
||||
#define USE_SMALL_DIV_TABLE |
||||
#endif |
||||
|
||||
/*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 outstanding carry propagating symbols.*/ |
||||
opus_uint32 ext; |
||||
/*A buffered input/output symbol, awaiting carry propagation.*/ |
||||
int rem; |
||||
/*Nonzero if an error occurred.*/ |
||||
int error; |
||||
}; |
||||
|
||||
static OPUS_INLINE opus_uint32 ec_range_bytes(ec_ctx *_this){ |
||||
return _this->offs; |
||||
} |
||||
|
||||
static OPUS_INLINE unsigned char *ec_get_buffer(ec_ctx *_this){ |
||||
return _this->buf; |
||||
} |
||||
|
||||
static OPUS_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 OPUS_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); |
||||
|
||||
/* Tested exhaustively for all n and for 1<=d<=256 */ |
||||
static OPUS_INLINE opus_uint32 celt_udiv(opus_uint32 n, opus_uint32 d) { |
||||
celt_sig_assert(d>0); |
||||
#ifdef USE_SMALL_DIV_TABLE |
||||
if (d>256) |
||||
return n/d; |
||||
else { |
||||
opus_uint32 t, q; |
||||
t = EC_ILOG(d&-d); |
||||
q = (opus_uint64)SMALL_DIV_TABLE[d>>t]*(n>>(t-1))>>32; |
||||
return q+(n-q*d >= d); |
||||
} |
||||
#else |
||||
return n/d; |
||||
#endif |
||||
} |
||||
|
||||
static OPUS_INLINE opus_int32 celt_sudiv(opus_int32 n, opus_int32 d) { |
||||
celt_sig_assert(d>0); |
||||
#ifdef USE_SMALL_DIV_TABLE |
||||
if (n<0) |
||||
return -(opus_int32)celt_udiv(-n, d); |
||||
else |
||||
return celt_udiv(n, d); |
||||
#else |
||||
return n/d; |
||||
#endif |
||||
} |
||||
|
||||
#endif |
||||
@ -0,0 +1,266 @@
|
||||
/* 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/ee398a/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=celt_udiv(_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; |
||||
} |
||||
|
||||
int ec_dec_icdf16(ec_dec *_this,const opus_uint16 *_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,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(_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); |
||||
|
||||
/*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_icdf16(ec_dec *_this,const opus_uint16 *_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 2, 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,305 @@
|
||||
/* 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 OPUS_INLINE 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=celt_udiv(_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_icdf16(ec_enc *_this,int _s,const opus_uint16 *_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){ |
||||
if (_this->buf) 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,119 @@
|
||||
/* 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 discernible 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 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_icdf16(ec_enc *_this,int _s,const opus_uint16 *_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 2, 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 remaining 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,79 @@
|
||||
/* Copyright (C) 2003 Jean-Marc Valin */ |
||||
/**
|
||||
@file fixed_c5x.h |
||||
@brief Fixed-point operations for the TI C5x DSP family |
||||
*/ |
||||
/*
|
||||
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_C5X_H |
||||
#define FIXED_C5X_H |
||||
|
||||
#include "dsplib.h" |
||||
|
||||
#undef IMUL32 |
||||
static OPUS_INLINE long IMUL32(long i, long j) |
||||
{ |
||||
long ac0, ac1; |
||||
ac0 = _lmpy(i>>16,j); |
||||
ac1 = ac0 + _lmpy(i,j>>16); |
||||
return _lmpyu(i,j) + (ac1<<16); |
||||
} |
||||
|
||||
#undef MAX16 |
||||
#define MAX16(a,b) _max(a,b) |
||||
|
||||
#undef MIN16 |
||||
#define MIN16(a,b) _min(a,b) |
||||
|
||||
#undef MAX32 |
||||
#define MAX32(a,b) _lmax(a,b) |
||||
|
||||
#undef MIN32 |
||||
#define MIN32(a,b) _lmin(a,b) |
||||
|
||||
#undef VSHR32 |
||||
#define VSHR32(a, shift) _lshl(a,-(shift)) |
||||
|
||||
#undef MULT16_16_Q15 |
||||
#define MULT16_16_Q15(a,b) (_smpy(a,b)) |
||||
|
||||
#undef MULT16_16SU |
||||
#define MULT16_16SU(a,b) _lmpysu(a,b) |
||||
|
||||
#undef MULT_16_16 |
||||
#define MULT_16_16(a,b) _lmpy(a,b) |
||||
|
||||
/* FIXME: This is technically incorrect and is bound to cause problems. Is there any cleaner solution? */ |
||||
#undef MULT16_32_Q15 |
||||
#define MULT16_32_Q15(a,b) ADD32(SHL(MULT16_16((a),SHR((b),16)),1), SHR(MULT16_16SU((a),(b)),15)) |
||||
|
||||
#define celt_ilog2(x) (30 - _lnorm(x)) |
||||
#define OVERRIDE_CELT_ILOG2 |
||||
|
||||
#define celt_maxabs16(x, len) MAX32(EXTEND32(maxval((DATA *)x, len)),-EXTEND32(minval((DATA *)x, len))) |
||||
#define OVERRIDE_CELT_MAXABS16 |
||||
|
||||
#endif /* FIXED_C5X_H */ |
||||
@ -0,0 +1,70 @@
|
||||
/* Copyright (C) 2008 CSIRO */ |
||||
/**
|
||||
@file fixed_c6x.h |
||||
@brief Fixed-point operations for the TI C6x DSP family |
||||
*/ |
||||
/*
|
||||
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_C6X_H |
||||
#define FIXED_C6X_H |
||||
|
||||
#undef MULT16_16SU |
||||
#define MULT16_16SU(a,b) _mpysu(a,b) |
||||
|
||||
#undef MULT_16_16 |
||||
#define MULT_16_16(a,b) _mpy(a,b) |
||||
|
||||
#define celt_ilog2(x) (30 - _norm(x)) |
||||
#define OVERRIDE_CELT_ILOG2 |
||||
|
||||
#undef MULT16_32_Q15 |
||||
#define MULT16_32_Q15(a,b) (_mpylill(a, b) >> 15) |
||||
|
||||
#if 0 |
||||
#include "dsplib.h" |
||||
|
||||
#undef MAX16 |
||||
#define MAX16(a,b) _max(a,b) |
||||
|
||||
#undef MIN16 |
||||
#define MIN16(a,b) _min(a,b) |
||||
|
||||
#undef MAX32 |
||||
#define MAX32(a,b) _lmax(a,b) |
||||
|
||||
#undef MIN32 |
||||
#define MIN32(a,b) _lmin(a,b) |
||||
|
||||
#undef VSHR32 |
||||
#define VSHR32(a, shift) _lshl(a,-(shift)) |
||||
|
||||
#undef MULT16_16_Q15 |
||||
#define MULT16_16_Q15(a,b) (_smpy(a,b)) |
||||
|
||||
#define celt_maxabs16(x, len) MAX32(EXTEND32(maxval((DATA *)x, len)),-EXTEND32(minval((DATA *)x, len))) |
||||
#define OVERRIDE_CELT_MAXABS16 |
||||
|
||||
#endif /* FIXED_C6X_H */ |
||||
@ -0,0 +1,848 @@
|
||||
/* 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> |
||||
#include "opus_defines.h" |
||||
|
||||
#ifdef CELT_C |
||||
OPUS_EXPORT opus_int64 celt_mips=0; |
||||
#else |
||||
extern opus_int64 celt_mips; |
||||
#endif |
||||
|
||||
#define MULT16_16U(a,b) ((opus_uint32)(a)*(opus_uint32)(b)) |
||||
#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)) |
||||
#define MULT32_32_P31(a,b) ADD32(SHL32(MULT16_16(SHR((a),16),SHR((b),16)),1), SHR32(128+(opus_int32)(MULT16_16U(((a)&0x0000ffff),((b)&0x0000ffff))>>(16+7)) + SHR32(MULT16_16SU(SHR((a),16),((b)&0x0000ffff)),7) + SHR32(MULT16_16SU(SHR((b),16),((a)&0x0000ffff)),7), 8) ) |
||||
#define MULT32_32_P31_ovflw(a,b) ADD32_ovflw(SHL32(MULT16_16(SHR((a),16),SHR((b),16)),1), SHR32(128+(opus_int32)(MULT16_16U(((a)&0x0000ffff),((b)&0x0000ffff))>>(16+7)) + SHR32(MULT16_16SU(SHR((a),16),((b)&0x0000ffff)),7) + SHR32(MULT16_16SU(SHR((b),16),((a)&0x0000ffff)),7), 8) ) |
||||
#define MULT32_32_Q32(a,b) ADD32(ADD32(MULT16_16(SHR((a),16),SHR((b),16)), SHR(MULT16_16SU(SHR((a),16),((b)&0x0000ffff)),16)), SHR(MULT16_16SU(SHR((b),16),((a)&0x0000ffff)),16)) |
||||
|
||||
/** 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_val64)1)<<(bits)))) |
||||
#define GCONST2(x,bits) ((celt_glog)(.5+(x)*(((celt_glog)1)<<(bits)))) |
||||
#define GCONST(x) GCONST2((x),DB_SHIFT) |
||||
|
||||
#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) |
||||
|
||||
/** Add two 32-bit values, ignore any overflows */ |
||||
#define ADD32_ovflw(a,b) (celt_mips+=2,(opus_val32)((opus_uint32)(a)+(opus_uint32)(b))) |
||||
/** Subtract two 32-bit values, ignore any overflows */ |
||||
#define SUB32_ovflw(a,b) (celt_mips+=2,(opus_val32)((opus_uint32)(a)-(opus_uint32)(b))) |
||||
/* Avoid MSVC warning C4146: unary minus operator applied to unsigned type */ |
||||
/** Negate 32-bit value, ignore any overflows */ |
||||
#define NEG32_ovflw(a) (celt_mips+=2,(opus_val32)(0-(opus_uint32)(a))) |
||||
/** 32-bit shift left, ignoring overflows */ |
||||
#define SHL32_ovflw(a,shift) ((opus_int32)((opus_uint32)(a)<<(shift))) |
||||
/** 32-bit arithmetic shift right with rounding-to-nearest, ignoring overflows */ |
||||
#define PSHR32_ovflw(a,shift) (SHR32(ADD32_ovflw(a, (EXTEND32(1)<<(shift)>>1)),shift)) |
||||
|
||||
static OPUS_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 OPUS_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 OPUS_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 OPUS_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 OPUS_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 OPUS_INLINE short SHL16_(int a, int shift, char *file, int line) |
||||
{ |
||||
opus_int32 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 = (opus_int32)((opus_uint32)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 OPUS_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 OPUS_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", (long long)a, shift, file, line); |
||||
#ifdef FIXED_DEBUG_ASSERT |
||||
celt_assert(0); |
||||
#endif |
||||
} |
||||
res = (opus_int64)((opus_uint64)a<<shift); |
||||
if (!VERIFY_INT(res)) |
||||
{ |
||||
fprintf (stderr, "SHL32: output is not int: %lld<<%d = %lld in %s: line %d\n", (long long)a, shift, (long long)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 SHR64(a,shift) (celt_mips++,(a) >> (shift)) |
||||
|
||||
#define ROUND16(x,a) (celt_mips--,EXTRACT16(PSHR32((x),(a)))) |
||||
#define SROUND16(x,a) (celt_mips--,EXTRACT16(SATURATE(PSHR32(x,a), 32767))); |
||||
|
||||
#define HALF16(x) (SHR16(x,1)) |
||||
#define HALF32(x) (SHR32(x,1)) |
||||
|
||||
#define ADD16(a, b) ADD16_(a, b, __FILE__, __LINE__) |
||||
static OPUS_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 OPUS_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 OPUS_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 OPUS_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 OPUS_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", (unsigned long long)a, (unsigned long long)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", (unsigned long long)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 OPUS_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", (unsigned long long)a, (unsigned long long)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", (unsigned long long)a, (unsigned long long)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", (unsigned long long)a, (unsigned long long)b, (unsigned long long)res, file, line); |
||||
#ifdef FIXED_DEBUG_ASSERT |
||||
celt_assert(0); |
||||
#endif |
||||
} |
||||
celt_mips+=2; |
||||
return res; |
||||
} |
||||
|
||||
/* result fits in 16 bits */ |
||||
static OPUS_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; |
||||
} |
||||
|
||||
/* result fits in 32 bits */ |
||||
static OPUS_INLINE int MULT32_32_32(opus_int64 a, opus_int64 b) |
||||
{ |
||||
opus_int64 res; |
||||
if (!VERIFY_INT(a) || !VERIFY_INT(b)) |
||||
{ |
||||
fprintf (stderr, "MULT32_32_32: inputs are not int: %lld %lld\n", (long long)a, (long long)b); |
||||
#ifdef FIXED_DEBUG_ASSERT |
||||
celt_assert(0); |
||||
#endif |
||||
} |
||||
res = a*b; |
||||
if (!VERIFY_INT(res)) |
||||
{ |
||||
fprintf (stderr, "MULT32_32_32: output is not int: %lld\n", (long long)res); |
||||
#ifdef FIXED_DEBUG_ASSERT |
||||
celt_assert(0); |
||||
#endif |
||||
} |
||||
celt_mips+=5; |
||||
return res; |
||||
} |
||||
|
||||
static OPUS_INLINE int MULT32_32_Q16(opus_int64 a, opus_int64 b) |
||||
{ |
||||
opus_int64 res; |
||||
if (!VERIFY_INT(a) || !VERIFY_INT(b)) |
||||
{ |
||||
fprintf (stderr, "MULT32_32_Q16: inputs are not int: %lld %lld\n", (long long)a, (long long)b); |
||||
#ifdef FIXED_DEBUG_ASSERT |
||||
celt_assert(0); |
||||
#endif |
||||
} |
||||
res = ((opus_int64)(a)*(opus_int64)(b)) >> 16; |
||||
if (!VERIFY_INT(res)) |
||||
{ |
||||
fprintf (stderr, "MULT32_32_Q16: output is not int: %lld*%lld=%lld\n", (long long)a, (long long)b, (long long)res); |
||||
#ifdef FIXED_DEBUG_ASSERT |
||||
celt_assert(0); |
||||
#endif |
||||
} |
||||
celt_mips+=5; |
||||
return res; |
||||
} |
||||
|
||||
#define MULT16_16(a, b) MULT16_16_(a, b, __FILE__, __LINE__) |
||||
static OPUS_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 OPUS_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_int64)(1)<<(16+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 OPUS_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)<<(16+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)))) |
||||
#define MAC16_32_Q16(c,a,b) (celt_mips-=2,ADD32((c),MULT16_32_Q16((a),(b)))) |
||||
|
||||
static OPUS_INLINE int SATURATE(int a, int b) |
||||
{ |
||||
if (a>b) |
||||
a=b; |
||||
if (a<-b) |
||||
a = -b; |
||||
celt_mips+=3; |
||||
return a; |
||||
} |
||||
|
||||
static OPUS_INLINE opus_int16 SATURATE16(opus_int32 a) |
||||
{ |
||||
celt_mips+=3; |
||||
if (a>32767) |
||||
return 32767; |
||||
else if (a<-32768) |
||||
return -32768; |
||||
else return a; |
||||
} |
||||
|
||||
static OPUS_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 OPUS_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 OPUS_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 OPUS_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 OPUS_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 OPUS_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 OPUS_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 OPUS_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 OPUS_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; |
||||
} |
||||
|
||||
static OPUS_INLINE opus_val16 SIG2WORD16_generic(celt_sig x) |
||||
{ |
||||
x = PSHR32(x, SIG_SHIFT); |
||||
x = MAX32(x, -32768); |
||||
x = MIN32(x, 32767); |
||||
return EXTRACT16(x); |
||||
} |
||||
#define SIG2WORD16(x) (SIG2WORD16_generic(x)) |
||||
|
||||
|
||||
#undef PRINT_MIPS |
||||
#define PRINT_MIPS(file) do {fprintf (file, "total complexity = %llu MIPS\n", (unsigned long long)celt_mips);} while (0); |
||||
|
||||
#endif |
||||
@ -0,0 +1,218 @@
|
||||
/* 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 */ |
||||
#if OPUS_FAST_INT64 |
||||
#define MULT16_32_Q16(a,b) ((opus_val32)SHR((opus_int64)((opus_val16)(a))*(b),16)) |
||||
#else |
||||
#define MULT16_32_Q16(a,b) ADD32(MULT16_16((a),SHR((b),16)), SHR(MULT16_16SU((a),((b)&0x0000ffff)),16)) |
||||
#endif |
||||
|
||||
/** 16x32 multiplication, followed by a 16-bit shift right (round-to-nearest). Results fits in 32 bits */ |
||||
#if OPUS_FAST_INT64 |
||||
#define MULT16_32_P16(a,b) ((opus_val32)PSHR((opus_int64)((opus_val16)(a))*(b),16)) |
||||
#else |
||||
#define MULT16_32_P16(a,b) ADD32(MULT16_16((a),SHR((b),16)), PSHR(MULT16_16SU((a),((b)&0x0000ffff)),16)) |
||||
#endif |
||||
|
||||
/** 16x32 multiplication, followed by a 15-bit shift right. Results fits in 32 bits */ |
||||
#if OPUS_FAST_INT64 |
||||
#define MULT16_32_Q15(a,b) ((opus_val32)SHR((opus_int64)((opus_val16)(a))*(b),15)) |
||||
#else |
||||
#define MULT16_32_Q15(a,b) ADD32(SHL(MULT16_16((a),SHR((b),16)),1), SHR(MULT16_16SU((a),((b)&0x0000ffff)),15)) |
||||
#endif |
||||
|
||||
/** 32x32 multiplication, followed by a 16-bit shift right. Results fits in 32 bits */ |
||||
#if OPUS_FAST_INT64 |
||||
#define MULT32_32_Q16(a,b) ((opus_val32)SHR((opus_int64)(a)*(opus_int64)(b),16)) |
||||
#else |
||||
#define MULT32_32_Q16(a,b) (ADD32(ADD32(ADD32((opus_val32)(SHR32(((opus_uint32)((a)&0x0000ffff)*(opus_uint32)((b)&0x0000ffff)),16)), MULT16_16SU(SHR32(a,16),((b)&0x0000ffff))), MULT16_16SU(SHR32(b,16),((a)&0x0000ffff))), SHL32(MULT16_16(SHR32(a,16),SHR32(b,16)),16))) |
||||
#endif |
||||
|
||||
/** 32x32 multiplication, followed by a 31-bit shift right. Results fits in 32 bits */ |
||||
#if OPUS_FAST_INT64 |
||||
#define MULT32_32_Q31(a,b) ((opus_val32)SHR((opus_int64)(a)*(opus_int64)(b),31)) |
||||
#else |
||||
#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)) |
||||
#endif |
||||
|
||||
/** 32x32 multiplication, followed by a 31-bit shift right (with rounding). Results fits in 32 bits */ |
||||
#if OPUS_FAST_INT64 |
||||
#define MULT32_32_P31(a,b) ((opus_val32)SHR(1073741824+(opus_int64)(a)*(opus_int64)(b),31)) |
||||
#define MULT32_32_P31_ovflw(a,b) MULT32_32_P31(a,b) |
||||
#else |
||||
#define MULT16_16U(a,b) ((opus_uint32)(a)*(opus_uint32)(b)) |
||||
#define MULT32_32_P31(a,b) ADD32(SHL(MULT16_16(SHR((a),16),SHR((b),16)),1), SHR32(128+(opus_int32)SHR(MULT16_16U(((a)&0x0000ffff),((b)&0x0000ffff)),16+7) + SHR32(MULT16_16SU(SHR((a),16),((b)&0x0000ffff)),7) + SHR32(MULT16_16SU(SHR((b),16),((a)&0x0000ffff)),7), 8) ) |
||||
#define MULT32_32_P31_ovflw(a,b) ADD32_ovflw(SHL(MULT16_16(SHR((a),16),SHR((b),16)),1), SHR32(128+(opus_int32)SHR(MULT16_16U(((a)&0x0000ffff),((b)&0x0000ffff)),16+7) + SHR32(MULT16_16SU(SHR((a),16),((b)&0x0000ffff)),7) + SHR32(MULT16_16SU(SHR((b),16),((a)&0x0000ffff)),7), 8) ) |
||||
#endif |
||||
|
||||
/** 32x32 multiplication, followed by a 32-bit shift right. Results fits in 32 bits */ |
||||
#if OPUS_FAST_INT64 |
||||
#define MULT32_32_Q32(a,b) ((opus_val32)SHR((opus_int64)(a)*(opus_int64)(b),32)) |
||||
#else |
||||
#define MULT32_32_Q32(a,b) ADD32(ADD32(MULT16_16(SHR((a),16),SHR((b),16)), SHR(MULT16_16SU(SHR((a),16),((b)&0x0000ffff)),16)), SHR(MULT16_16SU(SHR((b),16),((a)&0x0000ffff)),16)) |
||||
#endif |
||||
|
||||
/** 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_int64)1)<<(bits)))) |
||||
|
||||
/** Compile-time conversion of float constant to log gain value */ |
||||
#define GCONST2(x,bits) ((celt_glog)(.5+(x)*(((celt_glog)1)<<(bits)))) |
||||
|
||||
/** Compile-time conversion of float constant to DB_SHIFT log gain value */ |
||||
#define GCONST(x) GCONST2((x),DB_SHIFT) |
||||
|
||||
/** 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))) |
||||
|
||||
/** Arithmetic shift-right of a 64-bit value */ |
||||
#define SHR64(a,shift) ((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))) |
||||
|
||||
#define SATURATE16(x) (EXTRACT16((x)>32767 ? 32767 : (x)<-32768 ? -32768 : (x))) |
||||
|
||||
/** Shift by a and round-to-nearest 32-bit value. Result is a 16-bit value */ |
||||
#define ROUND16(x,a) (EXTRACT16(PSHR32((x),(a)))) |
||||
/** Shift by a and round-to-nearest 32-bit value. Result is a saturated 16-bit value */ |
||||
#define SROUND16(x,a) EXTRACT16(SATURATE(PSHR32(x,a), 32767)); |
||||
|
||||
/** 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)) |
||||
|
||||
/** Add two 32-bit values, ignore any overflows */ |
||||
#define ADD32_ovflw(a,b) ((opus_val32)((opus_uint32)(a)+(opus_uint32)(b))) |
||||
/** Subtract two 32-bit values, ignore any overflows */ |
||||
#define SUB32_ovflw(a,b) ((opus_val32)((opus_uint32)(a)-(opus_uint32)(b))) |
||||
/* Avoid MSVC warning C4146: unary minus operator applied to unsigned type */ |
||||
/** Negate 32-bit value, ignore any overflows */ |
||||
#define NEG32_ovflw(a) ((opus_val32)(0-(opus_uint32)(a))) |
||||
/** 32-bit shift left, ignoring overflows */ |
||||
#define SHL32_ovflw(a,shift) SHL32(a,shift) |
||||
/** 32-bit arithmetic shift right with rounding-to-nearest, ignoring overflows */ |
||||
#define PSHR32_ovflw(a,shift) (SHR32(ADD32_ovflw(a, (EXTEND32(1)<<(shift)>>1)),shift)) |
||||
|
||||
/** 16x16 multiplication where the result fits in 16 bits */ |
||||
#define MULT16_16_16(a,b) ((((opus_val16)(a))*((opus_val16)(b)))) |
||||
|
||||
/** 32x32 multiplication where the result fits in 32 bits */ |
||||
#define MULT32_32_32(a,b) ((((opus_val32)(a))*((opus_val32)(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, followed by a 15-bit shift right and 32-bit add.
|
||||
b must fit in 31 bits. |
||||
Result 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))) |
||||
|
||||
/** 16x32 multiplication, followed by a 16-bit shift right and 32-bit add.
|
||||
Results fits in 32 bits */ |
||||
#define MAC16_32_Q16(c,a,b) ADD32((c),ADD32(MULT16_16((a),SHR((b),16)), SHR(MULT16_16SU((a),((b)&0x0000ffff)),16))) |
||||
|
||||
#define MULT16_16_Q11_32(a,b) (SHR(MULT16_16((a),(b)),11)) |
||||
#define MULT16_16_Q11(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))) |
||||
|
||||
#if defined(__mips) |
||||
#include "mips/fixed_generic_mipsr1.h" |
||||
#endif |
||||
|
||||
static OPUS_INLINE opus_val16 SIG2WORD16_generic(celt_sig x) |
||||
{ |
||||
x = PSHR32(x, SIG_SHIFT); |
||||
x = MAX32(x, -32768); |
||||
x = MIN32(x, 32767); |
||||
return EXTRACT16(x); |
||||
} |
||||
#define SIG2WORD16(x) (SIG2WORD16_generic(x)) |
||||
|
||||
#endif |
||||
@ -0,0 +1,176 @@
|
||||
/* 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. |
||||
*/ |
||||
|
||||
/* With GCC, when SSE is available, the fastest conversion is cvtss2si. */ |
||||
#if defined(__GNUC__) && defined(__SSE__) |
||||
|
||||
#include <xmmintrin.h> |
||||
static OPUS_INLINE opus_int32 float2int(float x) {return _mm_cvt_ss2si(_mm_set_ss(x));} |
||||
|
||||
#elif (defined(_MSC_VER) && _MSC_VER >= 1400) && (defined(_M_X64) || (defined(_M_IX86_FP) && _M_IX86_FP >= 1)) |
||||
|
||||
#include <xmmintrin.h> |
||||
static OPUS_INLINE opus_int32 float2int(float value) |
||||
{ |
||||
/* _mm_load_ss will generate same code as _mm_set_ss
|
||||
** in _MSC_VER >= 1914 /02 so keep __mm_load__ss |
||||
** for backward compatibility. |
||||
*/ |
||||
return _mm_cvtss_si32(_mm_load_ss(&value)); |
||||
} |
||||
|
||||
#elif (defined(_MSC_VER) && _MSC_VER >= 1400) && defined (_M_IX86) |
||||
|
||||
#include <math.h> |
||||
|
||||
/* Win32 doesn't seem to have these functions.
|
||||
** Therefore implement OPUS_INLINE versions of these functions here. |
||||
*/ |
||||
|
||||
static OPUS_INLINE opus_int32 |
||||
float2int (float flt) |
||||
{ int intgr; |
||||
|
||||
_asm |
||||
{ fld flt |
||||
fistp intgr |
||||
} ; |
||||
|
||||
return intgr ; |
||||
} |
||||
#elif defined(__aarch64__) |
||||
|
||||
#include <arm_neon.h> |
||||
static OPUS_INLINE opus_int32 float2int(float flt) |
||||
{ |
||||
return vcvtns_s32_f32(flt); |
||||
} |
||||
|
||||
#elif defined(HAVE_LRINTF) && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L |
||||
|
||||
/* 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) && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L |
||||
|
||||
#define _ISOC9X_SOURCE 1 |
||||
#define _ISOC99_SOURCE 1 |
||||
|
||||
#define __USE_ISOC9X 1 |
||||
#define __USE_ISOC99 1 |
||||
|
||||
#include <math.h> |
||||
#define float2int(x) lrint(x) |
||||
|
||||
#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 OPUS_INLINE opus_int16 FLOAT2INT16(float x) |
||||
{ |
||||
x = x*CELT_SIG_SCALE; |
||||
x = MAX32(x, -32768); |
||||
x = MIN32(x, 32767); |
||||
return (opus_int16)float2int(x); |
||||
} |
||||
|
||||
static OPUS_INLINE opus_int32 FLOAT2INT24(float x) |
||||
{ |
||||
x = x*(CELT_SIG_SCALE*256.f); |
||||
x = MAX32(x, -16777216); |
||||
x = MIN32(x, 16777216); |
||||
return float2int(x); |
||||
} |
||||
#ifdef FIXED_POINT |
||||
static OPUS_INLINE opus_int32 FLOAT2SIG(float x) |
||||
{ |
||||
x = x*((opus_int32)32768<<SIG_SHIFT); |
||||
x = MAX32(x, -(65536<<SIG_SHIFT)); |
||||
x = MIN32(x, 65536<<SIG_SHIFT); |
||||
return float2int(x); |
||||
} |
||||
#endif |
||||
#endif /* DISABLE_FLOAT_API */ |
||||
|
||||
#endif /* FLOAT_CAST_H */ |
||||
@ -0,0 +1,650 @@
|
||||
/*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" |
||||
|
||||
#ifndef M_PI |
||||
#define M_PI 3.141592653 |
||||
#endif |
||||
|
||||
/* The guts header contains all the multiplication and addition macros that are defined for
|
||||
complex numbers. It also declares the kf_ internal functions. |
||||
*/ |
||||
|
||||
static void kf_bfly2( |
||||
kiss_fft_cpx * Fout, |
||||
int m, |
||||
int N |
||||
) |
||||
{ |
||||
kiss_fft_cpx * Fout2; |
||||
int i; |
||||
(void)m; |
||||
#ifdef CUSTOM_MODES |
||||
if (m==1) |
||||
{ |
||||
celt_assert(m==1); |
||||
for (i=0;i<N;i++) |
||||
{ |
||||
kiss_fft_cpx t; |
||||
Fout2 = Fout + 1; |
||||
t = *Fout2; |
||||
C_SUB( *Fout2 , *Fout , t ); |
||||
C_ADDTO( *Fout , t ); |
||||
Fout += 2; |
||||
} |
||||
} else |
||||
#endif |
||||
{ |
||||
celt_coef tw; |
||||
tw = QCONST32(0.7071067812f, COEF_SHIFT-1); |
||||
/* We know that m==4 here because the radix-2 is just after a radix-4 */ |
||||
celt_assert(m==4); |
||||
for (i=0;i<N;i++) |
||||
{ |
||||
kiss_fft_cpx t; |
||||
Fout2 = Fout + 4; |
||||
t = Fout2[0]; |
||||
C_SUB( Fout2[0] , Fout[0] , t ); |
||||
C_ADDTO( Fout[0] , t ); |
||||
|
||||
t.r = S_MUL(ADD32_ovflw(Fout2[1].r, Fout2[1].i), tw); |
||||
t.i = S_MUL(SUB32_ovflw(Fout2[1].i, Fout2[1].r), tw); |
||||
C_SUB( Fout2[1] , Fout[1] , t ); |
||||
C_ADDTO( Fout[1] , t ); |
||||
|
||||
t.r = Fout2[2].i; |
||||
t.i = NEG32_ovflw(Fout2[2].r); |
||||
C_SUB( Fout2[2] , Fout[2] , t ); |
||||
C_ADDTO( Fout[2] , t ); |
||||
|
||||
t.r = S_MUL(SUB32_ovflw(Fout2[3].i, Fout2[3].r), tw); |
||||
t.i = S_MUL(NEG32_ovflw(ADD32_ovflw(Fout2[3].i, Fout2[3].r)), tw); |
||||
C_SUB( Fout2[3] , Fout[3] , t ); |
||||
C_ADDTO( Fout[3] , t ); |
||||
Fout += 8; |
||||
} |
||||
} |
||||
} |
||||
|
||||
static void kf_bfly4( |
||||
kiss_fft_cpx * Fout, |
||||
const size_t fstride, |
||||
const kiss_fft_state *st, |
||||
int m, |
||||
int N, |
||||
int mm |
||||
) |
||||
{ |
||||
int i; |
||||
|
||||
if (m==1) |
||||
{ |
||||
/* Degenerate case where all the twiddles are 1. */ |
||||
for (i=0;i<N;i++) |
||||
{ |
||||
kiss_fft_cpx scratch0, scratch1; |
||||
|
||||
C_SUB( scratch0 , *Fout, Fout[2] ); |
||||
C_ADDTO(*Fout, Fout[2]); |
||||
C_ADD( scratch1 , Fout[1] , Fout[3] ); |
||||
C_SUB( Fout[2], *Fout, scratch1 ); |
||||
C_ADDTO( *Fout , scratch1 ); |
||||
C_SUB( scratch1 , Fout[1] , Fout[3] ); |
||||
|
||||
Fout[1].r = ADD32_ovflw(scratch0.r, scratch1.i); |
||||
Fout[1].i = SUB32_ovflw(scratch0.i, scratch1.r); |
||||
Fout[3].r = SUB32_ovflw(scratch0.r, scratch1.i); |
||||
Fout[3].i = ADD32_ovflw(scratch0.i, scratch1.r); |
||||
Fout+=4; |
||||
} |
||||
} else { |
||||
int j; |
||||
kiss_fft_cpx scratch[6]; |
||||
const kiss_twiddle_cpx *tw1,*tw2,*tw3; |
||||
const int m2=2*m; |
||||
const int m3=3*m; |
||||
kiss_fft_cpx * Fout_beg = Fout; |
||||
for (i=0;i<N;i++) |
||||
{ |
||||
Fout = Fout_beg + i*mm; |
||||
tw3 = tw2 = tw1 = st->twiddles; |
||||
/* m is guaranteed to be a multiple of 4. */ |
||||
for (j=0;j<m;j++) |
||||
{ |
||||
C_MUL(scratch[0],Fout[m] , *tw1 ); |
||||
C_MUL(scratch[1],Fout[m2] , *tw2 ); |
||||
C_MUL(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 = ADD32_ovflw(scratch[5].r, scratch[4].i); |
||||
Fout[m].i = SUB32_ovflw(scratch[5].i, scratch[4].r); |
||||
Fout[m3].r = SUB32_ovflw(scratch[5].r, scratch[4].i); |
||||
Fout[m3].i = ADD32_ovflw(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; |
||||
#ifdef FIXED_POINT |
||||
/*epi3.r = -16384;*/ /* Unused */ |
||||
epi3.i = -QCONST32(0.86602540f, COEF_SHIFT-1); |
||||
#else |
||||
epi3 = st->twiddles[fstride*m]; |
||||
#endif |
||||
for (i=0;i<N;i++) |
||||
{ |
||||
Fout = Fout_beg + i*mm; |
||||
tw1=tw2=st->twiddles; |
||||
/* For non-custom modes, m is guaranteed to be a multiple of 4. */ |
||||
k=m; |
||||
do { |
||||
|
||||
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 = SUB32_ovflw(Fout->r, HALF_OF(scratch[3].r)); |
||||
Fout[m].i = SUB32_ovflw(Fout->i, HALF_OF(scratch[3].i)); |
||||
|
||||
C_MULBYSCALAR( scratch[0] , epi3.i ); |
||||
|
||||
C_ADDTO(*Fout,scratch[3]); |
||||
|
||||
Fout[m2].r = ADD32_ovflw(Fout[m].r, scratch[0].i); |
||||
Fout[m2].i = SUB32_ovflw(Fout[m].i, scratch[0].r); |
||||
|
||||
Fout[m].r = SUB32_ovflw(Fout[m].r, scratch[0].i); |
||||
Fout[m].i = ADD32_ovflw(Fout[m].i, scratch[0].r); |
||||
|
||||
++Fout; |
||||
} while(--k); |
||||
} |
||||
} |
||||
|
||||
|
||||
#ifndef OVERRIDE_kf_bfly5 |
||||
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 *tw; |
||||
kiss_twiddle_cpx ya,yb; |
||||
kiss_fft_cpx * Fout_beg = Fout; |
||||
|
||||
#ifdef FIXED_POINT |
||||
ya.r = QCONST32(0.30901699f, COEF_SHIFT-1); |
||||
ya.i = -QCONST32(0.95105652f, COEF_SHIFT-1); |
||||
yb.r = -QCONST32(0.80901699f, COEF_SHIFT-1); |
||||
yb.i = -QCONST32(0.58778525f, COEF_SHIFT-1); |
||||
#else |
||||
ya = st->twiddles[fstride*m]; |
||||
yb = st->twiddles[fstride*2*m]; |
||||
#endif |
||||
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 non-custom modes, m is guaranteed to be a multiple of 4. */ |
||||
for ( u=0; u<m; ++u ) { |
||||
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 = ADD32_ovflw(Fout0->r, ADD32_ovflw(scratch[7].r, scratch[8].r)); |
||||
Fout0->i = ADD32_ovflw(Fout0->i, ADD32_ovflw(scratch[7].i, scratch[8].i)); |
||||
|
||||
scratch[5].r = ADD32_ovflw(scratch[0].r, ADD32_ovflw(S_MUL(scratch[7].r,ya.r), S_MUL(scratch[8].r,yb.r))); |
||||
scratch[5].i = ADD32_ovflw(scratch[0].i, ADD32_ovflw(S_MUL(scratch[7].i,ya.r), S_MUL(scratch[8].i,yb.r))); |
||||
|
||||
scratch[6].r = ADD32_ovflw(S_MUL(scratch[10].i,ya.i), S_MUL(scratch[9].i,yb.i)); |
||||
scratch[6].i = NEG32_ovflw(ADD32_ovflw(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 = ADD32_ovflw(scratch[0].r, ADD32_ovflw(S_MUL(scratch[7].r,yb.r), S_MUL(scratch[8].r,ya.r))); |
||||
scratch[11].i = ADD32_ovflw(scratch[0].i, ADD32_ovflw(S_MUL(scratch[7].i,yb.r), S_MUL(scratch[8].i,ya.r))); |
||||
scratch[12].r = SUB32_ovflw(S_MUL(scratch[9].i,ya.i), S_MUL(scratch[10].i,yb.i)); |
||||
scratch[12].i = SUB32_ovflw(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 /* OVERRIDE_kf_bfly5 */ |
||||
|
||||
|
||||
#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; |
||||
int i; |
||||
int stages=0; |
||||
int nbak = n; |
||||
|
||||
/*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[2*stages] = p; |
||||
if (p==2 && stages > 1) |
||||
{ |
||||
facbuf[2*stages] = 4; |
||||
facbuf[2] = 2; |
||||
} |
||||
stages++; |
||||
} while (n > 1); |
||||
n = nbak; |
||||
/* Reverse the order to get the radix 4 at the end, so we can use the
|
||||
fast degenerate case. It turns out that reversing the order also |
||||
improves the noise behaviour. */ |
||||
for (i=0;i<stages/2;i++) |
||||
{ |
||||
int tmp; |
||||
tmp = facbuf[2*i]; |
||||
facbuf[2*i] = facbuf[2*(stages-i-1)]; |
||||
facbuf[2*(stages-i-1)] = tmp; |
||||
} |
||||
for (i=0;i<stages;i++) |
||||
{ |
||||
n /= facbuf[2*i]; |
||||
facbuf[2*i+1] = n; |
||||
} |
||||
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; |
||||
#ifdef ENABLE_QEXT |
||||
twiddles[i].r = (int)MIN32(2147483647, floor(.5+2147483648*cos((2*M_PI/nfft)*phase))); |
||||
twiddles[i].i = (int)MIN32(2147483647, floor(.5+2147483648*sin((2*M_PI/nfft)*phase))); |
||||
#else |
||||
kf_cexp2(twiddles+i, DIV32(SHL32(phase,17),nfft)); |
||||
#endif |
||||
} |
||||
#else |
||||
for (i=0;i<nfft;++i) { |
||||
const double pi=3.14159265358979323846264338327; |
||||
double phase = ( -2*pi /nfft ) * i; |
||||
kf_cexp(twiddles+i, phase ); |
||||
} |
||||
#endif |
||||
} |
||||
|
||||
int opus_fft_alloc_arch_c(kiss_fft_state *st) { |
||||
(void)st; |
||||
return 0; |
||||
} |
||||
|
||||
/*
|
||||
* |
||||
* 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, int arch) |
||||
{ |
||||
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; |
||||
#ifdef FIXED_POINT |
||||
st->scale_shift = celt_ilog2(st->nfft); |
||||
# ifdef ENABLE_QEXT |
||||
if (st->nfft == 1<<st->scale_shift) |
||||
st->scale = QCONST32(1.0f, 30); |
||||
else |
||||
st->scale = (((opus_int64)1073741824<<st->scale_shift)+st->nfft/2)/st->nfft; |
||||
# else |
||||
if (st->nfft == 1<<st->scale_shift) |
||||
st->scale = Q15ONE; |
||||
else |
||||
st->scale = (1073741824+st->nfft/2)/st->nfft>>(15-st->scale_shift); |
||||
# endif |
||||
#else |
||||
st->scale = 1.f/nfft; |
||||
#endif |
||||
if (base != NULL) |
||||
{ |
||||
st->twiddles = base->twiddles; |
||||
st->shift = 0; |
||||
while (st->shift < 32 && nfft<<st->shift != base->nfft) |
||||
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); |
||||
|
||||
/* Initialize architecture specific fft parameters */ |
||||
if (opus_fft_alloc_arch(st, arch)) |
||||
goto fail; |
||||
} |
||||
return st; |
||||
fail: |
||||
opus_fft_free(st, arch); |
||||
return NULL; |
||||
} |
||||
|
||||
kiss_fft_state *opus_fft_alloc(int nfft,void * mem,size_t * lenmem, int arch) |
||||
{ |
||||
return opus_fft_alloc_twiddles(nfft, mem, lenmem, NULL, arch); |
||||
} |
||||
|
||||
void opus_fft_free_arch_c(kiss_fft_state *st) { |
||||
(void)st; |
||||
} |
||||
|
||||
void opus_fft_free(const kiss_fft_state *cfg, int arch) |
||||
{ |
||||
if (cfg) |
||||
{ |
||||
opus_fft_free_arch((kiss_fft_state *)cfg, arch); |
||||
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 */ |
||||
|
||||
#ifdef FIXED_POINT |
||||
#ifndef OVERRIDE_fft_downshift |
||||
static void fft_downshift(kiss_fft_cpx *x, int N, int *total, int step) { |
||||
int shift; |
||||
shift = IMIN(step, *total); |
||||
*total -= shift; |
||||
if (shift == 1) { |
||||
int i; |
||||
for (i=0;i<N;i++) { |
||||
x[i].r = SHR32(x[i].r, 1); |
||||
x[i].i = SHR32(x[i].i, 1); |
||||
} |
||||
} else if (shift>0) { |
||||
int i; |
||||
for (i=0;i<N;i++) { |
||||
x[i].r = PSHR32(x[i].r, shift); |
||||
x[i].i = PSHR32(x[i].i, shift); |
||||
} |
||||
} |
||||
} |
||||
#endif /* OVERRIDE_fft_downshift */ |
||||
#else |
||||
#define fft_downshift(x, N, total, step) |
||||
#endif |
||||
|
||||
void opus_fft_impl(const kiss_fft_state *st,kiss_fft_cpx *fout ARG_FIXED(int downshift)) |
||||
{ |
||||
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; |
||||
|
||||
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: |
||||
fft_downshift(fout, st->nfft, &downshift, 1); |
||||
kf_bfly2(fout, m, fstride[i]); |
||||
break; |
||||
case 4: |
||||
fft_downshift(fout, st->nfft, &downshift, 2); |
||||
kf_bfly4(fout,fstride[i]<<shift,st,m, fstride[i], m2); |
||||
break; |
||||
#ifndef RADIX_TWO_ONLY |
||||
case 3: |
||||
fft_downshift(fout, st->nfft, &downshift, 2); |
||||
kf_bfly3(fout,fstride[i]<<shift,st,m, fstride[i], m2); |
||||
break; |
||||
case 5: |
||||
fft_downshift(fout, st->nfft, &downshift, 3); |
||||
kf_bfly5(fout,fstride[i]<<shift,st,m, fstride[i], m2); |
||||
break; |
||||
#endif |
||||
} |
||||
m = m2; |
||||
} |
||||
fft_downshift(fout, st->nfft, &downshift, downshift); |
||||
} |
||||
|
||||
void opus_fft_c(const kiss_fft_state *st,const kiss_fft_cpx *fin,kiss_fft_cpx *fout) |
||||
{ |
||||
int i; |
||||
celt_coef scale; |
||||
#ifdef FIXED_POINT |
||||
/* Allows us to scale with MULT16_32_Q16(), which is faster than
|
||||
MULT16_32_Q15() on ARM. */ |
||||
int scale_shift = st->scale_shift-1; |
||||
#endif |
||||
scale = st->scale; |
||||
|
||||
celt_assert2 (fin != fout, "In-place FFT not supported"); |
||||
/* Bit-reverse the input */ |
||||
for (i=0;i<st->nfft;i++) |
||||
{ |
||||
kiss_fft_cpx x = fin[i]; |
||||
fout[st->bitrev[i]].r = S_MUL2(x.r, scale); |
||||
fout[st->bitrev[i]].i = S_MUL2(x.i, scale); |
||||
} |
||||
opus_fft_impl(st, fout ARG_FIXED(scale_shift)); |
||||
} |
||||
|
||||
|
||||
void opus_ifft_c(const kiss_fft_state *st,const kiss_fft_cpx *fin,kiss_fft_cpx *fout) |
||||
{ |
||||
int i; |
||||
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]; |
||||
for (i=0;i<st->nfft;i++) |
||||
fout[i].i = -fout[i].i; |
||||
opus_fft_impl(st, fout ARG_FIXED(0)); |
||||
for (i=0;i<st->nfft;i++) |
||||
fout[i].i = -fout[i].i; |
||||
} |
||||
@ -0,0 +1,209 @@
|
||||
/*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" |
||||
#include "cpu_support.h" |
||||
|
||||
#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 |
||||
# ifdef ENABLE_QEXT |
||||
# define COEF_SHIFT 32 |
||||
# else |
||||
# define COEF_SHIFT 16 |
||||
# endif |
||||
|
||||
# define kiss_twiddle_scalar celt_coef |
||||
|
||||
/* Some 32-bit CPUs would load/store a kiss_twiddle_cpx with a single memory
|
||||
* access, and could benefit from additional alignment. |
||||
*/ |
||||
# define KISS_TWIDDLE_CPX_ALIGNMENT (sizeof(opus_int32)) |
||||
|
||||
#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 |
||||
|
||||
#if defined(__GNUC__) && defined(KISS_TWIDDLE_CPX_ALIGNMENT) |
||||
#define KISS_TWIDDLE_CPX_ALIGNED __attribute__((aligned(KISS_TWIDDLE_CPX_ALIGNMENT))) |
||||
#else |
||||
#define KISS_TWIDDLE_CPX_ALIGNED |
||||
#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_ALIGNED 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 arch_fft_state{ |
||||
int is_supported; |
||||
void *priv; |
||||
} arch_fft_state; |
||||
|
||||
typedef struct kiss_fft_state{ |
||||
int nfft; |
||||
celt_coef scale; |
||||
#ifdef FIXED_POINT |
||||
int scale_shift; |
||||
#endif |
||||
int shift; |
||||
opus_int16 factors[2*MAXFACTORS]; |
||||
const opus_int16 *bitrev; |
||||
const kiss_twiddle_cpx *twiddles; |
||||
arch_fft_state *arch_fft; |
||||
} kiss_fft_state; |
||||
|
||||
#if defined(HAVE_ARM_NE10) |
||||
#include "arm/fft_arm.h" |
||||
#endif |
||||
|
||||
/*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, int arch); |
||||
|
||||
kiss_fft_state *opus_fft_alloc(int nfft,void * mem,size_t * lenmem, int arch); |
||||
|
||||
/**
|
||||
* 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_c(const kiss_fft_state *cfg,const kiss_fft_cpx *fin,kiss_fft_cpx *fout); |
||||
void opus_ifft_c(const kiss_fft_state *cfg,const kiss_fft_cpx *fin,kiss_fft_cpx *fout); |
||||
|
||||
void opus_fft_impl(const kiss_fft_state *st,kiss_fft_cpx *fout ARG_FIXED(int downshift)); |
||||
void opus_ifft_impl(const kiss_fft_state *st,kiss_fft_cpx *fout); |
||||
|
||||
void opus_fft_free(const kiss_fft_state *cfg, int arch); |
||||
|
||||
|
||||
void opus_fft_free_arch_c(kiss_fft_state *st); |
||||
int opus_fft_alloc_arch_c(kiss_fft_state *st); |
||||
|
||||
#if !defined(OVERRIDE_OPUS_FFT) |
||||
/* Is run-time CPU detection enabled on this platform? */ |
||||
#if defined(OPUS_HAVE_RTCD) && (defined(HAVE_ARM_NE10)) |
||||
|
||||
extern int (*const OPUS_FFT_ALLOC_ARCH_IMPL[OPUS_ARCHMASK+1])( |
||||
kiss_fft_state *st); |
||||
|
||||
#define opus_fft_alloc_arch(_st, arch) \ |
||||
((*OPUS_FFT_ALLOC_ARCH_IMPL[(arch)&OPUS_ARCHMASK])(_st)) |
||||
|
||||
extern void (*const OPUS_FFT_FREE_ARCH_IMPL[OPUS_ARCHMASK+1])( |
||||
kiss_fft_state *st); |
||||
#define opus_fft_free_arch(_st, arch) \ |
||||
((*OPUS_FFT_FREE_ARCH_IMPL[(arch)&OPUS_ARCHMASK])(_st)) |
||||
|
||||
extern void (*const OPUS_FFT[OPUS_ARCHMASK+1])(const kiss_fft_state *cfg, |
||||
const kiss_fft_cpx *fin, kiss_fft_cpx *fout); |
||||
#define opus_fft(_cfg, _fin, _fout, arch) \ |
||||
((*OPUS_FFT[(arch)&OPUS_ARCHMASK])(_cfg, _fin, _fout)) |
||||
|
||||
extern void (*const OPUS_IFFT[OPUS_ARCHMASK+1])(const kiss_fft_state *cfg, |
||||
const kiss_fft_cpx *fin, kiss_fft_cpx *fout); |
||||
#define opus_ifft(_cfg, _fin, _fout, arch) \ |
||||
((*OPUS_IFFT[(arch)&OPUS_ARCHMASK])(_cfg, _fin, _fout)) |
||||
|
||||
#else /* else for if defined(OPUS_HAVE_RTCD) && (defined(HAVE_ARM_NE10)) */ |
||||
|
||||
#define opus_fft_alloc_arch(_st, arch) \ |
||||
((void)(arch), opus_fft_alloc_arch_c(_st)) |
||||
|
||||
#define opus_fft_free_arch(_st, arch) \ |
||||
((void)(arch), opus_fft_free_arch_c(_st)) |
||||
|
||||
#define opus_fft(_cfg, _fin, _fout, arch) \ |
||||
((void)(arch), opus_fft_c(_cfg, _fin, _fout)) |
||||
|
||||
#define opus_ifft(_cfg, _fin, _fout, arch) \ |
||||
((void)(arch), opus_ifft_c(_cfg, _fin, _fout)) |
||||
|
||||
#endif /* end if defined(OPUS_HAVE_RTCD) && (defined(HAVE_ARM_NE10)) */ |
||||
#endif /* end if !defined(OVERRIDE_OPUS_FFT) */ |
||||
|
||||
#endif |
||||
@ -0,0 +1,235 @@
|
||||
/* 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; |
||||
} |
||||
|
||||
void ec_laplace_encode_p0(ec_enc *enc, int value, opus_uint16 p0, opus_uint16 decay) |
||||
{ |
||||
int s; |
||||
opus_uint16 sign_icdf[3]; |
||||
sign_icdf[0] = 32768-p0; |
||||
sign_icdf[1] = sign_icdf[0]/2; |
||||
sign_icdf[2] = 0; |
||||
s = value == 0 ? 0 : (value > 0 ? 1 : 2); |
||||
ec_enc_icdf16(enc, s, sign_icdf, 15); |
||||
value = abs(value); |
||||
if (value) |
||||
{ |
||||
int i; |
||||
opus_uint16 icdf[8]; |
||||
icdf[0] = IMAX(7, decay); |
||||
for (i=1;i<7;i++) |
||||
{ |
||||
icdf[i] = IMAX(7-i, (icdf[i-1] * (opus_int32)decay) >> 15); |
||||
} |
||||
icdf[7] = 0; |
||||
value--; |
||||
do { |
||||
ec_enc_icdf16(enc, IMIN(value, 7), icdf, 15); |
||||
value -= 7; |
||||
} while (value >= 0); |
||||
} |
||||
} |
||||
|
||||
int ec_laplace_decode_p0(ec_dec *dec, opus_uint16 p0, opus_uint16 decay) |
||||
{ |
||||
int s; |
||||
int value; |
||||
opus_uint16 sign_icdf[3]; |
||||
sign_icdf[0] = 32768-p0; |
||||
sign_icdf[1] = sign_icdf[0]/2; |
||||
sign_icdf[2] = 0; |
||||
s = ec_dec_icdf16(dec, sign_icdf, 15); |
||||
if (s==2) s = -1; |
||||
if (s != 0) |
||||
{ |
||||
int i; |
||||
int v; |
||||
opus_uint16 icdf[8]; |
||||
icdf[0] = IMAX(7, decay); |
||||
for (i=1;i<7;i++) |
||||
{ |
||||
icdf[i] = IMAX(7-i, (icdf[i-1] * (opus_int32)decay) >> 15); |
||||
} |
||||
icdf[7] = 0; |
||||
value = 1; |
||||
do { |
||||
v = ec_dec_icdf16(dec, icdf, 15); |
||||
value += v; |
||||
} while (v == 7); |
||||
return s*value; |
||||
} else return 0; |
||||
} |
||||
|
||||
#if 0 |
||||
|
||||
#include <stdio.h> |
||||
#define NB_VALS 10 |
||||
#define DATA_SIZE 10000 |
||||
int main() { |
||||
ec_enc enc; |
||||
ec_dec dec; |
||||
unsigned char *ptr; |
||||
int i; |
||||
int decay, p0; |
||||
int val[NB_VALS] = {6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; |
||||
/*for (i=0;i<NB_VALS;i++) {
|
||||
val[i] = -log(rand()/(float)RAND_MAX); |
||||
if (rand()%2) val[i] = -val[i]; |
||||
}*/ |
||||
p0 = 16000; |
||||
decay = 16000; |
||||
ptr = (unsigned char *)malloc(DATA_SIZE); |
||||
ec_enc_init(&enc,ptr,DATA_SIZE); |
||||
for (i=0;i<NB_VALS;i++) { |
||||
printf("%d ", val[i]); |
||||
} |
||||
printf("\n"); |
||||
for (i=0;i<NB_VALS;i++) { |
||||
ec_laplace_encode_p0(&enc, val[i], p0, decay); |
||||
} |
||||
|
||||
ec_enc_done(&enc); |
||||
|
||||
ec_dec_init(&dec,ec_get_buffer(&enc),ec_range_bytes(&enc)); |
||||
|
||||
for (i=0;i<NB_VALS;i++) { |
||||
val[i] = ec_laplace_decode_p0(&dec, p0, decay); |
||||
} |
||||
for (i=0;i<NB_VALS;i++) { |
||||
printf("%d ", val[i]); |
||||
} |
||||
printf("\n"); |
||||
} |
||||
|
||||
#endif |
||||
@ -0,0 +1,57 @@
|
||||
/* 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. |
||||
*/ |
||||
|
||||
#ifndef LAPLACE_H |
||||
#define LAPLACE_H |
||||
|
||||
#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); |
||||
|
||||
|
||||
int ec_laplace_decode_p0(ec_dec *dec, opus_uint16 p0, opus_uint16 decay); |
||||
void ec_laplace_encode_p0(ec_enc *enc, int value, opus_uint16 p0, opus_uint16 decay); |
||||
|
||||
#endif |
||||
@ -0,0 +1,336 @@
|
||||
/* Copyright (c) 2002-2008 Jean-Marc Valin
|
||||
Copyright (c) 2007-2008 CSIRO |
||||
Copyright (c) 2007-2009 Xiph.Org Foundation |
||||
Copyright (c) 2024 Arm Limited |
||||
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 "float_cast.h" |
||||
#include "mathops.h" |
||||
|
||||
/*Compute floor(sqrt(_val)) with exact arithmetic.
|
||||
_val must be greater than 0. |
||||
This has been tested on all possible 32-bit inputs greater than 0.*/ |
||||
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_q29(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)); |
||||
return result; |
||||
} |
||||
|
||||
opus_val32 frac_div32(opus_val32 a, opus_val32 b) { |
||||
opus_val32 result = frac_div32_q29(a,b); |
||||
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)))); |
||||
} |
||||
|
||||
/** Reciprocal sqrt approximation in the range [0.25,1) (Q31 in, Q29 out) */ |
||||
opus_val32 celt_rsqrt_norm32(opus_val32 x) |
||||
{ |
||||
opus_int32 tmp; |
||||
/* Use the first-order Newton-Raphson method to refine the root estimate.
|
||||
* r = r * (1.5 - 0.5*x*r*r) */ |
||||
opus_int32 r_q29 = SHL32(celt_rsqrt_norm(SHR32(x, 31-16)), 15); |
||||
/* Split evaluation in steps to avoid exploding macro expansion. */ |
||||
tmp = MULT32_32_Q31(r_q29, r_q29); |
||||
tmp = MULT32_32_Q31(1073741824 /* Q31 */, tmp); |
||||
tmp = MULT32_32_Q31(x, tmp); |
||||
return SHL32(MULT32_32_Q31(r_q29, SUB32(201326592 /* Q27 */, tmp)), 4); |
||||
} |
||||
|
||||
/** Sqrt approximation (QX input, QX/2 output) */ |
||||
opus_val32 celt_sqrt(opus_val32 x) |
||||
{ |
||||
int k; |
||||
opus_val16 n; |
||||
opus_val32 rt; |
||||
/* These coeffs are optimized in fixed-point to minimize both RMS and max error
|
||||
of sqrt(x) over .25<x<1 without exceeding 32767. |
||||
The RMS error is 3.4e-5 and the max is 8.2e-5. */ |
||||
static const opus_val16 C[6] = {23171, 11574, -2901, 1592, -1002, 336}; |
||||
if (x==0) |
||||
return 0; |
||||
else if (x>=1073741824) |
||||
return 32767; |
||||
k = (celt_ilog2(x)>>1)-7; |
||||
x = VSHR32(x, 2*k); |
||||
n = x-32768; |
||||
rt = ADD32(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, ADD16(C[4], MULT16_16_Q15(n, (C[5]))))))))))); |
||||
rt = VSHR32(rt,7-k); |
||||
return rt; |
||||
} |
||||
|
||||
/* Perform fixed-point arithmetic to approximate the square root. When the input
|
||||
* is in Qx format, the output will be in Q(x/2 + 16) format. */ |
||||
opus_val32 celt_sqrt32(opus_val32 x) |
||||
{ |
||||
int k; |
||||
opus_int32 x_frac; |
||||
if (x==0) |
||||
return 0; |
||||
else if (x>=1073741824) |
||||
return 2147483647; /* 2^31 -1 */ |
||||
k = (celt_ilog2(x)>>1); |
||||
x_frac = VSHR32(x, 2*(k-14)-1); |
||||
x_frac = MULT32_32_Q31(celt_rsqrt_norm32(x_frac), x_frac); |
||||
if (k < 12) return PSHR32(x_frac, 12-k); |
||||
else return SHL32(x_frac, k-12); |
||||
} |
||||
|
||||
#define L1 32767 |
||||
#define L2 -7651 |
||||
#define L3 8277 |
||||
#define L4 -626 |
||||
|
||||
static OPUS_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 NEG16(_celt_cos_pi_2(EXTRACT16(65536-x))); |
||||
} |
||||
} else { |
||||
if (x&0x0000ffff) |
||||
return 0; |
||||
else if (x&0x0001ffff) |
||||
return -32767; |
||||
else |
||||
return 32767; |
||||
} |
||||
} |
||||
|
||||
/* Calculates the cosine of (PI*0.5*x) where the input x ranges from -1 to 1 and
|
||||
* is in Q30 format. The output will also be in Q31 format. */ |
||||
opus_val32 celt_cos_norm32(opus_val32 x) |
||||
{ |
||||
static const opus_val32 COS_NORM_COEFF_A0 = 134217720; /* Q27 */ |
||||
static const opus_val32 COS_NORM_COEFF_A1 = -662336704; /* Q29 */ |
||||
static const opus_val32 COS_NORM_COEFF_A2 = 544710848; /* Q31 */ |
||||
static const opus_val32 COS_NORM_COEFF_A3 = -178761936; /* Q33 */ |
||||
static const opus_val32 COS_NORM_COEFF_A4 = 29487206; /* Q35 */ |
||||
opus_int32 x_sq_q29, tmp; |
||||
/* The expected x is in the range of [-1.0f, 1.0f] */ |
||||
celt_sig_assert((x >= -1073741824) && (x <= 1073741824)); |
||||
/* Make cos(+/- pi/2) exactly zero. */ |
||||
if (ABS32(x) == 1<<30) return 0; |
||||
x_sq_q29 = MULT32_32_Q31(x, x); |
||||
/* Split evaluation in steps to avoid exploding macro expansion. */ |
||||
tmp = ADD32(COS_NORM_COEFF_A3, MULT32_32_Q31(x_sq_q29, COS_NORM_COEFF_A4)); |
||||
tmp = ADD32(COS_NORM_COEFF_A2, MULT32_32_Q31(x_sq_q29, tmp)); |
||||
tmp = ADD32(COS_NORM_COEFF_A1, MULT32_32_Q31(x_sq_q29, tmp)); |
||||
return SHL32(ADD32(COS_NORM_COEFF_A0, MULT32_32_Q31(x_sq_q29, tmp)), 4); |
||||
} |
||||
|
||||
/* Computes a 16 bit approximate reciprocal (1/x) for a normalized Q15 input,
|
||||
* resulting in a Q15 output. */ |
||||
opus_val16 celt_rcp_norm16(opus_val16 x) |
||||
{ |
||||
opus_val16 r; |
||||
/* 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, x)); |
||||
/* Perform two Newton iterations:
|
||||
r -= r*((r*n)+(r-1.Q15)) |
||||
= r*((r*n)+(r-1.Q15)). */ |
||||
r = SUB16(r, MULT16_16_Q15(r, |
||||
ADD16(MULT16_16_Q15(r, x), 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. */ |
||||
return SUB16(r, ADD16(1, MULT16_16_Q15(r, |
||||
ADD16(MULT16_16_Q15(r, x), ADD16(r, -32768))))); |
||||
} |
||||
|
||||
/* Computes a 32 bit approximated reciprocal (1/x) for a normalized Q31 input,
|
||||
* resulting in a Q30 output. The expected input range is [0.5f, 1.0f) in Q31 |
||||
* and the expected output range is [1.0f, 2.0f) in Q30. */ |
||||
opus_val32 celt_rcp_norm32(opus_val32 x) |
||||
{ |
||||
opus_val32 r_q30; |
||||
celt_sig_assert(x >= 1073741824); |
||||
r_q30 = SHL32(EXTEND32(celt_rcp_norm16(SHR32(x, 15)-32768)), 16); |
||||
/* Solving f(y) = a - 1/y using the Newton Method
|
||||
* Note: f(y)' = 1/y^2 |
||||
* r = r - f(r)/f(r)' = r - (x * r*r - r) |
||||
* = r - r*(r*x - 1) |
||||
* where |
||||
* - r means 1/y's approximation. |
||||
* - x means a, the input of function. |
||||
* Please note that: |
||||
* - It adds 1 to avoid overflow |
||||
* - -1.0f in Q30 is -1073741824. */ |
||||
return SUB32(r_q30, ADD32(SHL32( |
||||
MULT32_32_Q31(ADD32(MULT32_32_Q31(r_q30, x), -1073741824), |
||||
r_q30), 1), 1)); |
||||
} |
||||
|
||||
/** Reciprocal approximation (Q15 input, Q16 output) */ |
||||
opus_val32 celt_rcp(opus_val32 x) |
||||
{ |
||||
int i; |
||||
opus_val16 r; |
||||
celt_sig_assert(x>0); |
||||
i = celt_ilog2(x); |
||||
|
||||
/* Compute the reciprocal of a Q15 number in the range [0, 1). */ |
||||
r = celt_rcp_norm16(VSHR32(x,i-15)-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 |
||||
|
||||
#ifndef DISABLE_FLOAT_API |
||||
|
||||
void celt_float2int16_c(const float * OPUS_RESTRICT in, short * OPUS_RESTRICT out, int cnt) |
||||
{ |
||||
int i; |
||||
for (i = 0; i < cnt; i++) |
||||
{ |
||||
out[i] = FLOAT2INT16(in[i]); |
||||
} |
||||
} |
||||
|
||||
int opus_limit2_checkwithin1_c(float * samples, int cnt) |
||||
{ |
||||
int i; |
||||
if (cnt <= 0) |
||||
{ |
||||
return 1; |
||||
} |
||||
|
||||
for (i = 0; i < cnt; i++) |
||||
{ |
||||
float clippedVal = samples[i]; |
||||
clippedVal = FMAX(-2.0f, clippedVal); |
||||
clippedVal = FMIN(2.0f, clippedVal); |
||||
samples[i] = clippedVal; |
||||
} |
||||
|
||||
/* C implementation can't provide quick hint. Assume it might exceed -1/+1. */ |
||||
return 0; |
||||
} |
||||
|
||||
#endif /* DISABLE_FLOAT_API */ |
||||
@ -0,0 +1,662 @@
|
||||
/* Copyright (c) 2002-2008 Jean-Marc Valin
|
||||
Copyright (c) 2007-2008 CSIRO |
||||
Copyright (c) 2007-2009 Xiph.Org Foundation |
||||
Copyright (c) 2024 Arm Limited |
||||
Written by Jean-Marc Valin, and Yunho Huh */ |
||||
/**
|
||||
@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" |
||||
|
||||
|
||||
#if defined(OPUS_ARM_MAY_HAVE_NEON_INTR) |
||||
#include "arm/mathops_arm.h" |
||||
#endif |
||||
|
||||
#define PI 3.1415926535897931 |
||||
|
||||
/* 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); |
||||
|
||||
/* CELT doesn't need it for fixed-point, by analysis.c does. */ |
||||
#if !defined(FIXED_POINT) || defined(ANALYSIS_C) |
||||
#define cA 0.43157974f |
||||
#define cB 0.67848403f |
||||
#define cC 0.08595542f |
||||
#define cE ((float)PI/2) |
||||
static OPUS_INLINE float fast_atan2f(float y, float x) { |
||||
float x2, y2; |
||||
x2 = x*x; |
||||
y2 = y*y; |
||||
/* For very small values, we don't care about the answer, so
|
||||
we can just return 0. */ |
||||
if (x2 + y2 < 1e-18f) |
||||
{ |
||||
return 0; |
||||
} |
||||
if(x2<y2){ |
||||
float den = (y2 + cB*x2) * (y2 + cC*x2); |
||||
return -x*y*(y2 + cA*x2) / den + (y<0 ? -cE : cE); |
||||
}else{ |
||||
float den = (x2 + cB*y2) * (x2 + cC*y2); |
||||
return x*y*(x2 + cA*y2) / den + (y<0 ? -cE : cE) - (x*y<0 ? -cE : cE); |
||||
} |
||||
} |
||||
#undef cA |
||||
#undef cB |
||||
#undef cC |
||||
#undef cE |
||||
#endif |
||||
|
||||
|
||||
#ifndef OVERRIDE_CELT_MAXABS16 |
||||
static OPUS_INLINE opus_val32 celt_maxabs16(const opus_val16 *x, int len) |
||||
{ |
||||
int i; |
||||
opus_val16 maxval = 0; |
||||
opus_val16 minval = 0; |
||||
for (i=0;i<len;i++) |
||||
{ |
||||
maxval = MAX16(maxval, x[i]); |
||||
minval = MIN16(minval, x[i]); |
||||
} |
||||
return MAX32(EXTEND32(maxval),-EXTEND32(minval)); |
||||
} |
||||
#endif |
||||
|
||||
#if defined(ENABLE_RES24) && defined(FIXED_POINT) |
||||
static OPUS_INLINE opus_res celt_maxabs_res(const opus_res *x, int len) |
||||
{ |
||||
int i; |
||||
opus_res maxval = 0; |
||||
opus_res minval = 0; |
||||
for (i=0;i<len;i++) |
||||
{ |
||||
maxval = MAX32(maxval, x[i]); |
||||
minval = MIN32(minval, x[i]); |
||||
} |
||||
/* opus_res should never reach such amplitude, so we should be safe. */ |
||||
celt_sig_assert(minval != -2147483648); |
||||
return MAX32(maxval,-minval); |
||||
} |
||||
#else |
||||
#define celt_maxabs_res celt_maxabs16 |
||||
#endif |
||||
|
||||
|
||||
#ifndef OVERRIDE_CELT_MAXABS32 |
||||
#ifdef FIXED_POINT |
||||
static OPUS_INLINE opus_val32 celt_maxabs32(const opus_val32 *x, int len) |
||||
{ |
||||
int i; |
||||
opus_val32 maxval = 0; |
||||
opus_val32 minval = 0; |
||||
for (i=0;i<len;i++) |
||||
{ |
||||
maxval = MAX32(maxval, x[i]); |
||||
minval = MIN32(minval, x[i]); |
||||
} |
||||
return MAX32(maxval, -minval); |
||||
} |
||||
#else |
||||
#define celt_maxabs32(x,len) celt_maxabs16(x,len) |
||||
#endif |
||||
#endif |
||||
|
||||
#ifndef FIXED_POINT |
||||
/* Calculates the arctangent of x using a Remez approximation of order 15,
|
||||
* incorporating only odd-powered terms. */ |
||||
static OPUS_INLINE float celt_atan_norm(float x) |
||||
{ |
||||
#define ATAN2_2_OVER_PI 0.636619772367581f |
||||
float x_sq = x * x; |
||||
|
||||
/* Polynomial coefficients approximated in the [0, 1] range.
|
||||
* Lolremez command: lolremez --degree 6 --range "0:1" |
||||
* "(atan(sqrt(x))-sqrt(x))/(x*sqrt(x))" "1/(sqrt(x)*x)" |
||||
* Please note that ATAN2_COEFF_A01 is fixed to 1.0f. */ |
||||
#define ATAN2_COEFF_A03 -3.3331659436225891113281250000e-01f |
||||
#define ATAN2_COEFF_A05 1.99627041816711425781250000000e-01f |
||||
#define ATAN2_COEFF_A07 -1.3976582884788513183593750000e-01f |
||||
#define ATAN2_COEFF_A09 9.79423448443412780761718750000e-02f |
||||
#define ATAN2_COEFF_A11 -5.7773590087890625000000000000e-02f |
||||
#define ATAN2_COEFF_A13 2.30401363223791122436523437500e-02f |
||||
#define ATAN2_COEFF_A15 -4.3554059229791164398193359375e-03f |
||||
return ATAN2_2_OVER_PI * (x + x * x_sq * (ATAN2_COEFF_A03 |
||||
+ x_sq * (ATAN2_COEFF_A05 |
||||
+ x_sq * (ATAN2_COEFF_A07 |
||||
+ x_sq * (ATAN2_COEFF_A09 |
||||
+ x_sq * (ATAN2_COEFF_A11 |
||||
+ x_sq * (ATAN2_COEFF_A13 |
||||
+ x_sq * (ATAN2_COEFF_A15)))))))); |
||||
} |
||||
|
||||
/* Calculates the arctangent of y/x, returning an approximate value in radians.
|
||||
* Please refer to the linked wiki page (https://en.wikipedia.org/wiki/Atan2)
|
||||
* to learn how atan2 results are computed. */ |
||||
static OPUS_INLINE float celt_atan2p_norm(float y, float x) |
||||
{ |
||||
celt_sig_assert(x>=0 && y>=0); |
||||
|
||||
/* For very small values, we don't care about the answer. */ |
||||
if ((x*x + y*y) < 1e-18f) |
||||
{ |
||||
return 0; |
||||
} |
||||
|
||||
if (y < x) |
||||
{ |
||||
return celt_atan_norm(y / x); |
||||
} else { |
||||
return 1.f - celt_atan_norm(x / y); |
||||
} |
||||
} |
||||
#endif |
||||
|
||||
#if !defined(FIXED_POINT) || defined(ENABLE_QEXT) |
||||
/* Computes estimated cosine values for (PI/2 * x) using only terms with even
|
||||
* exponents. */ |
||||
static OPUS_INLINE float celt_cos_norm2(float x) |
||||
{ |
||||
float x_norm_sq; |
||||
int output_sign; |
||||
/* Restrict x to [-1, 3]. */ |
||||
x -= 4*floor(.25*(x+1)); |
||||
/* Negative sign for [1, 3]. */ |
||||
output_sign = 1 - 2*(x>1); |
||||
/* Restrict to [-1, 1]. */ |
||||
x -= 2*(x>1); |
||||
|
||||
/* The cosine function, cos(x), has a Taylor series representation consisting
|
||||
* exclusively of even-powered polynomial terms. */ |
||||
x_norm_sq = x * x; |
||||
|
||||
/* Polynomial coefficients approximated in the [0, 1] range using only terms
|
||||
* with even exponents. |
||||
* Lolremez command: lolremez --degree 4 --range 0:1 "cos(sqrt(x)*pi*0.5)" */ |
||||
#define COS_COEFF_A0 9.999999403953552246093750000000e-01f |
||||
#define COS_COEFF_A2 -1.233698248863220214843750000000000f |
||||
#define COS_COEFF_A4 2.536507546901702880859375000000e-01f |
||||
#define COS_COEFF_A6 -2.08106283098459243774414062500e-02f |
||||
#define COS_COEFF_A8 8.581906440667808055877685546875e-04f |
||||
return output_sign * (COS_COEFF_A0 + x_norm_sq * (COS_COEFF_A2 + |
||||
x_norm_sq * (COS_COEFF_A4 + |
||||
x_norm_sq * (COS_COEFF_A6 + |
||||
x_norm_sq * (COS_COEFF_A8))))); |
||||
} |
||||
|
||||
#endif |
||||
|
||||
#ifndef FIXED_POINT |
||||
|
||||
#define celt_sqrt(x) ((float)sqrt(x)) |
||||
#define celt_sqrt32(x) ((float)sqrt(x)) |
||||
#define celt_rsqrt(x) (1.f/celt_sqrt(x)) |
||||
#define celt_rsqrt_norm(x) (celt_rsqrt(x)) |
||||
#define celt_rsqrt_norm32(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)) |
||||
#define frac_div32_q29(a,b) frac_div32(a,b) |
||||
|
||||
#ifdef FLOAT_APPROX |
||||
/* Calculates the base-2 logarithm (log2(x)) of a number. It is designed for
|
||||
* systems using radix-2 floating-point representation, with the exponent |
||||
* located at bits 23 to 30 and an offset of 127. Note that special cases like |
||||
* denormalized numbers, positive/negative infinity, and NaN are not handled. |
||||
* log2(x) = log2(x^exponent * mantissa) |
||||
* = exponent + log2(mantissa) */ |
||||
|
||||
/* Log2 x normalization single precision coefficients calculated by
|
||||
* 1 / (1 + 0.125 * index). |
||||
* Coefficients in Double Precision |
||||
* double log2_x_norm_coeff[8] = { |
||||
* 1.0000000000000000000, 8.888888888888888e-01, |
||||
* 8.000000000000000e-01, 7.272727272727273e-01, |
||||
* 6.666666666666666e-01, 6.153846153846154e-01, |
||||
* 5.714285714285714e-01, 5.333333333333333e-01} */ |
||||
static const float log2_x_norm_coeff[8] = { |
||||
1.000000000000000000000000000f, 8.88888895511627197265625e-01f, |
||||
8.00000000000000000000000e-01f, 7.27272748947143554687500e-01f, |
||||
6.66666686534881591796875e-01f, 6.15384638309478759765625e-01f, |
||||
5.71428596973419189453125e-01f, 5.33333361148834228515625e-01f}; |
||||
|
||||
/* Log2 y normalization single precision coefficients calculated by
|
||||
* log2(1 + 0.125 * index). |
||||
* Coefficients in Double Precision |
||||
* double log2_y_norm_coeff[8] = { |
||||
* 0.0000000000000000000, 1.699250014423124e-01, |
||||
* 3.219280948873623e-01, 4.594316186372973e-01, |
||||
* 5.849625007211562e-01, 7.004397181410922e-01, |
||||
* 8.073549220576041e-01, 9.068905956085185e-01}; */ |
||||
static const float log2_y_norm_coeff[8] = { |
||||
0.0000000000000000000000000000f, 1.699250042438507080078125e-01f, |
||||
3.219280838966369628906250e-01f, 4.594316184520721435546875e-01f, |
||||
5.849624872207641601562500e-01f, 7.004396915435791015625000e-01f, |
||||
8.073549270629882812500000e-01f, 9.068905711174011230468750e-01f}; |
||||
|
||||
static OPUS_INLINE float celt_log2(float x) |
||||
{ |
||||
opus_int32 integer; |
||||
opus_int32 range_idx; |
||||
union { |
||||
float f; |
||||
opus_uint32 i; |
||||
} in; |
||||
in.f = x; |
||||
integer = (opus_int32)(in.i>>23)-127; |
||||
in.i = (opus_int32)in.i - (opus_int32)((opus_uint32)integer<<23); |
||||
|
||||
/* Normalize the mantissa range from [1, 2] to [1,1.125], and then shift x
|
||||
* by 1.0625 to [-0.0625, 0.0625]. */ |
||||
range_idx = (in.i >> 20) & 0x7; |
||||
in.f = in.f * log2_x_norm_coeff[range_idx] - 1.0625f; |
||||
|
||||
/* Polynomial coefficients approximated in the [1, 1.125] range.
|
||||
* Lolremez command: lolremez --degree 4 --range -0.0625:0.0625 |
||||
* "log(x+1.0625)/log(2)" |
||||
* Coefficients in Double Precision |
||||
* A0: 8.7462840624502679e-2 A1: 1.3578296070972002 |
||||
* A2: -6.3897703690210047e-1 A3: 4.0197125617419959e-1 |
||||
* A4: -2.8415445877832832e-1 */ |
||||
#define LOG2_COEFF_A0 8.74628424644470214843750000e-02f |
||||
#define LOG2_COEFF_A1 1.357829570770263671875000000000f |
||||
#define LOG2_COEFF_A2 -6.3897705078125000000000000e-01f |
||||
#define LOG2_COEFF_A3 4.01971250772476196289062500e-01f |
||||
#define LOG2_COEFF_A4 -2.8415444493293762207031250e-01f |
||||
in.f = LOG2_COEFF_A0 + in.f * (LOG2_COEFF_A1 |
||||
+ in.f * (LOG2_COEFF_A2 |
||||
+ in.f * (LOG2_COEFF_A3 |
||||
+ in.f * (LOG2_COEFF_A4)))); |
||||
return integer + in.f + log2_y_norm_coeff[range_idx]; |
||||
} |
||||
|
||||
/* Calculates an approximation of 2^x. The approximation was achieved by
|
||||
* employing a base-2 exponential function and utilizing a Remez approximation |
||||
* of order 5, ensuring a controlled relative error. |
||||
* exp2(x) = exp2(integer + fraction) |
||||
* = exp2(integer) * exp2(fraction) */ |
||||
static OPUS_INLINE float celt_exp2(float x) |
||||
{ |
||||
opus_int32 integer; |
||||
float frac; |
||||
union { |
||||
float f; |
||||
opus_uint32 i; |
||||
} res; |
||||
integer = (int)floor(x); |
||||
if (integer < -50) |
||||
return 0; |
||||
frac = x-integer; |
||||
|
||||
/* Polynomial coefficients approximated in the [0, 1] range.
|
||||
* Lolremez command: lolremez --degree 5 --range 0:1 |
||||
* "exp(x*0.693147180559945)" "exp(x*0.693147180559945)" |
||||
* NOTE: log(2) ~ 0.693147180559945 */ |
||||
#define EXP2_COEFF_A0 9.999999403953552246093750000000e-01f |
||||
#define EXP2_COEFF_A1 6.931530833244323730468750000000e-01f |
||||
#define EXP2_COEFF_A2 2.401536107063293457031250000000e-01f |
||||
#define EXP2_COEFF_A3 5.582631751894950866699218750000e-02f |
||||
#define EXP2_COEFF_A4 8.989339694380760192871093750000e-03f |
||||
#define EXP2_COEFF_A5 1.877576694823801517486572265625e-03f |
||||
res.f = EXP2_COEFF_A0 + frac * (EXP2_COEFF_A1 |
||||
+ frac * (EXP2_COEFF_A2 |
||||
+ frac * (EXP2_COEFF_A3 |
||||
+ frac * (EXP2_COEFF_A4 |
||||
+ frac * (EXP2_COEFF_A5))))); |
||||
res.i = (opus_uint32)((opus_int32)res.i + (opus_int32)((opus_uint32)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 |
||||
|
||||
#define celt_exp2_db celt_exp2 |
||||
#define celt_log2_db celt_log2 |
||||
|
||||
#define celt_sin(x) celt_cos_norm2((0.5f*PI) * (x) - 1.0f) |
||||
#define celt_log(x) (celt_log2(x) * 0.6931471805599453f) |
||||
#define celt_exp(x) (celt_exp2((x) * 1.4426950408889634f)) |
||||
|
||||
#endif |
||||
|
||||
#ifdef FIXED_POINT |
||||
|
||||
#include "os_support.h" |
||||
|
||||
#ifndef OVERRIDE_CELT_ILOG2 |
||||
/** Integer log in base2. Undefined for zero and negative numbers */ |
||||
static OPUS_INLINE opus_int16 celt_ilog2(opus_int32 x) |
||||
{ |
||||
celt_sig_assert(x>0); |
||||
return EC_ILOG(x)-1; |
||||
} |
||||
#endif |
||||
|
||||
|
||||
/** Integer log in base2. Defined for zero, but not for negative numbers */ |
||||
static OPUS_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_rsqrt_norm32(opus_val32 x); |
||||
|
||||
opus_val32 celt_sqrt(opus_val32 x); |
||||
|
||||
opus_val32 celt_sqrt32(opus_val32 x); |
||||
|
||||
opus_val16 celt_cos_norm(opus_val32 x); |
||||
|
||||
opus_val32 celt_cos_norm32(opus_val32 x); |
||||
|
||||
/** Base-2 logarithm approximation (log2(x)). (Q14 input, Q10 output) */ |
||||
static OPUS_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-10)), 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 SHL32(i-13,10)+SHR32(frac,14-10); |
||||
} |
||||
|
||||
/*
|
||||
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 |
||||
|
||||
static OPUS_INLINE opus_val32 celt_exp2_frac(opus_val16 x) |
||||
{ |
||||
opus_val16 frac; |
||||
frac = SHL16(x, 4); |
||||
return ADD16(D0, MULT16_16_Q15(frac, ADD16(D1, MULT16_16_Q15(frac, ADD16(D2 , MULT16_16_Q15(D3,frac)))))); |
||||
} |
||||
|
||||
#undef D0 |
||||
#undef D1 |
||||
#undef D2 |
||||
#undef D3 |
||||
|
||||
/** Base-2 exponential approximation (2^x). (Q10 input, Q16 output) */ |
||||
static OPUS_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 = celt_exp2_frac(x-SHL16(integer,10)); |
||||
return VSHR32(EXTEND32(frac), -integer-2); |
||||
} |
||||
|
||||
#ifdef ENABLE_QEXT |
||||
|
||||
/* Calculates the base-2 logarithm of a Q14 input value. The result is returned
|
||||
* in Q(DB_SHIFT). If the input value is 0, the function will output -32.0f. */ |
||||
static OPUS_INLINE opus_val32 celt_log2_db(opus_val32 x) { |
||||
/* Q30 */ |
||||
static const opus_val32 log2_x_norm_coeff[8] = { |
||||
1073741824, 954437184, 858993472, 780903168, |
||||
715827904, 660764224, 613566784, 572662336}; |
||||
/* Q24 */ |
||||
static const opus_val32 log2_y_norm_coeff[8] = { |
||||
0, 2850868, 5401057, 7707983, |
||||
9814042, 11751428, 13545168, 15215099}; |
||||
static const opus_val32 LOG2_COEFF_A0 = 1467383; /* Q24 */ |
||||
static const opus_val32 LOG2_COEFF_A1 = 182244800; /* Q27 */ |
||||
static const opus_val32 LOG2_COEFF_A2 = -21440512; /* Q25 */ |
||||
static const opus_val32 LOG2_COEFF_A3 = 107903336; /* Q28 */ |
||||
static const opus_val32 LOG2_COEFF_A4 = -610217024; /* Q31 */ |
||||
|
||||
opus_int32 integer, norm_coeff_idx, tmp; |
||||
opus_val32 mantissa; |
||||
if (x==0) { |
||||
return -536870912; /* -32.0f */ |
||||
} |
||||
integer = SUB32(celt_ilog2(x), 14); /* Q0 */ |
||||
mantissa = VSHR32(x, integer + 14 - 29); /* Q29 */ |
||||
norm_coeff_idx = SHR32(mantissa, 29 - 3) & 0x7; |
||||
/* mantissa is in Q28 (29 + Q_NORM_CONST - 31 where Q_NORM_CONST is Q30)
|
||||
* 285212672 (Q28) is 1.0625f. */ |
||||
mantissa = SUB32(MULT32_32_Q31(mantissa, log2_x_norm_coeff[norm_coeff_idx]), |
||||
285212672); |
||||
|
||||
/* q_a3(Q28): q_mantissa + q_a4 - 31
|
||||
* q_a2(Q25): q_mantissa + q_a3 - 31 |
||||
* q_a1(Q27): q_mantissa + q_a2 - 31 + 5 |
||||
* q_a0(Q24): q_mantissa + q_a1 - 31 |
||||
* where q_mantissa is Q28 */ |
||||
/* Split evaluation in steps to avoid exploding macro expansion. */ |
||||
tmp = MULT32_32_Q31(mantissa, LOG2_COEFF_A4); |
||||
tmp = MULT32_32_Q31(mantissa, ADD32(LOG2_COEFF_A3, tmp)); |
||||
tmp = SHL32(MULT32_32_Q31(mantissa, ADD32(LOG2_COEFF_A2, tmp)), 5 /* SHL32 for LOG2_COEFF_A1 */); |
||||
tmp = MULT32_32_Q31(mantissa, ADD32(LOG2_COEFF_A1, tmp)); |
||||
return ADD32(log2_y_norm_coeff[norm_coeff_idx], |
||||
ADD32(SHL32(integer, DB_SHIFT), |
||||
ADD32(LOG2_COEFF_A0, tmp))); |
||||
} |
||||
|
||||
/* Calculates exp2 for Q28 within a specific range (0 to 1.0) using fixed-point
|
||||
* arithmetic. The input number must be adjusted for Q DB_SHIFT. */ |
||||
static OPUS_INLINE opus_val32 celt_exp2_db_frac(opus_val32 x) |
||||
{ |
||||
/* Approximation constants. */ |
||||
static const opus_int32 EXP2_COEFF_A0 = 268435440; /* Q28 */ |
||||
static const opus_int32 EXP2_COEFF_A1 = 744267456; /* Q30 */ |
||||
static const opus_int32 EXP2_COEFF_A2 = 1031451904; /* Q32 */ |
||||
static const opus_int32 EXP2_COEFF_A3 = 959088832; /* Q34 */ |
||||
static const opus_int32 EXP2_COEFF_A4 = 617742720; /* Q36 */ |
||||
static const opus_int32 EXP2_COEFF_A5 = 516104352; /* Q38 */ |
||||
opus_int32 tmp; |
||||
/* Converts input value from Q24 to Q29. */ |
||||
opus_val32 x_q29 = SHL32(x, 29 - 24); |
||||
/* Split evaluation in steps to avoid exploding macro expansion. */ |
||||
tmp = ADD32(EXP2_COEFF_A4, MULT32_32_Q31(x_q29, EXP2_COEFF_A5)); |
||||
tmp = ADD32(EXP2_COEFF_A3, MULT32_32_Q31(x_q29, tmp)); |
||||
tmp = ADD32(EXP2_COEFF_A2, MULT32_32_Q31(x_q29, tmp)); |
||||
tmp = ADD32(EXP2_COEFF_A1, MULT32_32_Q31(x_q29, tmp)); |
||||
return ADD32(EXP2_COEFF_A0, MULT32_32_Q31(x_q29, tmp)); |
||||
} |
||||
|
||||
/* Calculates exp2 for Q16 using fixed-point arithmetic. The input number must
|
||||
* be adjusted for Q DB_SHIFT. */ |
||||
static OPUS_INLINE opus_val32 celt_exp2_db(opus_val32 x) |
||||
{ |
||||
int integer; |
||||
opus_val32 frac; |
||||
integer = SHR32(x,DB_SHIFT); |
||||
if (integer>14) |
||||
return 0x7f000000; |
||||
else if (integer <= -17) |
||||
return 0; |
||||
frac = celt_exp2_db_frac(x-SHL32(integer, DB_SHIFT)); /* Q28 */ |
||||
return VSHR32(frac, -integer + 28 - 16); /* Q16 */ |
||||
} |
||||
#else |
||||
|
||||
#define celt_log2_db(x) SHL32(EXTEND32(celt_log2(x)), DB_SHIFT-10) |
||||
#define celt_exp2_db_frac(x) SHL32(celt_exp2_frac(PSHR32(x, DB_SHIFT-10)), 14) |
||||
#define celt_exp2_db(x) celt_exp2(PSHR32(x, DB_SHIFT-10)) |
||||
|
||||
#endif |
||||
|
||||
|
||||
opus_val32 celt_rcp(opus_val32 x); |
||||
opus_val32 celt_rcp_norm32(opus_val32 x); |
||||
|
||||
#define celt_div(a,b) MULT32_32_Q31((opus_val32)(a),celt_rcp(b)) |
||||
|
||||
opus_val32 frac_div32_q29(opus_val32 a, opus_val32 b); |
||||
opus_val32 frac_div32(opus_val32 a, opus_val32 b); |
||||
|
||||
/* Computes atan(x) multiplied by 2/PI. The input value (x) should be within the
|
||||
* range of -1 to 1 and represented in Q30 format. The function will return the |
||||
* result in Q30 format. */ |
||||
static OPUS_INLINE opus_val32 celt_atan_norm(opus_val32 x) |
||||
{ |
||||
/* Approximation constants. */ |
||||
static const opus_int32 ATAN_2_OVER_PI = 1367130551; /* Q31 */ |
||||
static const opus_int32 ATAN_COEFF_A03 = -715791936; /* Q31 */ |
||||
static const opus_int32 ATAN_COEFF_A05 = 857391616; /* Q32 */ |
||||
static const opus_int32 ATAN_COEFF_A07 = -1200579328; /* Q33 */ |
||||
static const opus_int32 ATAN_COEFF_A09 = 1682636672; /* Q34 */ |
||||
static const opus_int32 ATAN_COEFF_A11 = -1985085440; /* Q35 */ |
||||
static const opus_int32 ATAN_COEFF_A13 = 1583306112; /* Q36 */ |
||||
static const opus_int32 ATAN_COEFF_A15 = -598602432; /* Q37 */ |
||||
opus_int32 x_sq_q30; |
||||
opus_int32 x_q31; |
||||
opus_int32 tmp; |
||||
/* The expected x is in the range of [-1.0f, 1.0f] */ |
||||
celt_sig_assert((x <= 1073741824) && (x >= -1073741824)); |
||||
|
||||
/* If x = 1.0f, returns 0.5f */ |
||||
if (x == 1073741824) |
||||
{ |
||||
return 536870912; /* 0.5f (Q30) */ |
||||
} |
||||
/* If x = 1.0f, returns 0.5f */ |
||||
if (x == -1073741824) |
||||
{ |
||||
return -536870912; /* -0.5f (Q30) */ |
||||
} |
||||
x_q31 = SHL32(x, 1); |
||||
x_sq_q30 = MULT32_32_Q31(x_q31, x); |
||||
/* Split evaluation in steps to avoid exploding macro expansion. */ |
||||
tmp = MULT32_32_Q31(x_sq_q30, ATAN_COEFF_A15); |
||||
tmp = MULT32_32_Q31(x_sq_q30, ADD32(ATAN_COEFF_A13, tmp)); |
||||
tmp = MULT32_32_Q31(x_sq_q30, ADD32(ATAN_COEFF_A11, tmp)); |
||||
tmp = MULT32_32_Q31(x_sq_q30, ADD32(ATAN_COEFF_A09, tmp)); |
||||
tmp = MULT32_32_Q31(x_sq_q30, ADD32(ATAN_COEFF_A07, tmp)); |
||||
tmp = MULT32_32_Q31(x_sq_q30, ADD32(ATAN_COEFF_A05, tmp)); |
||||
tmp = MULT32_32_Q31(x_sq_q30, ADD32(ATAN_COEFF_A03, tmp)); |
||||
tmp = ADD32(x, MULT32_32_Q31(x_q31, tmp)); |
||||
return MULT32_32_Q31(ATAN_2_OVER_PI, tmp); |
||||
} |
||||
|
||||
/* Calculates the arctangent of y/x, multiplies the result by 2/pi, and returns
|
||||
* the value in Q30 format. Both input values (x and y) must be within the range |
||||
* of 0 to 1 and represented in Q30 format. Inputs must be zero or greater, and |
||||
* at least one input must be non-zero. */ |
||||
static OPUS_INLINE opus_val32 celt_atan2p_norm(opus_val32 y, opus_val32 x) |
||||
{ |
||||
celt_sig_assert(x>=0 && y>=0); |
||||
if (y==0 && x==0) { |
||||
return 0; |
||||
} else if (y < x) { |
||||
return celt_atan_norm(SHR32(frac_div32(y, x), 1)); |
||||
} else { |
||||
celt_sig_assert(y > 0); |
||||
return 1073741824 /* 1.0f Q30 */ - |
||||
celt_atan_norm(SHR32(frac_div32(x, y), 1)); |
||||
} |
||||
} |
||||
|
||||
#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 OPUS_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 OPUS_INLINE opus_val16 celt_atan2p(opus_val16 y, opus_val16 x) |
||||
{ |
||||
if (x==0 && y==0) { |
||||
return 0; |
||||
} else 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 */ |
||||
|
||||
#ifndef DISABLE_FLOAT_API |
||||
|
||||
void celt_float2int16_c(const float * OPUS_RESTRICT in, short * OPUS_RESTRICT out, int cnt); |
||||
|
||||
#ifndef OVERRIDE_FLOAT2INT16 |
||||
#define celt_float2int16(in, out, cnt, arch) ((void)(arch), celt_float2int16_c(in, out, cnt)) |
||||
#endif |
||||
|
||||
int opus_limit2_checkwithin1_c(float *samples, int cnt); |
||||
|
||||
#ifndef OVERRIDE_LIMIT2_CHECKWITHIN1 |
||||
#define opus_limit2_checkwithin1(samples, cnt, arch) ((void)(arch), opus_limit2_checkwithin1_c(samples, cnt)) |
||||
#endif |
||||
|
||||
#endif /* DISABLE_FLOAT_API */ |
||||
|
||||
#endif /* MATHOPS_H */ |
||||
@ -0,0 +1,390 @@
|
||||
/* 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" |
||||
|
||||
#if defined(FIXED_POINT) && defined(__mips) && __mips == 32 |
||||
#include "mips/mdct_mipsr1.h" |
||||
#endif |
||||
|
||||
#ifndef M_PI |
||||
#define M_PI 3.141592653 |
||||
#endif |
||||
|
||||
#ifdef CUSTOM_MODES |
||||
|
||||
int clt_mdct_init(mdct_lookup *l,int N, int maxshift, int arch) |
||||
{ |
||||
int i; |
||||
kiss_twiddle_scalar *trig; |
||||
int shift; |
||||
int N2=N>>1; |
||||
l->n = N; |
||||
l->maxshift = maxshift; |
||||
for (i=0;i<=maxshift;i++) |
||||
{ |
||||
if (i==0) |
||||
l->kfft[i] = opus_fft_alloc(N>>2>>i, 0, 0, arch); |
||||
else |
||||
l->kfft[i] = opus_fft_alloc_twiddles(N>>2>>i, 0, 0, l->kfft[0], arch); |
||||
#ifndef ENABLE_TI_DSPLIB55 |
||||
if (l->kfft[i]==NULL) |
||||
return 0; |
||||
#endif |
||||
} |
||||
l->trig = trig = (kiss_twiddle_scalar*)opus_alloc((N-(N2>>maxshift))*sizeof(kiss_twiddle_scalar)); |
||||
if (l->trig==NULL) |
||||
return 0; |
||||
for (shift=0;shift<=maxshift;shift++) |
||||
{ |
||||
/* We have enough points that sine isn't necessary */ |
||||
#if defined(FIXED_POINT) |
||||
#ifndef ENABLE_QEXT |
||||
for (i=0;i<N2;i++) |
||||
trig[i] = TRIG_UPSCALE*celt_cos_norm(DIV32(ADD32(SHL32(EXTEND32(i),17),N2+16384),N)); |
||||
#else |
||||
for (i=0;i<N2;i++) |
||||
trig[i] = (kiss_twiddle_scalar)MAX32(-2147483647,MIN32(2147483647,floor(.5+2147483648*cos(2*M_PI*(i+.125)/N)))); |
||||
#endif |
||||
#else |
||||
for (i=0;i<N2;i++) |
||||
trig[i] = (kiss_twiddle_scalar)cos(2*PI*(i+.125)/N); |
||||
#endif |
||||
trig += N2; |
||||
N2 >>= 1; |
||||
N >>= 1; |
||||
} |
||||
return 1; |
||||
} |
||||
|
||||
void clt_mdct_clear(mdct_lookup *l, int arch) |
||||
{ |
||||
int i; |
||||
for (i=0;i<=l->maxshift;i++) |
||||
opus_fft_free(l->kfft[i], arch); |
||||
opus_free((kiss_twiddle_scalar*)l->trig); |
||||
} |
||||
|
||||
#endif /* CUSTOM_MODES */ |
||||
|
||||
/* Forward MDCT trashes the input array */ |
||||
#ifndef OVERRIDE_clt_mdct_forward |
||||
void clt_mdct_forward_c(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_scalar * OPUS_RESTRICT out, |
||||
const celt_coef *window, int overlap, int shift, int stride, int arch) |
||||
{ |
||||
int i; |
||||
int N, N2, N4; |
||||
VARDECL(kiss_fft_scalar, f); |
||||
VARDECL(kiss_fft_cpx, f2); |
||||
const kiss_fft_state *st = l->kfft[shift]; |
||||
const kiss_twiddle_scalar *trig; |
||||
celt_coef scale; |
||||
#ifdef FIXED_POINT |
||||
/* Allows us to scale with MULT16_32_Q16(), which is faster than
|
||||
MULT16_32_Q15() on ARM. */ |
||||
int scale_shift = st->scale_shift-1; |
||||
int headroom; |
||||
#endif |
||||
SAVE_STACK; |
||||
(void)arch; |
||||
scale = st->scale; |
||||
|
||||
N = l->n; |
||||
trig = l->trig; |
||||
for (i=0;i<shift;i++) |
||||
{ |
||||
N >>= 1; |
||||
trig += N; |
||||
} |
||||
N2 = N>>1; |
||||
N4 = N>>2; |
||||
|
||||
ALLOC(f, N2, kiss_fft_scalar); |
||||
ALLOC(f2, N4, kiss_fft_cpx); |
||||
|
||||
/* 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 celt_coef * OPUS_RESTRICT wp1 = window+(overlap>>1); |
||||
const celt_coef * OPUS_RESTRICT wp2 = window+(overlap>>1)-1; |
||||
for(i=0;i<((overlap+3)>>2);i++) |
||||
{ |
||||
/* Real part arranged as -d-cR, Imag part arranged as -b+aR*/ |
||||
*yp++ = S_MUL(xp1[N2], *wp2) + S_MUL(*xp2, *wp1); |
||||
*yp++ = S_MUL(*xp1, *wp1) - S_MUL(xp2[-N2], *wp2); |
||||
xp1+=2; |
||||
xp2-=2; |
||||
wp1+=2; |
||||
wp2-=2; |
||||
} |
||||
wp1 = window; |
||||
wp2 = window+overlap-1; |
||||
for(;i<N4-((overlap+3)>>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++ = -S_MUL(xp1[-N2], *wp1) + S_MUL(*xp2, *wp2); |
||||
*yp++ = S_MUL(*xp1, *wp2) + S_MUL(xp2[N2], *wp1); |
||||
xp1+=2; |
||||
xp2-=2; |
||||
wp1+=2; |
||||
wp2-=2; |
||||
} |
||||
} |
||||
/* Pre-rotation */ |
||||
{ |
||||
kiss_fft_scalar * OPUS_RESTRICT yp = f; |
||||
const kiss_twiddle_scalar *t = &trig[0]; |
||||
#ifdef FIXED_POINT |
||||
opus_val32 maxval=1; |
||||
#endif |
||||
for(i=0;i<N4;i++) |
||||
{ |
||||
kiss_fft_cpx yc; |
||||
kiss_twiddle_scalar t0, t1; |
||||
kiss_fft_scalar re, im, yr, yi; |
||||
t0 = t[i]; |
||||
t1 = t[N4+i]; |
||||
re = *yp++; |
||||
im = *yp++; |
||||
yr = S_MUL(re,t0) - S_MUL(im,t1); |
||||
yi = S_MUL(im,t0) + S_MUL(re,t1); |
||||
/* For QEXT, it's best to scale before the FFT, but otherwise it's best to scale after.
|
||||
For floating-point it doesn't matter. */ |
||||
#ifdef ENABLE_QEXT |
||||
yc.r = yr; |
||||
yc.i = yi; |
||||
#else |
||||
yc.r = S_MUL2(yr, scale); |
||||
yc.i = S_MUL2(yi, scale); |
||||
#endif |
||||
#ifdef FIXED_POINT |
||||
maxval = MAX32(maxval, MAX32(ABS32(yc.r), ABS32(yc.i))); |
||||
#endif |
||||
f2[st->bitrev[i]] = yc; |
||||
} |
||||
#ifdef FIXED_POINT |
||||
headroom = IMAX(0, IMIN(scale_shift, 28-celt_ilog2(maxval))); |
||||
#endif |
||||
} |
||||
|
||||
/* N/4 complex FFT, does not downscale anymore */ |
||||
opus_fft_impl(st, f2 ARG_FIXED(scale_shift-headroom)); |
||||
|
||||
/* Post-rotate */ |
||||
{ |
||||
/* Temp pointers to make it really clear to the compiler what we're doing */ |
||||
const kiss_fft_cpx * OPUS_RESTRICT fp = f2; |
||||
kiss_fft_scalar * OPUS_RESTRICT yp1 = out; |
||||
kiss_fft_scalar * OPUS_RESTRICT yp2 = out+stride*(N2-1); |
||||
const kiss_twiddle_scalar *t = &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; |
||||
kiss_fft_scalar t0, t1; |
||||
#ifdef ENABLE_QEXT |
||||
t0 = S_MUL2(t[i], scale); |
||||
t1 = S_MUL2(t[N4+i], scale); |
||||
#else |
||||
t0 = t[i]; |
||||
t1 = t[N4+i]; |
||||
#endif |
||||
yr = PSHR32(S_MUL(fp->i,t1) - S_MUL(fp->r,t0), headroom); |
||||
yi = PSHR32(S_MUL(fp->r,t1) + S_MUL(fp->i,t0), headroom); |
||||
*yp1 = yr; |
||||
*yp2 = yi; |
||||
fp++; |
||||
yp1 += 2*stride; |
||||
yp2 -= 2*stride; |
||||
} |
||||
} |
||||
RESTORE_STACK; |
||||
} |
||||
#endif /* OVERRIDE_clt_mdct_forward */ |
||||
|
||||
#ifndef OVERRIDE_clt_mdct_backward |
||||
void clt_mdct_backward_c(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_scalar * OPUS_RESTRICT out, |
||||
const celt_coef * OPUS_RESTRICT window, int overlap, int shift, int stride, int arch) |
||||
{ |
||||
int i; |
||||
int N, N2, N4; |
||||
const kiss_twiddle_scalar *trig; |
||||
#ifdef FIXED_POINT |
||||
int pre_shift, post_shift, fft_shift; |
||||
#endif |
||||
(void) arch; |
||||
|
||||
N = l->n; |
||||
trig = l->trig; |
||||
for (i=0;i<shift;i++) |
||||
{ |
||||
N >>= 1; |
||||
trig += N; |
||||
} |
||||
N2 = N>>1; |
||||
N4 = N>>2; |
||||
|
||||
#ifdef FIXED_POINT |
||||
{ |
||||
opus_val32 sumval=N2; |
||||
opus_val32 maxval=0; |
||||
for (i=0;i<N2;i++) { |
||||
maxval = MAX32(maxval, ABS32(in[i*stride])); |
||||
sumval = ADD32_ovflw(sumval, ABS32(SHR32(in[i*stride],11))); |
||||
} |
||||
pre_shift = IMAX(0, 29-celt_zlog2(1+maxval)); |
||||
/* Worst-case where all the energy goes to a single sample. */ |
||||
post_shift = IMAX(0, 19-celt_ilog2(ABS32(sumval))); |
||||
post_shift = IMIN(post_shift, pre_shift); |
||||
fft_shift = pre_shift - post_shift; |
||||
} |
||||
#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 = out+(overlap>>1); |
||||
const kiss_twiddle_scalar * OPUS_RESTRICT t = &trig[0]; |
||||
const opus_int16 * OPUS_RESTRICT bitrev = l->kfft[shift]->bitrev; |
||||
for(i=0;i<N4;i++) |
||||
{ |
||||
int rev; |
||||
kiss_fft_scalar yr, yi; |
||||
opus_val32 x1, x2; |
||||
rev = *bitrev++; |
||||
x1 = SHL32_ovflw(*xp1, pre_shift); |
||||
x2 = SHL32_ovflw(*xp2, pre_shift); |
||||
yr = ADD32_ovflw(S_MUL(x2, t[i]), S_MUL(x1, t[N4+i])); |
||||
yi = SUB32_ovflw(S_MUL(x1, t[i]), S_MUL(x2, t[N4+i])); |
||||
/* We swap real and imag because we use an FFT instead of an IFFT. */ |
||||
yp[2*rev+1] = yr; |
||||
yp[2*rev] = yi; |
||||
/* Storing the pre-rotation directly in the bitrev order. */ |
||||
xp1+=2*stride; |
||||
xp2-=2*stride; |
||||
} |
||||
} |
||||
|
||||
opus_fft_impl(l->kfft[shift], (kiss_fft_cpx*)(out+(overlap>>1)) ARG_FIXED(fft_shift)); |
||||
|
||||
/* Post-rotate and de-shuffle from both ends of the buffer at once to make
|
||||
it in-place. */ |
||||
{ |
||||
kiss_fft_scalar * yp0 = out+(overlap>>1); |
||||
kiss_fft_scalar * yp1 = out+(overlap>>1)+N2-2; |
||||
const kiss_twiddle_scalar *t = &trig[0]; |
||||
/* Loop to (N4+1)>>1 to handle odd N4. When N4 is odd, the
|
||||
middle pair will be computed twice. */ |
||||
for(i=0;i<(N4+1)>>1;i++) |
||||
{ |
||||
kiss_fft_scalar re, im, yr, yi; |
||||
kiss_twiddle_scalar t0, t1; |
||||
/* We swap real and imag because we're using an FFT instead of an IFFT. */ |
||||
re = yp0[1]; |
||||
im = yp0[0]; |
||||
t0 = t[i]; |
||||
t1 = t[N4+i]; |
||||
/* We'd scale up by 2 here, but instead it's done when mixing the windows */ |
||||
yr = PSHR32_ovflw(ADD32_ovflw(S_MUL(re,t0), S_MUL(im,t1)), post_shift); |
||||
yi = PSHR32_ovflw(SUB32_ovflw(S_MUL(re,t1), S_MUL(im,t0)), post_shift); |
||||
/* We swap real and imag because we're using an FFT instead of an IFFT. */ |
||||
re = yp1[1]; |
||||
im = yp1[0]; |
||||
yp0[0] = yr; |
||||
yp1[1] = yi; |
||||
|
||||
t0 = t[(N4-i-1)]; |
||||
t1 = t[(N2-i-1)]; |
||||
/* We'd scale up by 2 here, but instead it's done when mixing the windows */ |
||||
yr = PSHR32_ovflw(ADD32_ovflw(S_MUL(re,t0), S_MUL(im,t1)), post_shift); |
||||
yi = PSHR32_ovflw(SUB32_ovflw(S_MUL(re,t1), S_MUL(im,t0)), post_shift); |
||||
yp1[0] = yr; |
||||
yp0[1] = yi; |
||||
yp0 += 2; |
||||
yp1 -= 2; |
||||
} |
||||
} |
||||
|
||||
/* Mirror on both sides for TDAC */ |
||||
{ |
||||
kiss_fft_scalar * OPUS_RESTRICT xp1 = out+overlap-1; |
||||
kiss_fft_scalar * OPUS_RESTRICT yp1 = out; |
||||
const celt_coef * OPUS_RESTRICT wp1 = window; |
||||
const celt_coef * OPUS_RESTRICT wp2 = window+overlap-1; |
||||
|
||||
for(i = 0; i < overlap/2; i++) |
||||
{ |
||||
kiss_fft_scalar x1, x2; |
||||
x1 = *xp1; |
||||
x2 = *yp1; |
||||
*yp1++ = SUB32_ovflw(S_MUL(x2, *wp2), S_MUL(x1, *wp1)); |
||||
*xp1-- = ADD32_ovflw(S_MUL(x2, *wp1), S_MUL(x1, *wp2)); |
||||
wp1++; |
||||
wp2--; |
||||
} |
||||
} |
||||
} |
||||
#endif /* OVERRIDE_clt_mdct_backward */ |
||||
@ -0,0 +1,111 @@
|
||||
/* 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; |
||||
|
||||
#if defined(HAVE_ARM_NE10) |
||||
#include "arm/mdct_arm.h" |
||||
#endif |
||||
|
||||
int clt_mdct_init(mdct_lookup *l,int N, int maxshift, int arch); |
||||
void clt_mdct_clear(mdct_lookup *l, int arch); |
||||
|
||||
/** Compute a forward MDCT and scale by 4/N, trashes the input array */ |
||||
void clt_mdct_forward_c(const mdct_lookup *l, kiss_fft_scalar *in, |
||||
kiss_fft_scalar * OPUS_RESTRICT out, |
||||
const celt_coef *window, int overlap, |
||||
int shift, int stride, int arch); |
||||
|
||||
/** Compute a backward MDCT (no scaling) and performs weighted overlap-add
|
||||
(scales implicitly by 1/2) */ |
||||
void clt_mdct_backward_c(const mdct_lookup *l, kiss_fft_scalar *in, |
||||
kiss_fft_scalar * OPUS_RESTRICT out, |
||||
const celt_coef * OPUS_RESTRICT window, |
||||
int overlap, int shift, int stride, int arch); |
||||
|
||||
#if !defined(OVERRIDE_OPUS_MDCT) |
||||
/* Is run-time CPU detection enabled on this platform? */ |
||||
#if defined(OPUS_HAVE_RTCD) && defined(HAVE_ARM_NE10) |
||||
|
||||
extern void (*const CLT_MDCT_FORWARD_IMPL[OPUS_ARCHMASK+1])( |
||||
const mdct_lookup *l, kiss_fft_scalar *in, |
||||
kiss_fft_scalar * OPUS_RESTRICT out, const celt_coef *window, |
||||
int overlap, int shift, int stride, int arch); |
||||
|
||||
#define clt_mdct_forward(_l, _in, _out, _window, _overlap, _shift, _stride, _arch) \ |
||||
((*CLT_MDCT_FORWARD_IMPL[(arch)&OPUS_ARCHMASK])(_l, _in, _out, \
|
||||
_window, _overlap, _shift, \
|
||||
_stride, _arch)) |
||||
|
||||
extern void (*const CLT_MDCT_BACKWARD_IMPL[OPUS_ARCHMASK+1])( |
||||
const mdct_lookup *l, kiss_fft_scalar *in, |
||||
kiss_fft_scalar * OPUS_RESTRICT out, const celt_coef *window, |
||||
int overlap, int shift, int stride, int arch); |
||||
|
||||
#define clt_mdct_backward(_l, _in, _out, _window, _overlap, _shift, _stride, _arch) \ |
||||
(*CLT_MDCT_BACKWARD_IMPL[(arch)&OPUS_ARCHMASK])(_l, _in, _out, \
|
||||
_window, _overlap, _shift, \
|
||||
_stride, _arch) |
||||
|
||||
#else /* if defined(OPUS_HAVE_RTCD) && defined(HAVE_ARM_NE10) */ |
||||
|
||||
#define clt_mdct_forward(_l, _in, _out, _window, _overlap, _shift, _stride, _arch) \ |
||||
clt_mdct_forward_c(_l, _in, _out, _window, _overlap, _shift, _stride, _arch) |
||||
|
||||
#define clt_mdct_backward(_l, _in, _out, _window, _overlap, _shift, _stride, _arch) \ |
||||
clt_mdct_backward_c(_l, _in, _out, _window, _overlap, _shift, _stride, _arch) |
||||
|
||||
#endif /* end if defined(OPUS_HAVE_RTCD) && defined(HAVE_ARM_NE10) && !defined(FIXED_POINT) */ |
||||
#endif /* end if !defined(OVERRIDE_OPUS_MDCT) */ |
||||
|
||||
#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,520 @@
|
||||
/* 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" |
||||
#include "cpu_support.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.1415926535897931 |
||||
#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) |
||||
{ |
||||
mode->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; |
||||
celt_coef *window; |
||||
opus_int16 *logN; |
||||
int LM; |
||||
int arch = opus_select_arch(); |
||||
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; |
||||
} |
||||
#ifdef ENABLE_QEXT |
||||
if (frame_size < 40 || frame_size > 2048 || frame_size%2!=0) |
||||
#else |
||||
if (frame_size < 40 || frame_size > 1024 || frame_size%2!=0) |
||||
#endif |
||||
{ |
||||
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. */ |
||||
#ifdef ENABLE_QEXT |
||||
if(Fs == 96000) /* 96 kHz */ |
||||
{ |
||||
mode->preemph[0] = QCONST16(0.9230041504f, 15); |
||||
mode->preemph[1] = QCONST16(0.2200012207f, 15); |
||||
mode->preemph[2] = QCONST16(1.5128347184f, SIG_SHIFT); /* exact 1/preemph[3] */ |
||||
mode->preemph[3] = QCONST16(0.6610107422f, 13); |
||||
} else |
||||
#endif |
||||
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; |
||||
#if !defined(SMALL_FOOTPRINT) |
||||
/* Make sure we don't allocate a band larger than our PVQ table.
|
||||
208 should be enough, but let's be paranoid. */ |
||||
if ((mode->eBands[mode->nbEBands] - mode->eBands[mode->nbEBands-1])<<LM > |
||||
208) { |
||||
goto failure; |
||||
} |
||||
#endif |
||||
|
||||
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 = (celt_coef*)opus_alloc(mode->overlap*sizeof(*window)); |
||||
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 |
||||
# ifdef ENABLE_QEXT |
||||
for (i=0;i<mode->overlap;i++) |
||||
window[i] = MIN32(2147483647, 2147483648*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 |
||||
#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); |
||||
#ifdef ENABLE_QEXT |
||||
OPUS_CLEAR(&mode->qext_cache, 1); |
||||
if ( (mode->Fs == 48000 && (mode->shortMdctSize==120 || mode->shortMdctSize==90)) || (mode->Fs == 96000 && (mode->shortMdctSize==240 || mode->shortMdctSize==180)) ) { |
||||
CELTMode dummy; |
||||
compute_qext_mode(&dummy, mode); |
||||
compute_pulse_cache(&dummy, dummy.maxLM); |
||||
OPUS_COPY(&mode->qext_cache, &dummy.cache, 1); |
||||
} |
||||
#endif |
||||
|
||||
if (clt_mdct_init(&mode->mdct, 2*mode->shortMdctSize*mode->nbShortMdcts, |
||||
mode->maxLM, arch) == 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 */ |
||||
} |
||||
|
||||
#if defined(CUSTOM_MODES) || defined(ENABLE_OPUS_CUSTOM_API) |
||||
void opus_custom_mode_destroy(CELTMode *mode) |
||||
{ |
||||
int arch = opus_select_arch(); |
||||
|
||||
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 */ |
||||
#ifdef CUSTOM_MODES |
||||
#ifdef ENABLE_QEXT |
||||
if (mode->qext_cache.index) opus_free((opus_int16*)mode->qext_cache.index); |
||||
if (mode->qext_cache.bits) opus_free((unsigned char*)mode->qext_cache.bits); |
||||
if (mode->qext_cache.caps) opus_free((unsigned char*)mode->qext_cache.caps); |
||||
#endif |
||||
opus_free((opus_int16*)mode->eBands); |
||||
opus_free((unsigned char*)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, arch); |
||||
|
||||
opus_free((CELTMode *)mode); |
||||
#else |
||||
(void)arch; |
||||
celt_assert(0); |
||||
#endif |
||||
} |
||||
#endif |
||||
|
||||
#ifdef ENABLE_QEXT |
||||
|
||||
static const opus_int16 qext_eBands_180[] = { |
||||
/* 20k 22k 24k 26k 28k 30k 32k 34k 36k 38k 40k 42k 44k 47k 48k */ |
||||
74, 82, 90, 98, 106, 114, 122, 130, 138, 146, 154, 162, 168, 174, 180 |
||||
}; |
||||
|
||||
static const opus_int16 qext_logN_180[] = {24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 21, 21, 21}; |
||||
|
||||
/* Extra bands. */ |
||||
static const opus_int16 qext_eBands_240[] = { |
||||
/* 20k 22k 24k 26k 28k 30k 32k 34k 36k 38k 40k 42k 44k 47k 48k */ |
||||
100, 110, 120, 130, 140, 150, 160, 170, 180, 190, 200, 210, 220, 230, 240 |
||||
}; |
||||
|
||||
static const opus_int16 qext_logN_240[] = {27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27}; |
||||
|
||||
void compute_qext_mode(CELTMode *qext, const CELTMode *m) |
||||
{ |
||||
OPUS_COPY(qext, m, 1); |
||||
if (m->shortMdctSize*48000 == 120*m->Fs) { |
||||
qext->eBands = qext_eBands_240; |
||||
qext->logN = qext_logN_240; |
||||
} else if (m->shortMdctSize*48000 == 90*m->Fs) { |
||||
qext->eBands = qext_eBands_180; |
||||
qext->logN = qext_logN_180; |
||||
} else { |
||||
celt_assert(0); |
||||
} |
||||
qext->nbEBands = qext->effEBands = NB_QEXT_BANDS; |
||||
while (qext->eBands[qext->effEBands] > qext->shortMdctSize) |
||||
qext->effEBands--; |
||||
qext->nbAllocVectors = 0; |
||||
qext->allocVectors = NULL; |
||||
OPUS_COPY(&qext->cache, &m->qext_cache, 1); |
||||
} |
||||
#endif |
||||
@ -0,0 +1,85 @@
|
||||
/* 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 |
||||
|
||||
#define DEC_PITCH_BUF_SIZE 2048 |
||||
|
||||
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 celt_coef *window; |
||||
mdct_lookup mdct; |
||||
PulseCache cache; |
||||
#ifdef ENABLE_QEXT |
||||
PulseCache qext_cache; |
||||
#endif |
||||
}; |
||||
|
||||
#ifdef ENABLE_QEXT |
||||
#define QEXT_PACKET_SIZE_CAP 3825 |
||||
#define NB_QEXT_BANDS 14 |
||||
void compute_qext_mode(CELTMode *qext, const CELTMode *m); |
||||
#endif |
||||
|
||||
#endif |
||||
@ -0,0 +1,98 @@
|
||||
/* 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 "opus_types.h" |
||||
#include "opus_defines.h" |
||||
|
||||
#include <string.h> |
||||
#include <stdlib.h> |
||||
|
||||
/** Opus wrapper for malloc(). To do your own dynamic allocation replace this function, opus_realloc, and opus_free */ |
||||
#ifndef OVERRIDE_OPUS_ALLOC |
||||
static OPUS_INLINE void *opus_alloc (size_t size) |
||||
{ |
||||
return malloc(size); |
||||
} |
||||
#endif |
||||
|
||||
#ifndef OVERRIDE_OPUS_REALLOC |
||||
static OPUS_INLINE void *opus_realloc (void *ptr, size_t size) |
||||
{ |
||||
return realloc(ptr, size); |
||||
} |
||||
#endif |
||||
|
||||
/** Used only for non-threadsafe pseudostack.
|
||||
If desired, this can always return the same area of memory rather than allocating a new one every time. */ |
||||
#ifndef OVERRIDE_OPUS_ALLOC_SCRATCH |
||||
static OPUS_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 replace this function, opus_realloc, and opus_free */ |
||||
#ifndef OVERRIDE_OPUS_FREE |
||||
static OPUS_INLINE void opus_free (void *ptr) |
||||
{ |
||||
free(ptr); |
||||
} |
||||
#endif |
||||
|
||||
/** Copy n elements 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 elements 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 */ |
||||
#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,560 @@
|
||||
/* 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); |
||||
} |
||||
} |
||||
|
||||
static void celt_fir5(opus_val16 *x, |
||||
const opus_val16 *num, |
||||
int N) |
||||
{ |
||||
int i; |
||||
opus_val16 num0, num1, num2, num3, num4; |
||||
opus_val32 mem0, mem1, mem2, mem3, mem4; |
||||
num0=num[0]; |
||||
num1=num[1]; |
||||
num2=num[2]; |
||||
num3=num[3]; |
||||
num4=num[4]; |
||||
mem0=0; |
||||
mem1=0; |
||||
mem2=0; |
||||
mem3=0; |
||||
mem4=0; |
||||
for (i=0;i<N;i++) |
||||
{ |
||||
opus_val32 sum = SHL32(EXTEND32(x[i]), SIG_SHIFT); |
||||
sum = MAC16_16(sum,num0,mem0); |
||||
sum = MAC16_16(sum,num1,mem1); |
||||
sum = MAC16_16(sum,num2,mem2); |
||||
sum = MAC16_16(sum,num3,mem3); |
||||
sum = MAC16_16(sum,num4,mem4); |
||||
mem4 = mem3; |
||||
mem3 = mem2; |
||||
mem2 = mem1; |
||||
mem1 = mem0; |
||||
mem0 = x[i]; |
||||
x[i] = ROUND16(sum, SIG_SHIFT); |
||||
} |
||||
} |
||||
|
||||
|
||||
void pitch_downsample(celt_sig * OPUS_RESTRICT x[], opus_val16 * OPUS_RESTRICT x_lp, |
||||
int len, int C, int factor, int arch) |
||||
{ |
||||
int i; |
||||
opus_val32 ac[5]; |
||||
opus_val16 tmp=Q15ONE; |
||||
opus_val16 lpc[4]; |
||||
opus_val16 lpc2[5]; |
||||
opus_val16 c1 = QCONST16(.8f,15); |
||||
int offset; |
||||
#ifdef FIXED_POINT |
||||
int shift; |
||||
opus_val32 maxabs; |
||||
#endif |
||||
offset = factor/2; |
||||
#ifdef FIXED_POINT |
||||
maxabs = celt_maxabs32(x[0], len*factor); |
||||
if (C==2) |
||||
{ |
||||
opus_val32 maxabs_1 = celt_maxabs32(x[1], len*factor); |
||||
maxabs = MAX32(maxabs, maxabs_1); |
||||
} |
||||
if (maxabs<1) |
||||
maxabs=1; |
||||
shift = celt_ilog2(maxabs)-10; |
||||
if (shift<0) |
||||
shift=0; |
||||
if (C==2) |
||||
shift++; |
||||
for (i=1;i<len;i++) |
||||
x_lp[i] = SHR32(x[0][(factor*i-offset)], shift+2) + SHR32(x[0][(factor*i+offset)], shift+2) + SHR32(x[0][factor*i], shift+1); |
||||
x_lp[0] = SHR32(x[0][offset], shift+2) + SHR32(x[0][0], shift+1); |
||||
if (C==2) |
||||
{ |
||||
for (i=1;i<len;i++) |
||||
x_lp[i] += SHR32(x[1][(factor*i-offset)], shift+2) + SHR32(x[1][(factor*i+offset)], shift+2) + SHR32(x[1][factor*i], shift+1); |
||||
x_lp[0] += SHR32(x[1][offset], shift+2) + SHR32(x[1][0], shift+1); |
||||
} |
||||
#else |
||||
for (i=1;i<len;i++) |
||||
x_lp[i] = .25f*x[0][(factor*i-offset)] + .25f*x[0][(factor*i+offset)] + .5f*x[0][factor*i]; |
||||
x_lp[0] = .25f*x[0][offset] + .5f*x[0][0]; |
||||
if (C==2) |
||||
{ |
||||
for (i=1;i<len;i++) |
||||
x_lp[i] += .25f*x[1][(factor*i-offset)] + .25f*x[1][(factor*i+offset)] + .5f*x[1][factor*i]; |
||||
x_lp[0] += .25f*x[1][offset] + .5f*x[1][0]; |
||||
} |
||||
#endif |
||||
_celt_autocorr(x_lp, ac, NULL, 0, |
||||
4, len, arch); |
||||
|
||||
/* 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); |
||||
} |
||||
/* Add a zero */ |
||||
lpc2[0] = lpc[0] + QCONST16(.8f,SIG_SHIFT); |
||||
lpc2[1] = lpc[1] + MULT16_16_Q15(c1,lpc[0]); |
||||
lpc2[2] = lpc[2] + MULT16_16_Q15(c1,lpc[1]); |
||||
lpc2[3] = lpc[3] + MULT16_16_Q15(c1,lpc[2]); |
||||
lpc2[4] = MULT16_16_Q15(c1,lpc[3]); |
||||
celt_fir5(x_lp, lpc2, len); |
||||
} |
||||
|
||||
/* Pure C implementation. */ |
||||
#ifdef FIXED_POINT |
||||
opus_val32 |
||||
#else |
||||
void |
||||
#endif |
||||
celt_pitch_xcorr_c(const opus_val16 *_x, const opus_val16 *_y, |
||||
opus_val32 *xcorr, int len, int max_pitch, int arch) |
||||
{ |
||||
|
||||
#if 0 /* This is a simple version of the pitch correlation that should work
|
||||
well on DSPs like Blackfin and TI C5x/C6x */ |
||||
int i, j; |
||||
#ifdef FIXED_POINT |
||||
opus_val32 maxcorr=1; |
||||
#endif |
||||
#if !defined(OVERRIDE_PITCH_XCORR) |
||||
(void)arch; |
||||
#endif |
||||
for (i=0;i<max_pitch;i++) |
||||
{ |
||||
opus_val32 sum = 0; |
||||
for (j=0;j<len;j++) |
||||
sum = MAC16_16(sum, _x[j], _y[i+j]); |
||||
xcorr[i] = sum; |
||||
#ifdef FIXED_POINT |
||||
maxcorr = MAX32(maxcorr, sum); |
||||
#endif |
||||
} |
||||
#ifdef FIXED_POINT |
||||
return maxcorr; |
||||
#endif |
||||
|
||||
#else /* Unrolled version of the pitch correlation -- runs faster on x86 and ARM */ |
||||
int i; |
||||
/*The EDSP version requires that max_pitch is at least 1, and that _x is
|
||||
32-bit aligned. |
||||
Since it's hard to put asserts in assembly, put them here.*/ |
||||
#ifdef FIXED_POINT |
||||
opus_val32 maxcorr=1; |
||||
#endif |
||||
celt_assert(max_pitch>0); |
||||
celt_sig_assert(((size_t)_x&3)==0); |
||||
for (i=0;i<max_pitch-3;i+=4) |
||||
{ |
||||
opus_val32 sum[4]={0,0,0,0}; |
||||
#if defined(OPUS_CHECK_ASM) && defined(FIXED_POINT) |
||||
{ |
||||
opus_val32 sum_c[4]={0,0,0,0}; |
||||
xcorr_kernel_c(_x, _y+i, sum_c, len); |
||||
#endif |
||||
xcorr_kernel(_x, _y+i, sum, len, arch); |
||||
#if defined(OPUS_CHECK_ASM) && defined(FIXED_POINT) |
||||
celt_assert(memcmp(sum, sum_c, sizeof(sum)) == 0); |
||||
} |
||||
#endif |
||||
xcorr[i]=sum[0]; |
||||
xcorr[i+1]=sum[1]; |
||||
xcorr[i+2]=sum[2]; |
||||
xcorr[i+3]=sum[3]; |
||||
#ifdef FIXED_POINT |
||||
sum[0] = MAX32(sum[0], sum[1]); |
||||
sum[2] = MAX32(sum[2], sum[3]); |
||||
sum[0] = MAX32(sum[0], sum[2]); |
||||
maxcorr = MAX32(maxcorr, sum[0]); |
||||
#endif |
||||
} |
||||
/* In case max_pitch isn't a multiple of 4, do non-unrolled version. */ |
||||
for (;i<max_pitch;i++) |
||||
{ |
||||
opus_val32 sum; |
||||
sum = celt_inner_prod(_x, _y+i, len, arch); |
||||
xcorr[i] = sum; |
||||
#ifdef FIXED_POINT |
||||
maxcorr = MAX32(maxcorr, sum); |
||||
#endif |
||||
} |
||||
#ifdef FIXED_POINT |
||||
return maxcorr; |
||||
#endif |
||||
#endif |
||||
} |
||||
|
||||
void pitch_search(const opus_val16 * OPUS_RESTRICT x_lp, opus_val16 * OPUS_RESTRICT y, |
||||
int len, int max_pitch, int *pitch, int arch) |
||||
{ |
||||
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; |
||||
opus_val32 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(MAX32(1, MAX32(xmax, ymax))) - 14 + celt_ilog2(len)/2; |
||||
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 */ |
||||
|
||||
#ifdef FIXED_POINT |
||||
maxcorr = |
||||
#endif |
||||
celt_pitch_xcorr(x_lp4, y_lp4, xcorr, len>>2, max_pitch>>2, arch); |
||||
|
||||
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; |
||||
xcorr[i] = 0; |
||||
if (abs(i-2*best_pitch[0])>2 && abs(i-2*best_pitch[1])>2) |
||||
continue; |
||||
#ifdef FIXED_POINT |
||||
sum = 0; |
||||
for (j=0;j<len>>1;j++) |
||||
sum += SHR32(MULT16_16(x_lp[j],y[i+j]), shift); |
||||
#else |
||||
sum = celt_inner_prod(x_lp, y+i, len>>1, arch); |
||||
#endif |
||||
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; |
||||
} |
||||
|
||||
#ifdef FIXED_POINT |
||||
static opus_val16 compute_pitch_gain(opus_val32 xy, opus_val32 xx, opus_val32 yy) |
||||
{ |
||||
opus_val32 x2y2; |
||||
int sx, sy, shift; |
||||
opus_val32 g; |
||||
opus_val16 den; |
||||
if (xy == 0 || xx == 0 || yy == 0) |
||||
return 0; |
||||
sx = celt_ilog2(xx)-14; |
||||
sy = celt_ilog2(yy)-14; |
||||
shift = sx + sy; |
||||
x2y2 = SHR32(MULT16_16(VSHR32(xx, sx), VSHR32(yy, sy)), 14); |
||||
if (shift & 1) { |
||||
if (x2y2 < 32768) |
||||
{ |
||||
x2y2 <<= 1; |
||||
shift--; |
||||
} else { |
||||
x2y2 >>= 1; |
||||
shift++; |
||||
} |
||||
} |
||||
den = celt_rsqrt_norm(x2y2); |
||||
g = MULT16_32_Q15(den, xy); |
||||
g = VSHR32(g, (shift>>1)-1); |
||||
return EXTRACT16(MAX32(-Q15ONE, MIN32(g, Q15ONE))); |
||||
} |
||||
#else |
||||
static opus_val16 compute_pitch_gain(opus_val32 xy, opus_val32 xx, opus_val32 yy) |
||||
{ |
||||
return xy/celt_sqrt(1+xx*yy); |
||||
} |
||||
#endif |
||||
|
||||
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 arch) |
||||
{ |
||||
int k, i, T, T0; |
||||
opus_val16 g, g0; |
||||
opus_val16 pg; |
||||
opus_val32 xy,xx,yy,xy2; |
||||
opus_val32 xcorr[3]; |
||||
opus_val32 best_xy, best_yy; |
||||
int offset; |
||||
int minperiod0; |
||||
VARDECL(opus_val32, yy_lookup); |
||||
SAVE_STACK; |
||||
|
||||
minperiod0 = minperiod; |
||||
maxperiod /= 2; |
||||
minperiod /= 2; |
||||
*T0_ /= 2; |
||||
prev_period /= 2; |
||||
N /= 2; |
||||
x += maxperiod; |
||||
if (*T0_>=maxperiod) |
||||
*T0_=maxperiod-1; |
||||
|
||||
T = T0 = *T0_; |
||||
ALLOC(yy_lookup, maxperiod+1, opus_val32); |
||||
dual_inner_prod(x, x, x-T0, N, &xx, &xy, arch); |
||||
yy_lookup[0] = xx; |
||||
yy=xx; |
||||
for (i=1;i<=maxperiod;i++) |
||||
{ |
||||
yy = yy+MULT16_16(x[-i],x[-i])-MULT16_16(x[N-i],x[N-i]); |
||||
yy_lookup[i] = MAX32(0, yy); |
||||
} |
||||
yy = yy_lookup[T0]; |
||||
best_xy = xy; |
||||
best_yy = yy; |
||||
g = g0 = compute_pitch_gain(xy, xx, yy); |
||||
/* Look for any pitch at T/k */ |
||||
for (k=2;k<=15;k++) |
||||
{ |
||||
int T1, T1b; |
||||
opus_val16 g1; |
||||
opus_val16 cont=0; |
||||
opus_val16 thresh; |
||||
T1 = celt_udiv(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 = celt_udiv(2*second_check[k]*T0+k, 2*k); |
||||
} |
||||
dual_inner_prod(x, &x[-T1], &x[-T1b], N, &xy, &xy2, arch); |
||||
xy = HALF32(xy + xy2); |
||||
yy = HALF32(yy_lookup[T1] + yy_lookup[T1b]); |
||||
g1 = compute_pitch_gain(xy, xx, yy); |
||||
if (abs(T1-prev_period)<=1) |
||||
cont = prev_gain; |
||||
else if (abs(T1-prev_period)<=2 && 5*k*k < T0) |
||||
cont = HALF16(prev_gain); |
||||
else |
||||
cont = 0; |
||||
thresh = MAX16(QCONST16(.3f,15), MULT16_16_Q15(QCONST16(.7f,15),g0)-cont); |
||||
/* Bias against very high pitch (very short period) to avoid false-positives
|
||||
due to short-term correlation */ |
||||
if (T1<3*minperiod) |
||||
thresh = MAX16(QCONST16(.4f,15), MULT16_16_Q15(QCONST16(.85f,15),g0)-cont); |
||||
else if (T1<2*minperiod) |
||||
thresh = MAX16(QCONST16(.5f,15), MULT16_16_Q15(QCONST16(.9f,15),g0)-cont); |
||||
if (g1 > thresh) |
||||
{ |
||||
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++) |
||||
xcorr[k] = celt_inner_prod(x, x-(T+k-1), N, arch); |
||||
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; |
||||
RESTORE_STACK; |
||||
return pg; |
||||
} |
||||
@ -0,0 +1,203 @@
|
||||
/* 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" |
||||
#include "cpu_support.h" |
||||
|
||||
#if (defined(OPUS_X86_MAY_HAVE_SSE) && !defined(FIXED_POINT)) \ |
||||
|| ((defined(OPUS_X86_MAY_HAVE_SSE4_1) || defined(OPUS_X86_MAY_HAVE_SSE2)) && defined(FIXED_POINT)) |
||||
#include "x86/pitch_sse.h" |
||||
#endif |
||||
|
||||
#if defined(FIXED_POINT) && defined(__mips) |
||||
#include "mips/pitch_mipsr1.h" |
||||
#endif |
||||
|
||||
#if (defined(OPUS_ARM_ASM) || defined(OPUS_ARM_MAY_HAVE_NEON_INTR)) |
||||
# include "arm/pitch_arm.h" |
||||
#endif |
||||
|
||||
void pitch_downsample(celt_sig * OPUS_RESTRICT x[], opus_val16 * OPUS_RESTRICT x_lp, |
||||
int len, int C, int factor, int arch); |
||||
|
||||
void pitch_search(const opus_val16 * OPUS_RESTRICT x_lp, opus_val16 * OPUS_RESTRICT y, |
||||
int len, int max_pitch, int *pitch, int arch); |
||||
|
||||
opus_val16 remove_doubling(opus_val16 *x, int maxperiod, int minperiod, |
||||
int N, int *T0, int prev_period, opus_val16 prev_gain, int arch); |
||||
|
||||
|
||||
/* OPT: This is the kernel you really want to optimize. It gets used a lot
|
||||
by the prefilter and by the PLC. */ |
||||
static OPUS_INLINE void xcorr_kernel_c(const opus_val16 * x, const opus_val16 * y, opus_val32 sum[4], int len) |
||||
{ |
||||
int j; |
||||
opus_val16 y_0, y_1, y_2, y_3; |
||||
celt_assert(len>=3); |
||||
y_3=0; /* gcc doesn't realize that y_3 can't be used uninitialized */ |
||||
y_0=*y++; |
||||
y_1=*y++; |
||||
y_2=*y++; |
||||
for (j=0;j<len-3;j+=4) |
||||
{ |
||||
opus_val16 tmp; |
||||
tmp = *x++; |
||||
y_3=*y++; |
||||
sum[0] = MAC16_16(sum[0],tmp,y_0); |
||||
sum[1] = MAC16_16(sum[1],tmp,y_1); |
||||
sum[2] = MAC16_16(sum[2],tmp,y_2); |
||||
sum[3] = MAC16_16(sum[3],tmp,y_3); |
||||
tmp=*x++; |
||||
y_0=*y++; |
||||
sum[0] = MAC16_16(sum[0],tmp,y_1); |
||||
sum[1] = MAC16_16(sum[1],tmp,y_2); |
||||
sum[2] = MAC16_16(sum[2],tmp,y_3); |
||||
sum[3] = MAC16_16(sum[3],tmp,y_0); |
||||
tmp=*x++; |
||||
y_1=*y++; |
||||
sum[0] = MAC16_16(sum[0],tmp,y_2); |
||||
sum[1] = MAC16_16(sum[1],tmp,y_3); |
||||
sum[2] = MAC16_16(sum[2],tmp,y_0); |
||||
sum[3] = MAC16_16(sum[3],tmp,y_1); |
||||
tmp=*x++; |
||||
y_2=*y++; |
||||
sum[0] = MAC16_16(sum[0],tmp,y_3); |
||||
sum[1] = MAC16_16(sum[1],tmp,y_0); |
||||
sum[2] = MAC16_16(sum[2],tmp,y_1); |
||||
sum[3] = MAC16_16(sum[3],tmp,y_2); |
||||
} |
||||
if (j++<len) |
||||
{ |
||||
opus_val16 tmp = *x++; |
||||
y_3=*y++; |
||||
sum[0] = MAC16_16(sum[0],tmp,y_0); |
||||
sum[1] = MAC16_16(sum[1],tmp,y_1); |
||||
sum[2] = MAC16_16(sum[2],tmp,y_2); |
||||
sum[3] = MAC16_16(sum[3],tmp,y_3); |
||||
} |
||||
if (j++<len) |
||||
{ |
||||
opus_val16 tmp=*x++; |
||||
y_0=*y++; |
||||
sum[0] = MAC16_16(sum[0],tmp,y_1); |
||||
sum[1] = MAC16_16(sum[1],tmp,y_2); |
||||
sum[2] = MAC16_16(sum[2],tmp,y_3); |
||||
sum[3] = MAC16_16(sum[3],tmp,y_0); |
||||
} |
||||
if (j<len) |
||||
{ |
||||
opus_val16 tmp=*x++; |
||||
y_1=*y++; |
||||
sum[0] = MAC16_16(sum[0],tmp,y_2); |
||||
sum[1] = MAC16_16(sum[1],tmp,y_3); |
||||
sum[2] = MAC16_16(sum[2],tmp,y_0); |
||||
sum[3] = MAC16_16(sum[3],tmp,y_1); |
||||
} |
||||
} |
||||
|
||||
#ifndef OVERRIDE_XCORR_KERNEL |
||||
#define xcorr_kernel(x, y, sum, len, arch) \ |
||||
((void)(arch),xcorr_kernel_c(x, y, sum, len)) |
||||
#endif /* OVERRIDE_XCORR_KERNEL */ |
||||
|
||||
|
||||
static OPUS_INLINE void dual_inner_prod_c(const opus_val16 *x, const opus_val16 *y01, const opus_val16 *y02, |
||||
int N, opus_val32 *xy1, opus_val32 *xy2) |
||||
{ |
||||
int i; |
||||
opus_val32 xy01=0; |
||||
opus_val32 xy02=0; |
||||
for (i=0;i<N;i++) |
||||
{ |
||||
xy01 = MAC16_16(xy01, x[i], y01[i]); |
||||
xy02 = MAC16_16(xy02, x[i], y02[i]); |
||||
} |
||||
*xy1 = xy01; |
||||
*xy2 = xy02; |
||||
} |
||||
|
||||
#ifndef OVERRIDE_DUAL_INNER_PROD |
||||
# define dual_inner_prod(x, y01, y02, N, xy1, xy2, arch) \ |
||||
((void)(arch),dual_inner_prod_c(x, y01, y02, N, xy1, xy2)) |
||||
#endif |
||||
|
||||
/*We make sure a C version is always available for cases where the overhead of
|
||||
vectorization and passing around an arch flag aren't worth it.*/ |
||||
static OPUS_INLINE opus_val32 celt_inner_prod_c(const opus_val16 *x, |
||||
const opus_val16 *y, int N) |
||||
{ |
||||
int i; |
||||
opus_val32 xy=0; |
||||
for (i=0;i<N;i++) |
||||
xy = MAC16_16(xy, x[i], y[i]); |
||||
return xy; |
||||
} |
||||
|
||||
#if !defined(OVERRIDE_CELT_INNER_PROD) |
||||
# define celt_inner_prod(x, y, N, arch) \ |
||||
((void)(arch),celt_inner_prod_c(x, y, N)) |
||||
#endif |
||||
|
||||
#ifdef NON_STATIC_COMB_FILTER_CONST_C |
||||
void comb_filter_const_c(opus_val32 *y, opus_val32 *x, int T, int N, |
||||
opus_val16 g10, opus_val16 g11, opus_val16 g12); |
||||
#endif |
||||
|
||||
|
||||
#ifdef FIXED_POINT |
||||
opus_val32 |
||||
#else |
||||
void |
||||
#endif |
||||
celt_pitch_xcorr_c(const opus_val16 *_x, const opus_val16 *_y, |
||||
opus_val32 *xcorr, int len, int max_pitch, int arch); |
||||
|
||||
#ifndef OVERRIDE_PITCH_XCORR |
||||
# define celt_pitch_xcorr celt_pitch_xcorr_c |
||||
#endif |
||||
|
||||
#ifdef NON_STATIC_COMB_FILTER_CONST_C |
||||
void comb_filter_const_c(opus_val32 *y, opus_val32 *x, int T, int N, |
||||
opus_val16 g10, opus_val16 g11, opus_val16 g12); |
||||
#endif |
||||
|
||||
#ifndef OVERRIDE_COMB_FILTER_CONST |
||||
# define comb_filter_const(y, x, T, N, g10, g11, g12, arch) \ |
||||
((void)(arch),comb_filter_const_c(y, x, T, N, g10, g11, g12)) |
||||
#endif |
||||
|
||||
|
||||
#endif |
||||
@ -0,0 +1,572 @@
|
||||
/* 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 Q4 */ |
||||
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 Q4 and converted back to float */ |
||||
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 celt_glog *eBands, celt_glog *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++) |
||||
{ |
||||
celt_glog d = PSHR32(SUB32(eBands[i+c*len], oldEBands[i+c*len]), DB_SHIFT-7); |
||||
dist = MAC16_16(dist, d,d); |
||||
} |
||||
} while (++c<C); |
||||
return MIN32(200,SHR32(dist,14)); |
||||
} |
||||
|
||||
static int quant_coarse_energy_impl(const CELTMode *m, int start, int end, |
||||
const celt_glog *eBands, celt_glog *oldEBands, |
||||
opus_int32 budget, opus_int32 tell, |
||||
const unsigned char *prob_model, celt_glog *error, ec_enc *enc, |
||||
int C, int LM, int intra, celt_glog max_decay, int lfe) |
||||
{ |
||||
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; |
||||
celt_glog x; |
||||
opus_val32 f, tmp; |
||||
celt_glog oldE; |
||||
celt_glog decay_bound; |
||||
x = eBands[i+c*m->nbEBands]; |
||||
oldE = MAXG(-GCONST(9.f), oldEBands[i+c*m->nbEBands]); |
||||
#ifdef FIXED_POINT |
||||
f = x - MULT16_32_Q15(coef,oldE) - prev[c]; |
||||
/* Rounding to nearest integer here is really important! */ |
||||
qi = (f+QCONST32(.5f,DB_SHIFT))>>DB_SHIFT; |
||||
decay_bound = MAXG(-GCONST(28.f), 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 = MAXG(-GCONST(28.f), 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)SHR32(SUB32(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 (lfe && i>=2) |
||||
qi = IMIN(qi, 0); |
||||
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] = f - SHL32(qi,DB_SHIFT); |
||||
badness += abs(qi0-qi); |
||||
q = (opus_val32)SHL32(EXTEND32(qi),DB_SHIFT); |
||||
|
||||
tmp = MULT16_32_Q15(coef,oldE) + prev[c] + q; |
||||
#ifdef FIXED_POINT |
||||
tmp = MAX32(-GCONST(28.f), tmp); |
||||
#endif |
||||
oldEBands[i+c*m->nbEBands] = tmp; |
||||
prev[c] = prev[c] + q - MULT16_32_Q15(beta,q); |
||||
} while (++c < C); |
||||
} |
||||
return lfe ? 0 : badness; |
||||
} |
||||
|
||||
void quant_coarse_energy(const CELTMode *m, int start, int end, int effEnd, |
||||
const celt_glog *eBands, celt_glog *oldEBands, opus_uint32 budget, |
||||
celt_glog *error, ec_enc *enc, int C, int LM, int nbAvailableBytes, |
||||
int force_intra, opus_val32 *delayedIntra, int two_pass, int loss_rate, int lfe) |
||||
{ |
||||
int intra; |
||||
celt_glog max_decay; |
||||
VARDECL(celt_glog, oldEBands_intra); |
||||
VARDECL(celt_glog, 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; |
||||
|
||||
max_decay = GCONST(16.f); |
||||
if (end-start>10) |
||||
{ |
||||
#ifdef FIXED_POINT |
||||
max_decay = SHL32(MIN32(SHR32(max_decay,DB_SHIFT-3), EXTEND32(nbAvailableBytes)),DB_SHIFT-3); |
||||
#else |
||||
max_decay = MIN32(max_decay, .125f*nbAvailableBytes); |
||||
#endif |
||||
} |
||||
if (lfe) |
||||
max_decay = GCONST(3.f); |
||||
enc_start_state = *enc; |
||||
|
||||
ALLOC(oldEBands_intra, C*m->nbEBands, celt_glog); |
||||
ALLOC(error_intra, C*m->nbEBands, celt_glog); |
||||
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, lfe); |
||||
} |
||||
|
||||
if (!intra) |
||||
{ |
||||
unsigned char *intra_buf; |
||||
ec_enc enc_intra_state; |
||||
opus_int32 tell_intra; |
||||
opus_uint32 nstart_bytes; |
||||
opus_uint32 nintra_bytes; |
||||
opus_uint32 save_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; |
||||
save_bytes = nintra_bytes-nstart_bytes; |
||||
if (save_bytes == 0) |
||||
save_bytes = ALLOC_NONE; |
||||
ALLOC(intra_bits, save_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, lfe); |
||||
|
||||
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, celt_glog *oldEBands, celt_glog *error, int *prev_quant, int *extra_quant, ec_enc *enc, int C) |
||||
{ |
||||
int i, c; |
||||
/* Encode finer resolution */ |
||||
for (i=start;i<end;i++) |
||||
{ |
||||
opus_int16 extra, prev; |
||||
extra = 1<<extra_quant[i]; |
||||
if (extra_quant[i] <= 0) |
||||
continue; |
||||
if (ec_tell(enc)+C*extra_quant[i] > (opus_int32)enc->storage*8) continue; |
||||
prev = (prev_quant!=NULL) ? prev_quant[i] : 0; |
||||
c=0; |
||||
do { |
||||
int q2; |
||||
celt_glog offset; |
||||
#ifdef FIXED_POINT |
||||
/* Has to be without rounding */ |
||||
q2 = VSHR32(ADD32(error[i+c*m->nbEBands], SHR32(GCONST(.5f), prev)), DB_SHIFT-extra_quant[i]-prev); |
||||
#else |
||||
q2 = (int)floor((error[i+c*m->nbEBands]*(1<<prev)+.5f)*extra); |
||||
#endif |
||||
if (q2 > extra-1) |
||||
q2 = extra-1; |
||||
if (q2<0) |
||||
q2 = 0; |
||||
ec_enc_bits(enc, q2, extra_quant[i]); |
||||
#ifdef FIXED_POINT |
||||
offset = SUB32(VSHR32(2*q2+1, extra_quant[i]-DB_SHIFT+1), GCONST(.5f)); |
||||
offset = SHR32(offset, prev); |
||||
#else |
||||
offset = (q2+.5f)*(1<<(14-extra_quant[i]))*(1.f/16384) - .5f; |
||||
offset *= (1<<(14-prev))*(1.f/16384); |
||||
#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, celt_glog *oldEBands, celt_glog *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; |
||||
celt_glog offset; |
||||
q2 = error[i+c*m->nbEBands]<0 ? 0 : 1; |
||||
ec_enc_bits(enc, q2, 1); |
||||
#ifdef FIXED_POINT |
||||
offset = SHR32(SHL32(q2,DB_SHIFT)-GCONST(.5f),fine_quant[i]+1); |
||||
#else |
||||
offset = (q2-.5f)*(1<<(14-fine_quant[i]-1))*(1.f/16384); |
||||
#endif |
||||
if (oldEBands != NULL) oldEBands[i+c*m->nbEBands] += offset; |
||||
error[i+c*m->nbEBands] -= offset; |
||||
bits_left--; |
||||
} while (++c < C); |
||||
} |
||||
} |
||||
} |
||||
|
||||
void unquant_coarse_energy(const CELTMode *m, int start, int end, celt_glog *oldEBands, int intra, ec_dec *dec, int C, int LM) |
||||
{ |
||||
const unsigned char *prob_model = e_prob_model[LM][intra]; |
||||
int i, c; |
||||
opus_val64 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_sig_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] = MAXG(-GCONST(9.f), oldEBands[i+c*m->nbEBands]); |
||||
tmp = MULT16_32_Q15(coef,oldEBands[i+c*m->nbEBands]) + prev[c] + q; |
||||
#ifdef FIXED_POINT |
||||
tmp = MIN32(GCONST(28.f), MAX32(-GCONST(28.f), tmp)); |
||||
#endif |
||||
oldEBands[i+c*m->nbEBands] = tmp; |
||||
prev[c] = prev[c] + q - MULT16_32_Q15(beta,q); |
||||
} while (++c < C); |
||||
} |
||||
} |
||||
|
||||
void unquant_fine_energy(const CELTMode *m, int start, int end, celt_glog *oldEBands, int *prev_quant, int *extra_quant, ec_dec *dec, int C) |
||||
{ |
||||
int i, c; |
||||
/* Decode finer resolution */ |
||||
for (i=start;i<end;i++) |
||||
{ |
||||
opus_int16 extra, prev; |
||||
extra = extra_quant[i]; |
||||
if (extra_quant[i] <= 0) |
||||
continue; |
||||
if (ec_tell(dec)+C*extra_quant[i] > (opus_int32)dec->storage*8) continue; |
||||
prev = (prev_quant!=NULL) ? prev_quant[i] : 0; |
||||
c=0; |
||||
do { |
||||
int q2; |
||||
celt_glog offset; |
||||
q2 = ec_dec_bits(dec, extra); |
||||
#ifdef FIXED_POINT |
||||
offset = SUB32(VSHR32(2*q2+1, extra-DB_SHIFT+1), GCONST(.5f)); |
||||
offset = SHR32(offset, prev); |
||||
#else |
||||
offset = (q2+.5f)*(1<<(14-extra))*(1.f/16384) - .5f; |
||||
offset *= (1<<(14-prev))*(1.f/16384); |
||||
#endif |
||||
oldEBands[i+c*m->nbEBands] += offset; |
||||
} while (++c < C); |
||||
} |
||||
} |
||||
|
||||
void unquant_energy_finalise(const CELTMode *m, int start, int end, celt_glog *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; |
||||
celt_glog offset; |
||||
q2 = ec_dec_bits(dec, 1); |
||||
#ifdef FIXED_POINT |
||||
offset = SHR32(SHL32(q2,DB_SHIFT)-GCONST(.5f),fine_quant[i]+1); |
||||
#else |
||||
offset = (q2-.5f)*(1<<(14-fine_quant[i]-1))*(1.f/16384); |
||||
#endif |
||||
if (oldEBands != NULL) oldEBands[i+c*m->nbEBands] += offset; |
||||
bits_left--; |
||||
} while (++c < C); |
||||
} |
||||
} |
||||
} |
||||
|
||||
void amp2Log2(const CELTMode *m, int effEnd, int end, |
||||
celt_ener *bandE, celt_glog *bandLogE, int C) |
||||
{ |
||||
int c, i; |
||||
c=0; |
||||
do { |
||||
for (i=0;i<effEnd;i++) |
||||
{ |
||||
bandLogE[i+c*m->nbEBands] = |
||||
celt_log2_db(bandE[i+c*m->nbEBands]) |
||||
- SHL32((celt_glog)eMeans[i],DB_SHIFT-4); |
||||
#ifdef FIXED_POINT |
||||
/* Compensate for bandE[] being Q12 but celt_log2() taking a Q14 input. */ |
||||
bandLogE[i+c*m->nbEBands] += GCONST(2.f); |
||||
#endif |
||||
} |
||||
for (i=effEnd;i<end;i++) |
||||
bandLogE[c*m->nbEBands+i] = -GCONST(14.f); |
||||
} while (++c < C); |
||||
} |
||||
@ -0,0 +1,66 @@
|
||||
/* 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" |
||||
|
||||
#ifdef FIXED_POINT |
||||
extern const signed char eMeans[25]; |
||||
#else |
||||
extern const opus_val16 eMeans[25]; |
||||
#endif |
||||
|
||||
void amp2Log2(const CELTMode *m, int effEnd, int end, |
||||
celt_ener *bandE, celt_glog *bandLogE, int C); |
||||
|
||||
void log2Amp(const CELTMode *m, int start, int end, |
||||
celt_ener *eBands, const celt_glog *oldEBands, int C); |
||||
|
||||
void quant_coarse_energy(const CELTMode *m, int start, int end, int effEnd, |
||||
const celt_glog *eBands, celt_glog *oldEBands, opus_uint32 budget, |
||||
celt_glog *error, ec_enc *enc, int C, int LM, |
||||
int nbAvailableBytes, int force_intra, opus_val32 *delayedIntra, |
||||
int two_pass, int loss_rate, int lfe); |
||||
|
||||
void quant_fine_energy(const CELTMode *m, int start, int end, celt_glog *oldEBands, celt_glog *error, int *fine_quant, int *extra_quant, ec_enc *enc, int C); |
||||
|
||||
void quant_energy_finalise(const CELTMode *m, int start, int end, celt_glog *oldEBands, celt_glog *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, celt_glog *oldEBands, int intra, ec_dec *dec, int C, int LM); |
||||
|
||||
void unquant_fine_energy(const CELTMode *m, int start, int end, celt_glog *oldEBands, int *fine_quant, int *extra_quant, ec_dec *dec, int C); |
||||
|
||||
void unquant_energy_finalise(const CELTMode *m, int start, int end, celt_glog *oldEBands, int *fine_quant, int *fine_priority, int bits_left, ec_dec *dec, int C); |
||||
|
||||
#endif /* QUANT_BANDS */ |
||||
@ -0,0 +1,876 @@
|
||||
/* 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" |
||||
#include "quant_bands.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 |
||||
}; |
||||
|
||||
#if defined(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[CELT_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]+(opus_int32)((opus_uint32)(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 OPUS_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, int signalBandwidth) |
||||
{ |
||||
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] + ((opus_int32)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 concentrated 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 = celt_udiv(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.*/ |
||||
int depth_threshold; |
||||
/*We choose a threshold with some hysteresis to keep bands from
|
||||
fluctuating in and out, but we try not to fold below a certain point. */ |
||||
if (codedBands > 17) |
||||
depth_threshold = j<prev ? 7 : 9; |
||||
else |
||||
depth_threshold = 0; |
||||
#ifdef FUZZING |
||||
(void)signalBandwidth; |
||||
(void)depth_threshold; |
||||
if ((rand()&0x1) == 0) |
||||
#else |
||||
if (codedBands<=start+2 || (band_bits > (depth_threshold*band_width<<LM<<BITRES)>>4 && j<=signalBandwidth)) |
||||
#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 = celt_udiv(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)))); |
||||
ebits[j] = celt_udiv(ebits[j], 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 clt_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 signalBandwidth) |
||||
{ |
||||
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, signalBandwidth); |
||||
RESTORE_STACK; |
||||
return codedBands; |
||||
} |
||||
#ifdef ENABLE_QEXT |
||||
|
||||
static const unsigned char last_zero[3] = {64, 50, 0}; |
||||
static const unsigned char last_cap[3] = {110, 60, 0}; |
||||
static const unsigned char last_other[4] = {120, 112, 70, 0}; |
||||
|
||||
static void ec_enc_depth(ec_enc *enc, opus_int32 depth, opus_int32 cap, opus_int32 *last) { |
||||
int sym = 3; |
||||
if (depth==*last) sym = 2; |
||||
if (depth==cap) sym = 1; |
||||
if (depth==0) sym = 0; |
||||
if (*last == 0) { |
||||
ec_enc_icdf(enc, IMIN(sym, 2), last_zero, 7); |
||||
} else if (*last == cap) { |
||||
ec_enc_icdf(enc, IMIN(sym, 2), last_cap, 7); |
||||
} else { |
||||
ec_enc_icdf(enc, sym, last_other, 7); |
||||
} |
||||
/* We accept some redundancy if depth==last (for last different from 0 and cap). */ |
||||
if (sym == 3) ec_enc_uint(enc, depth-1, cap); |
||||
*last = depth; |
||||
} |
||||
|
||||
static int ec_dec_depth(ec_dec *dec, opus_int32 cap, opus_int32 *last) { |
||||
int depth, sym; |
||||
if (*last == 0) { |
||||
sym = ec_dec_icdf(dec, last_zero, 7); |
||||
if (sym==2) sym=3; |
||||
} else if (*last == cap) { |
||||
sym = ec_dec_icdf(dec, last_cap, 7); |
||||
if (sym==2) sym=3; |
||||
} else { |
||||
sym = ec_dec_icdf(dec, last_other, 7); |
||||
} |
||||
if (sym==0) depth=0; |
||||
else if (sym==1) depth=cap; |
||||
else if (sym==2) depth=*last; |
||||
else depth = 1 + ec_dec_uint(dec, cap); |
||||
*last = depth; |
||||
return depth; |
||||
} |
||||
|
||||
#define MSWAP16(a,b) do {opus_val16 tmp = a;a=b;b=tmp;} while(0) |
||||
static opus_val16 median_of_5_val16(const opus_val16 *x) |
||||
{ |
||||
opus_val16 t0, t1, t2, t3, t4; |
||||
t2 = x[2]; |
||||
if (x[0] > x[1]) |
||||
{ |
||||
t0 = x[1]; |
||||
t1 = x[0]; |
||||
} else { |
||||
t0 = x[0]; |
||||
t1 = x[1]; |
||||
} |
||||
if (x[3] > x[4]) |
||||
{ |
||||
t3 = x[4]; |
||||
t4 = x[3]; |
||||
} else { |
||||
t3 = x[3]; |
||||
t4 = x[4]; |
||||
} |
||||
if (t0 > t3) |
||||
{ |
||||
MSWAP16(t0, t3); |
||||
MSWAP16(t1, t4); |
||||
} |
||||
if (t2 > t1) |
||||
{ |
||||
if (t1 < t3) |
||||
return MIN16(t2, t3); |
||||
else |
||||
return MIN16(t4, t1); |
||||
} else { |
||||
if (t2 < t3) |
||||
return MIN16(t1, t3); |
||||
else |
||||
return MIN16(t2, t4); |
||||
} |
||||
} |
||||
|
||||
void clt_compute_extra_allocation(const CELTMode *m, const CELTMode *qext_mode, int start, int end, int qext_end, const celt_glog *bandLogE, const celt_glog *qext_bandLogE, |
||||
opus_int32 total, int *extra_pulses, int *extra_equant, int C, int LM, ec_ctx *ec, int encode, opus_val16 tone_freq, opus_val32 toneishness) |
||||
{ |
||||
int i; |
||||
opus_int32 last=0; |
||||
opus_val32 sum; |
||||
opus_val32 fill; |
||||
int iter; |
||||
int tot_bands; |
||||
int tot_samples; |
||||
VARDECL(int, depth); |
||||
VARDECL(opus_int32, cap); |
||||
#ifdef FUZZING |
||||
float depth_std; |
||||
#endif |
||||
SAVE_STACK; |
||||
#ifdef FUZZING |
||||
depth_std = -10.f*log(1e-8+(float)rand()/(float)RAND_MAX); |
||||
depth_std = FMAX(0, FMIN(48, depth_std)); |
||||
#endif |
||||
if (qext_mode != NULL) { |
||||
celt_assert(end==m->nbEBands); |
||||
tot_bands = end + qext_end; |
||||
tot_samples = qext_mode->eBands[qext_end]*C<<LM; |
||||
} else { |
||||
tot_bands = end; |
||||
tot_samples = (m->eBands[end]-m->eBands[start])*C<<LM; |
||||
} |
||||
ALLOC(cap, tot_bands, opus_int32); |
||||
for (i=start;i<end;i++) cap[i] = 12; |
||||
if (qext_mode != NULL) { |
||||
for (i=0;i<qext_end;i++) cap[end+i] = 14; |
||||
} |
||||
if (total <= 0) { |
||||
for (i=start;i<m->nbEBands+qext_end;i++) { |
||||
extra_pulses[i] = extra_equant[i] = 0; |
||||
} |
||||
RESTORE_STACK; |
||||
return; |
||||
} |
||||
ALLOC(depth, tot_bands, int); |
||||
if (encode) { |
||||
VARDECL(opus_val16, flatE); |
||||
VARDECL(int, Ncoef); |
||||
VARDECL(opus_val16, min); |
||||
VARDECL(opus_val16, follower); |
||||
|
||||
ALLOC(flatE, tot_bands, opus_val16); |
||||
ALLOC(min, tot_bands, opus_val16); |
||||
ALLOC(Ncoef, tot_bands, int); |
||||
for (i=start;i<end;i++) { |
||||
Ncoef[i] = (m->eBands[i+1]-m->eBands[i])*C<<LM; |
||||
} |
||||
/* Remove the effect of band width, eMeans and pre-emphasis to compute the real (flat) spectrum. */ |
||||
for (i=start;i<end;i++) { |
||||
flatE[i] = PSHR32(bandLogE[i] - GCONST(0.0625f)*m->logN[i] + SHL32(eMeans[i],DB_SHIFT-4) - GCONST(.0062f)*(i+5)*(i+5), DB_SHIFT-10); |
||||
min[i] = 0; |
||||
} |
||||
if (C==2) { |
||||
for (i=start;i<end;i++) { |
||||
flatE[i] = MAXG(flatE[i], PSHR32(bandLogE[m->nbEBands+i] - GCONST(0.0625f)*m->logN[i] + SHL32(eMeans[i],DB_SHIFT-4) - GCONST(.0062f)*(i+5)*(i+5), DB_SHIFT-10)); |
||||
} |
||||
} |
||||
flatE[end-1] += QCONST16(2.f, 10); |
||||
if (qext_mode != NULL) { |
||||
opus_val16 min_depth = 0; |
||||
/* If we have enough bits, give at least 1 bit of depth to all higher bands. */ |
||||
if (total >= 3*C*(qext_mode->eBands[qext_end]-qext_mode->eBands[start])<<LM<<BITRES && (toneishness < QCONST32(.98f, 29) || tone_freq > 1.33f)) |
||||
min_depth = QCONST16(1.f, 10); |
||||
for (i=0;i<qext_end;i++) { |
||||
Ncoef[end+i] = (qext_mode->eBands[i+1]-qext_mode->eBands[i])*C<<LM; |
||||
min[end+i] = min_depth; |
||||
} |
||||
for (i=0;i<qext_end;i++) { |
||||
flatE[end+i] = PSHR32(qext_bandLogE[i] - GCONST(0.0625f)*qext_mode->logN[i] + SHL32(eMeans[i],DB_SHIFT-4) - GCONST(.0062f)*(end+i+5)*(end+i+5), DB_SHIFT-10); |
||||
} |
||||
if (C==2) { |
||||
for (i=0;i<qext_end;i++) { |
||||
flatE[end+i] = MAXG(flatE[end+i], PSHR32(qext_bandLogE[NB_QEXT_BANDS+i] - GCONST(0.0625f)*qext_mode->logN[i] + SHL32(eMeans[i],DB_SHIFT-4) - GCONST(.0062f)*(end+i+5)*(end+i+5), DB_SHIFT-10)); |
||||
} |
||||
} |
||||
} |
||||
ALLOC(follower, tot_bands, opus_val16); |
||||
for (i=start+2;i<tot_bands-2;i++) { |
||||
follower[i] = median_of_5_val16(&flatE[i-2]); |
||||
} |
||||
follower[start] = follower[start+1] = follower[start+2]; |
||||
follower[tot_bands-1] = follower[tot_bands-2] = follower[tot_bands-3]; |
||||
for (i=start+1;i<tot_bands;i++) { |
||||
follower[i] = MAX16(follower[i], follower[i-1]-QCONST16(1.f, 10)); |
||||
} |
||||
for (i=tot_bands-2;i>=start;i--) { |
||||
follower[i] = MAX16(follower[i], follower[i+1]-QCONST16(1.f, 10)); |
||||
} |
||||
for (i=start;i<tot_bands;i++) flatE[i] -= MULT16_16_Q15(Q15ONE-PSHR32(toneishness, 14), follower[i]); |
||||
if (qext_mode != NULL) { |
||||
for (i=0;i<qext_end;i++) flatE[end+i] = flatE[end+i] + QCONST16(3.f, 10) + QCONST16(.2f, 10)*i; |
||||
} |
||||
/* Approximate fill level assuming all bands contribute fully. */ |
||||
sum = 0; |
||||
for (i=start;i<tot_bands;i++) { |
||||
sum += MULT16_16(Ncoef[i], flatE[i]); |
||||
} |
||||
total >>= BITRES; |
||||
fill = (SHL32(total, 10) + sum)/tot_samples; |
||||
/* Iteratively refine the fill level considering the depth min and cap. */ |
||||
for (iter=0;iter<10;iter++) { |
||||
sum = 0; |
||||
for (i=start;i<tot_bands;i++) |
||||
sum += Ncoef[i] * MIN32(SHL32(cap[i], 10), MAX32(min[i], flatE[i]-fill)); |
||||
fill -= (SHL32(total, 10) - sum)/tot_samples; |
||||
} |
||||
for (i=start;i<tot_bands;i++) { |
||||
#ifdef FIXED_POINT |
||||
depth[i] = PSHR32(MIN32(SHL32(cap[i], 10), MAX32(min[i], flatE[i]-fill)), 10-2); |
||||
#else |
||||
depth[i] = (int)floor(.5+4*MIN32(SHL32(cap[i], 10), MAX32(min[i], flatE[i]-fill))); |
||||
#endif |
||||
#ifdef FUZZING |
||||
depth[i] = (int)-depth_std*log(1e-8+(float)rand()/(float)RAND_MAX); |
||||
depth[i] = IMAX(0, IMIN(cap[i]<<2, depth[i])); |
||||
#endif |
||||
if (ec_tell_frac(ec) + 80 < ec->storage*8<<BITRES) |
||||
ec_enc_depth(ec, depth[i], 4*cap[i], &last); |
||||
else |
||||
depth[i] = 0; |
||||
} |
||||
} else { |
||||
for (i=start;i<tot_bands;i++) { |
||||
if (ec_tell_frac(ec) + 80 < ec->storage*8<<BITRES) |
||||
depth[i] = ec_dec_depth(ec, 4*cap[i], &last); |
||||
else |
||||
depth[i] = 0; |
||||
} |
||||
} |
||||
for (i=start;i<end;i++) { |
||||
extra_equant[i] = (depth[i]+3)>>2; |
||||
extra_pulses[i] = ((((m->eBands[i+1]-m->eBands[i])<<LM)-1)*C * depth[i] * (1<<BITRES) + 2)>>2; |
||||
} |
||||
if (qext_mode) { |
||||
for (i=0;i<qext_end;i++) { |
||||
extra_equant[end+i] = (depth[end+i]+3)>>2; |
||||
extra_pulses[end+i] = ((((qext_mode->eBands[i+1]-qext_mode->eBands[i])<<LM)-1)*C * depth[end+i] * (1<<BITRES) + 2)>>2; |
||||
} |
||||
} |
||||
RESTORE_STACK; |
||||
} |
||||
#endif |
||||
@ -0,0 +1,104 @@
|
||||
/* 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 CELT_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 OPUS_INLINE int get_pulses(int i) |
||||
{ |
||||
return i<8 ? i : (8 + (i&7)) << ((i>>3)-1); |
||||
} |
||||
|
||||
static OPUS_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 OPUS_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 clt_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 signalBandwidth); |
||||
|
||||
void clt_compute_extra_allocation(const CELTMode *m, const CELTMode *qext_mode, int start, int end, int qext_end, const celt_glog *bandLogE, const celt_glog *qext_bandLogE, |
||||
opus_int32 total, int *extra_pulses, int *extra_equant, int C, int LM, ec_ctx *ec, int encode, opus_val16 tone_freq, opus_val32 toneishness); |
||||
|
||||
#endif |
||||
@ -0,0 +1,209 @@
|
||||
/* 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 |
||||
|
||||
#include "opus_types.h" |
||||
#include "opus_defines.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 |
||||
/* C99 does not allow VLAs of size zero */ |
||||
#define ALLOC_NONE 1 |
||||
|
||||
#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 |
||||
#define ALLOC_NONE 0 |
||||
|
||||
#else |
||||
|
||||
#ifdef CELT_C |
||||
char *scratch_ptr=0; |
||||
char *global_stack=0; |
||||
#else |
||||
extern char *global_stack; |
||||
extern char *scratch_ptr; |
||||
#endif /* CELT_C */ |
||||
|
||||
#if __STDC_VERSION__ >= 201112L |
||||
# include <stdalign.h> |
||||
# define ALIGNOF(T) alignof(T) |
||||
#elif defined(__GNUC__) || defined(__clang__) |
||||
# define ALIGNOF(T) __alignof__(T) |
||||
#else |
||||
# include <stddef.h> |
||||
# ifdef __cplusplus |
||||
template <typename T> |
||||
struct alignment_helper { |
||||
char c; |
||||
T member; |
||||
}; |
||||
# define ALIGNOF(T) (offsetof(alignment_helper<T>, member)) |
||||
# else |
||||
# define ALIGNOF(T) (offsetof(struct { char c; T member; }, member)) |
||||
# endif |
||||
#endif |
||||
|
||||
#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),ALIGNOF(type)),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=(char*)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)) |
||||
#ifdef ENABLE_HARDENING |
||||
#include "arch.h" |
||||
#define PUSH(stack, size, type) (ALIGN((stack),ALIGNOF(type)),(void)(((int)((size)*(sizeof(type)/(sizeof(char)))) <= (scratch_ptr)+GLOBAL_STACK_SIZE-(stack))?0:CELT_FATAL("pseudostack overflow")),(stack)+=(size)*(sizeof(type)/(sizeof(char))),(type*)(void*)((stack)-(size)*(sizeof(type)/(sizeof(char))))) |
||||
#else |
||||
#define PUSH(stack, size, type) (ALIGN((stack),ALIGNOF(type)),(stack)+=(size)*(sizeof(type)/(sizeof(char))),(type*)(void*)((stack)-(size)*(sizeof(type)/(sizeof(char))))) |
||||
#endif |
||||
|
||||
#if 0 /* Set this to 1 to instrument pseudostack usage */
|
||||
#define RESTORE_STACK (printf("%ld %s:%d\n", global_stack-scratch_ptr, __FILE__, __LINE__),global_stack = _saved_stack) |
||||
#else |
||||
#define RESTORE_STACK (global_stack = _saved_stack) |
||||
#endif |
||||
#define ALLOC_STACK char *_saved_stack; (global_stack = (global_stack==0) ? (scratch_ptr=(char*)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; |
||||
#define ALLOC_NONE 0 |
||||
|
||||
#endif /* VAR_ARRAYS */ |
||||
|
||||
|
||||
#ifdef ENABLE_VALGRIND |
||||
|
||||
#include <valgrind/memcheck.h> |
||||
#define OPUS_CHECK_ARRAY(ptr, len) VALGRIND_CHECK_MEM_IS_DEFINED(ptr, len*sizeof(*ptr)) |
||||
#define OPUS_CHECK_VALUE(value) VALGRIND_CHECK_VALUE_IS_DEFINED(value) |
||||
#define OPUS_CHECK_ARRAY_COND(ptr, len) VALGRIND_CHECK_MEM_IS_DEFINED(ptr, len*sizeof(*ptr)) |
||||
#define OPUS_CHECK_VALUE_COND(value) VALGRIND_CHECK_VALUE_IS_DEFINED(value) |
||||
#define OPUS_PRINT_INT(value) do {fprintf(stderr, #value " = %d at %s:%d\n", value, __FILE__, __LINE__);}while(0) |
||||
#define OPUS_FPRINTF fprintf |
||||
|
||||
#else |
||||
|
||||
static OPUS_INLINE int _opus_false(void) {return 0;} |
||||
#define OPUS_CHECK_ARRAY(ptr, len) _opus_false() |
||||
#define OPUS_CHECK_VALUE(value) _opus_false() |
||||
#define OPUS_PRINT_INT(value) do{}while(0) |
||||
#define OPUS_FPRINTF (void) |
||||
|
||||
#endif |
||||
|
||||
|
||||
#endif /* STACK_ALLOC_H */ |
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,388 @@
|
||||
/* The contents of this file was automatically generated by
|
||||
* dump_mode_arm_ne10.c with arguments: 48000 960 |
||||
* It contains static definitions for some pre-defined modes. */ |
||||
#include <NE10_types.h> |
||||
|
||||
#ifndef NE10_FFT_PARAMS48000_960 |
||||
#define NE10_FFT_PARAMS48000_960 |
||||
static const ne10_int32_t ne10_factors_480[64] = { |
||||
4, 40, 4, 30, 2, 15, 5, 3, 3, 1, 1, 0, 0, 0, 0, |
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
||||
0, 0, 0, 0, }; |
||||
static const ne10_int32_t ne10_factors_240[64] = { |
||||
3, 20, 4, 15, 5, 3, 3, 1, 1, 0, 0, 0, 0, 0, 0, |
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
||||
0, 0, 0, 0, }; |
||||
static const ne10_int32_t ne10_factors_120[64] = { |
||||
3, 10, 2, 15, 5, 3, 3, 1, 1, 0, 0, 0, 0, 0, 0, |
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
||||
0, 0, 0, 0, }; |
||||
static const ne10_int32_t ne10_factors_60[64] = { |
||||
2, 5, 5, 3, 3, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, |
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
||||
0, 0, 0, 0, }; |
||||
static const ne10_fft_cpx_int32_t ne10_twiddles_480[480] = { |
||||
{0,0}, {2147483647,0}, {2147483647,0}, |
||||
{2147483647,0}, {1961823921,-873460313}, {1436946998,-1595891394}, |
||||
{2147483647,0}, {1436946998,-1595891394}, {-224473265,-2135719496}, |
||||
{2147483647,0}, {663608871,-2042378339}, {-1737350854,-1262259096}, |
||||
{2147483647,0}, {-224473265,-2135719496}, {-2100555935,446487152}, |
||||
{2147483647,0}, {2100555974,-446486968}, {1961823921,-873460313}, |
||||
{1737350743,-1262259248}, {1436946998,-1595891394}, {1073741769,-1859775424}, |
||||
{663608871,-2042378339}, {224473078,-2135719516}, {-224473265,-2135719496}, |
||||
{-663609049,-2042378281}, {-1073741932,-1859775330}, {-1436947137,-1595891268}, |
||||
{-1737350854,-1262259096}, {-1961823997,-873460141}, {-2100556013,-446486785}, |
||||
{2147483647,0}, {2144540595,-112390613}, {2135719506,-224473172}, |
||||
{2121044558,-335940465}, {2100555974,-446486968}, {2074309912,-555809682}, |
||||
{2042378310,-663608960}, {2004848691,-769589332}, {1961823921,-873460313}, |
||||
{1913421927,-974937199}, {1859775377,-1073741851}, {1801031311,-1169603450}, |
||||
{1737350743,-1262259248}, {1668908218,-1351455280}, {1595891331,-1436947067}, |
||||
{1518500216,-1518500282}, {1436946998,-1595891394}, {1351455207,-1668908277}, |
||||
{1262259172,-1737350799}, {1169603371,-1801031362}, {1073741769,-1859775424}, |
||||
{974937230,-1913421912}, {873460227,-1961823959}, {769589125,-2004848771}, |
||||
{663608871,-2042378339}, {555809715,-2074309903}, {446486876,-2100555994}, |
||||
{335940246,-2121044593}, {224473078,-2135719516}, {112390647,-2144540593}, |
||||
{2147483647,0}, {2135719506,-224473172}, {2100555974,-446486968}, |
||||
{2042378310,-663608960}, {1961823921,-873460313}, {1859775377,-1073741851}, |
||||
{1737350743,-1262259248}, {1595891331,-1436947067}, {1436946998,-1595891394}, |
||||
{1262259172,-1737350799}, {1073741769,-1859775424}, {873460227,-1961823959}, |
||||
{663608871,-2042378339}, {446486876,-2100555994}, {224473078,-2135719516}, |
||||
{-94,-2147483647}, {-224473265,-2135719496}, {-446487060,-2100555955}, |
||||
{-663609049,-2042378281}, {-873460398,-1961823883}, {-1073741932,-1859775330}, |
||||
{-1262259116,-1737350839}, {-1436947137,-1595891268}, {-1595891628,-1436946738}, |
||||
{-1737350854,-1262259096}, {-1859775343,-1073741910}, {-1961823997,-873460141}, |
||||
{-2042378447,-663608538}, {-2100556013,-446486785}, {-2135719499,-224473240}, |
||||
{2147483647,0}, {2121044558,-335940465}, {2042378310,-663608960}, |
||||
{1913421927,-974937199}, {1737350743,-1262259248}, {1518500216,-1518500282}, |
||||
{1262259172,-1737350799}, {974937230,-1913421912}, {663608871,-2042378339}, |
||||
{335940246,-2121044593}, {-94,-2147483647}, {-335940431,-2121044564}, |
||||
{-663609049,-2042378281}, {-974937397,-1913421827}, {-1262259116,-1737350839}, |
||||
{-1518500258,-1518500240}, {-1737350854,-1262259096}, {-1913422071,-974936918}, |
||||
{-2042378447,-663608538}, {-2121044568,-335940406}, {-2147483647,188}, |
||||
{-2121044509,335940777}, {-2042378331,663608895}, {-1913421900,974937252}, |
||||
{-1737350633,1262259400}, {-1518499993,1518500506}, {-1262258813,1737351059}, |
||||
{-974936606,1913422229}, {-663609179,2042378239}, {-335940566,2121044542}, |
||||
{2147483647,0}, {2147299667,-28109693}, {2146747758,-56214570}, |
||||
{2145828015,-84309815}, {2144540595,-112390613}, {2142885719,-140452154}, |
||||
{2140863671,-168489630}, {2138474797,-196498235}, {2135719506,-224473172}, |
||||
{2132598271,-252409646}, {2129111626,-280302871}, {2125260168,-308148068}, |
||||
{2121044558,-335940465}, {2116465518,-363675300}, {2111523833,-391347822}, |
||||
{2106220349,-418953288}, {2100555974,-446486968}, {2094531681,-473944146}, |
||||
{2088148500,-501320115}, {2081407525,-528610186}, {2074309912,-555809682}, |
||||
{2066856885,-582913912}, {2059049696,-609918325}, {2050889698,-636818231}, |
||||
{2042378310,-663608960}, {2033516972,-690285983}, {2024307180,-716844791}, |
||||
{2014750533,-743280770}, {2004848691,-769589332}, {1994603329,-795766029}, |
||||
{1984016179,-821806435}, {1973089077,-847706028}, {1961823921,-873460313}, |
||||
{1950222618,-899064934}, {1938287127,-924515564}, {1926019520,-949807783}, |
||||
{1913421927,-974937199}, {1900496481,-999899565}, {1887245364,-1024690661}, |
||||
{1873670877,-1049306180}, {1859775377,-1073741851}, {1845561215,-1097993541}, |
||||
{1831030826,-1122057097}, {1816186632,-1145928502}, {1801031311,-1169603450}, |
||||
{1785567394,-1193077993}, {1769797456,-1216348214}, {1753724345,-1239409914}, |
||||
{1737350743,-1262259248}, {1720679456,-1284892300}, {1703713340,-1307305194}, |
||||
{1686455222,-1329494189}, {1668908218,-1351455280}, {1651075255,-1373184807}, |
||||
{1632959307,-1394679144}, {1614563642,-1415934412}, {1595891331,-1436947067}, |
||||
{1576945572,-1457713510}, {1557729613,-1478230181}, {1538246655,-1498493658}, |
||||
{1518500216,-1518500282}, {1498493590,-1538246721}, {1478230113,-1557729677}, |
||||
{1457713441,-1576945636}, {1436946998,-1595891394}, {1415934341,-1614563704}, |
||||
{1394679073,-1632959368}, {1373184735,-1651075315}, {1351455207,-1668908277}, |
||||
{1329494115,-1686455280}, {1307305120,-1703713397}, {1284892225,-1720679512}, |
||||
{1262259172,-1737350799}, {1239409837,-1753724400}, {1216348136,-1769797510}, |
||||
{1193077915,-1785567446}, {1169603371,-1801031362}, {1145928423,-1816186682}, |
||||
{1122057017,-1831030875}, {1097993571,-1845561197}, {1073741769,-1859775424}, |
||||
{1049305987,-1873670985}, {1024690635,-1887245378}, {999899482,-1900496524}, |
||||
{974937230,-1913421912}, {949807699,-1926019561}, {924515422,-1938287195}, |
||||
{899064965,-1950222603}, {873460227,-1961823959}, {847705824,-1973089164}, |
||||
{821806407,-1984016190}, {795765941,-1994603364}, {769589125,-2004848771}, |
||||
{743280682,-2014750566}, {716844642,-2024307233}, {690286016,-2033516961}, |
||||
{663608871,-2042378339}, {636818019,-2050889764}, {609918296,-2059049705}, |
||||
{582913822,-2066856911}, {555809715,-2074309903}, {528610126,-2081407540}, |
||||
{501319962,-2088148536}, {473944148,-2094531680}, {446486876,-2100555994}, |
||||
{418953102,-2106220386}, {391347792,-2111523838}, {363675176,-2116465540}, |
||||
{335940246,-2121044593}, {308148006,-2125260177}, {280302715,-2129111646}, |
||||
{252409648,-2132598271}, {224473078,-2135719516}, {196498046,-2138474814}, |
||||
{168489600,-2140863674}, {140452029,-2142885728}, {112390647,-2144540593}, |
||||
{84309753,-2145828017}, {56214412,-2146747762}, {28109695,-2147299667}, |
||||
{2147483647,0}, {2146747758,-56214570}, {2144540595,-112390613}, |
||||
{2140863671,-168489630}, {2135719506,-224473172}, {2129111626,-280302871}, |
||||
{2121044558,-335940465}, {2111523833,-391347822}, {2100555974,-446486968}, |
||||
{2088148500,-501320115}, {2074309912,-555809682}, {2059049696,-609918325}, |
||||
{2042378310,-663608960}, {2024307180,-716844791}, {2004848691,-769589332}, |
||||
{1984016179,-821806435}, {1961823921,-873460313}, {1938287127,-924515564}, |
||||
{1913421927,-974937199}, {1887245364,-1024690661}, {1859775377,-1073741851}, |
||||
{1831030826,-1122057097}, {1801031311,-1169603450}, {1769797456,-1216348214}, |
||||
{1737350743,-1262259248}, {1703713340,-1307305194}, {1668908218,-1351455280}, |
||||
{1632959307,-1394679144}, {1595891331,-1436947067}, {1557729613,-1478230181}, |
||||
{1518500216,-1518500282}, {1478230113,-1557729677}, {1436946998,-1595891394}, |
||||
{1394679073,-1632959368}, {1351455207,-1668908277}, {1307305120,-1703713397}, |
||||
{1262259172,-1737350799}, {1216348136,-1769797510}, {1169603371,-1801031362}, |
||||
{1122057017,-1831030875}, {1073741769,-1859775424}, {1024690635,-1887245378}, |
||||
{974937230,-1913421912}, {924515422,-1938287195}, {873460227,-1961823959}, |
||||
{821806407,-1984016190}, {769589125,-2004848771}, {716844642,-2024307233}, |
||||
{663608871,-2042378339}, {609918296,-2059049705}, {555809715,-2074309903}, |
||||
{501319962,-2088148536}, {446486876,-2100555994}, {391347792,-2111523838}, |
||||
{335940246,-2121044593}, {280302715,-2129111646}, {224473078,-2135719516}, |
||||
{168489600,-2140863674}, {112390647,-2144540593}, {56214412,-2146747762}, |
||||
{-94,-2147483647}, {-56214600,-2146747757}, {-112390835,-2144540584}, |
||||
{-168489787,-2140863659}, {-224473265,-2135719496}, {-280302901,-2129111622}, |
||||
{-335940431,-2121044564}, {-391347977,-2111523804}, {-446487060,-2100555955}, |
||||
{-501320144,-2088148493}, {-555809896,-2074309855}, {-609918476,-2059049651}, |
||||
{-663609049,-2042378281}, {-716844819,-2024307170}, {-769589300,-2004848703}, |
||||
{-821806581,-1984016118}, {-873460398,-1961823883}, {-924515591,-1938287114}, |
||||
{-974937397,-1913421827}, {-1024690575,-1887245411}, {-1073741932,-1859775330}, |
||||
{-1122057395,-1831030643}, {-1169603421,-1801031330}, {-1216348291,-1769797403}, |
||||
{-1262259116,-1737350839}, {-1307305268,-1703713283}, {-1351455453,-1668908078}, |
||||
{-1394679021,-1632959413}, {-1436947137,-1595891268}, {-1478230435,-1557729372}, |
||||
{-1518500258,-1518500240}, {-1557729742,-1478230045}, {-1595891628,-1436946738}, |
||||
{-1632959429,-1394679001}, {-1668908417,-1351455035}, {-1703713298,-1307305248}, |
||||
{-1737350854,-1262259096}, {-1769797708,-1216347848}, {-1801031344,-1169603400}, |
||||
{-1831030924,-1122056937}, {-1859775343,-1073741910}, {-1887245423,-1024690552}, |
||||
{-1913422071,-974936918}, {-1938287125,-924515568}, {-1961823997,-873460141}, |
||||
{-1984016324,-821806084}, {-2004848713,-769589276}, {-2024307264,-716844553}, |
||||
{-2042378447,-663608538}, {-2059049731,-609918206}, {-2074309994,-555809377}, |
||||
{-2088148499,-501320119}, {-2100556013,-446486785}, {-2111523902,-391347448}, |
||||
{-2121044568,-335940406}, {-2129111659,-280302621}, {-2135719499,-224473240}, |
||||
{-2140863681,-168489506}, {-2144540612,-112390298}, {-2146747758,-56214574}, |
||||
{2147483647,0}, {2145828015,-84309815}, {2140863671,-168489630}, |
||||
{2132598271,-252409646}, {2121044558,-335940465}, {2106220349,-418953288}, |
||||
{2088148500,-501320115}, {2066856885,-582913912}, {2042378310,-663608960}, |
||||
{2014750533,-743280770}, {1984016179,-821806435}, {1950222618,-899064934}, |
||||
{1913421927,-974937199}, {1873670877,-1049306180}, {1831030826,-1122057097}, |
||||
{1785567394,-1193077993}, {1737350743,-1262259248}, {1686455222,-1329494189}, |
||||
{1632959307,-1394679144}, {1576945572,-1457713510}, {1518500216,-1518500282}, |
||||
{1457713441,-1576945636}, {1394679073,-1632959368}, {1329494115,-1686455280}, |
||||
{1262259172,-1737350799}, {1193077915,-1785567446}, {1122057017,-1831030875}, |
||||
{1049305987,-1873670985}, {974937230,-1913421912}, {899064965,-1950222603}, |
||||
{821806407,-1984016190}, {743280682,-2014750566}, {663608871,-2042378339}, |
||||
{582913822,-2066856911}, {501319962,-2088148536}, {418953102,-2106220386}, |
||||
{335940246,-2121044593}, {252409648,-2132598271}, {168489600,-2140863674}, |
||||
{84309753,-2145828017}, {-94,-2147483647}, {-84309940,-2145828010}, |
||||
{-168489787,-2140863659}, {-252409834,-2132598249}, {-335940431,-2121044564}, |
||||
{-418953286,-2106220349}, {-501320144,-2088148493}, {-582914003,-2066856860}, |
||||
{-663609049,-2042378281}, {-743280858,-2014750501}, {-821806581,-1984016118}, |
||||
{-899065136,-1950222525}, {-974937397,-1913421827}, {-1049306374,-1873670768}, |
||||
{-1122057395,-1831030643}, {-1193078284,-1785567199}, {-1262259116,-1737350839}, |
||||
{-1329494061,-1686455323}, {-1394679021,-1632959413}, {-1457713485,-1576945595}, |
||||
{-1518500258,-1518500240}, {-1576945613,-1457713466}, {-1632959429,-1394679001}, |
||||
{-1686455338,-1329494041}, {-1737350854,-1262259096}, {-1785567498,-1193077837}, |
||||
{-1831030924,-1122056937}, {-1873671031,-1049305905}, {-1913422071,-974936918}, |
||||
{-1950222750,-899064648}, {-1984016324,-821806084}, {-2014750687,-743280354}, |
||||
{-2042378447,-663608538}, {-2066856867,-582913978}, {-2088148499,-501320119}, |
||||
{-2106220354,-418953261}, {-2121044568,-335940406}, {-2132598282,-252409555}, |
||||
{-2140863681,-168489506}, {-2145828021,-84309659}, {-2147483647,188}, |
||||
{-2145828006,84310034}, {-2140863651,168489881}, {-2132598237,252409928}, |
||||
{-2121044509,335940777}, {-2106220281,418953629}, {-2088148411,501320484}, |
||||
{-2066856765,582914339}, {-2042378331,663608895}, {-2014750557,743280706}, |
||||
{-1984016181,821806431}, {-1950222593,899064989}, {-1913421900,974937252}, |
||||
{-1873670848,1049306232}, {-1831030728,1122057257}, {-1785567289,1193078149}, |
||||
{-1737350633,1262259400}, {-1686455106,1329494336}, {-1632959185,1394679287}, |
||||
{-1576945358,1457713742}, {-1518499993,1518500506}, {-1457713209,1576945850}, |
||||
{-1394678735,1632959656}, {-1329493766,1686455555}, {-1262258813,1737351059}, |
||||
{-1193077546,1785567692}, {-1122056638,1831031107}, {-1049305599,1873671202}, |
||||
{-974936606,1913422229}, {-899064330,1950222896}, {-821805761,1984016458}, |
||||
{-743280025,2014750808}, {-663609179,2042378239}, {-582914134,2066856823}, |
||||
{-501320277,2088148461}, {-418953420,2106220322}, {-335940566,2121044542}, |
||||
{-252409716,2132598263}, {-168489668,2140863668}, {-84309821,2145828015}, |
||||
}; |
||||
static const ne10_fft_cpx_int32_t ne10_twiddles_240[240] = { |
||||
{0,0}, {2147483647,0}, {2147483647,0}, |
||||
{2147483647,0}, {1961823921,-873460313}, {1436946998,-1595891394}, |
||||
{2147483647,0}, {1436946998,-1595891394}, {-224473265,-2135719496}, |
||||
{2147483647,0}, {663608871,-2042378339}, {-1737350854,-1262259096}, |
||||
{2147483647,0}, {-224473265,-2135719496}, {-2100555935,446487152}, |
||||
{2147483647,0}, {2135719506,-224473172}, {2100555974,-446486968}, |
||||
{2042378310,-663608960}, {1961823921,-873460313}, {1859775377,-1073741851}, |
||||
{1737350743,-1262259248}, {1595891331,-1436947067}, {1436946998,-1595891394}, |
||||
{1262259172,-1737350799}, {1073741769,-1859775424}, {873460227,-1961823959}, |
||||
{663608871,-2042378339}, {446486876,-2100555994}, {224473078,-2135719516}, |
||||
{2147483647,0}, {2100555974,-446486968}, {1961823921,-873460313}, |
||||
{1737350743,-1262259248}, {1436946998,-1595891394}, {1073741769,-1859775424}, |
||||
{663608871,-2042378339}, {224473078,-2135719516}, {-224473265,-2135719496}, |
||||
{-663609049,-2042378281}, {-1073741932,-1859775330}, {-1436947137,-1595891268}, |
||||
{-1737350854,-1262259096}, {-1961823997,-873460141}, {-2100556013,-446486785}, |
||||
{2147483647,0}, {2042378310,-663608960}, {1737350743,-1262259248}, |
||||
{1262259172,-1737350799}, {663608871,-2042378339}, {-94,-2147483647}, |
||||
{-663609049,-2042378281}, {-1262259116,-1737350839}, {-1737350854,-1262259096}, |
||||
{-2042378447,-663608538}, {-2147483647,188}, {-2042378331,663608895}, |
||||
{-1737350633,1262259400}, {-1262258813,1737351059}, {-663609179,2042378239}, |
||||
{2147483647,0}, {2146747758,-56214570}, {2144540595,-112390613}, |
||||
{2140863671,-168489630}, {2135719506,-224473172}, {2129111626,-280302871}, |
||||
{2121044558,-335940465}, {2111523833,-391347822}, {2100555974,-446486968}, |
||||
{2088148500,-501320115}, {2074309912,-555809682}, {2059049696,-609918325}, |
||||
{2042378310,-663608960}, {2024307180,-716844791}, {2004848691,-769589332}, |
||||
{1984016179,-821806435}, {1961823921,-873460313}, {1938287127,-924515564}, |
||||
{1913421927,-974937199}, {1887245364,-1024690661}, {1859775377,-1073741851}, |
||||
{1831030826,-1122057097}, {1801031311,-1169603450}, {1769797456,-1216348214}, |
||||
{1737350743,-1262259248}, {1703713340,-1307305194}, {1668908218,-1351455280}, |
||||
{1632959307,-1394679144}, {1595891331,-1436947067}, {1557729613,-1478230181}, |
||||
{1518500216,-1518500282}, {1478230113,-1557729677}, {1436946998,-1595891394}, |
||||
{1394679073,-1632959368}, {1351455207,-1668908277}, {1307305120,-1703713397}, |
||||
{1262259172,-1737350799}, {1216348136,-1769797510}, {1169603371,-1801031362}, |
||||
{1122057017,-1831030875}, {1073741769,-1859775424}, {1024690635,-1887245378}, |
||||
{974937230,-1913421912}, {924515422,-1938287195}, {873460227,-1961823959}, |
||||
{821806407,-1984016190}, {769589125,-2004848771}, {716844642,-2024307233}, |
||||
{663608871,-2042378339}, {609918296,-2059049705}, {555809715,-2074309903}, |
||||
{501319962,-2088148536}, {446486876,-2100555994}, {391347792,-2111523838}, |
||||
{335940246,-2121044593}, {280302715,-2129111646}, {224473078,-2135719516}, |
||||
{168489600,-2140863674}, {112390647,-2144540593}, {56214412,-2146747762}, |
||||
{2147483647,0}, {2144540595,-112390613}, {2135719506,-224473172}, |
||||
{2121044558,-335940465}, {2100555974,-446486968}, {2074309912,-555809682}, |
||||
{2042378310,-663608960}, {2004848691,-769589332}, {1961823921,-873460313}, |
||||
{1913421927,-974937199}, {1859775377,-1073741851}, {1801031311,-1169603450}, |
||||
{1737350743,-1262259248}, {1668908218,-1351455280}, {1595891331,-1436947067}, |
||||
{1518500216,-1518500282}, {1436946998,-1595891394}, {1351455207,-1668908277}, |
||||
{1262259172,-1737350799}, {1169603371,-1801031362}, {1073741769,-1859775424}, |
||||
{974937230,-1913421912}, {873460227,-1961823959}, {769589125,-2004848771}, |
||||
{663608871,-2042378339}, {555809715,-2074309903}, {446486876,-2100555994}, |
||||
{335940246,-2121044593}, {224473078,-2135719516}, {112390647,-2144540593}, |
||||
{-94,-2147483647}, {-112390835,-2144540584}, {-224473265,-2135719496}, |
||||
{-335940431,-2121044564}, {-446487060,-2100555955}, {-555809896,-2074309855}, |
||||
{-663609049,-2042378281}, {-769589300,-2004848703}, {-873460398,-1961823883}, |
||||
{-974937397,-1913421827}, {-1073741932,-1859775330}, {-1169603421,-1801031330}, |
||||
{-1262259116,-1737350839}, {-1351455453,-1668908078}, {-1436947137,-1595891268}, |
||||
{-1518500258,-1518500240}, {-1595891628,-1436946738}, {-1668908417,-1351455035}, |
||||
{-1737350854,-1262259096}, {-1801031344,-1169603400}, {-1859775343,-1073741910}, |
||||
{-1913422071,-974936918}, {-1961823997,-873460141}, {-2004848713,-769589276}, |
||||
{-2042378447,-663608538}, {-2074309994,-555809377}, {-2100556013,-446486785}, |
||||
{-2121044568,-335940406}, {-2135719499,-224473240}, {-2144540612,-112390298}, |
||||
{2147483647,0}, {2140863671,-168489630}, {2121044558,-335940465}, |
||||
{2088148500,-501320115}, {2042378310,-663608960}, {1984016179,-821806435}, |
||||
{1913421927,-974937199}, {1831030826,-1122057097}, {1737350743,-1262259248}, |
||||
{1632959307,-1394679144}, {1518500216,-1518500282}, {1394679073,-1632959368}, |
||||
{1262259172,-1737350799}, {1122057017,-1831030875}, {974937230,-1913421912}, |
||||
{821806407,-1984016190}, {663608871,-2042378339}, {501319962,-2088148536}, |
||||
{335940246,-2121044593}, {168489600,-2140863674}, {-94,-2147483647}, |
||||
{-168489787,-2140863659}, {-335940431,-2121044564}, {-501320144,-2088148493}, |
||||
{-663609049,-2042378281}, {-821806581,-1984016118}, {-974937397,-1913421827}, |
||||
{-1122057395,-1831030643}, {-1262259116,-1737350839}, {-1394679021,-1632959413}, |
||||
{-1518500258,-1518500240}, {-1632959429,-1394679001}, {-1737350854,-1262259096}, |
||||
{-1831030924,-1122056937}, {-1913422071,-974936918}, {-1984016324,-821806084}, |
||||
{-2042378447,-663608538}, {-2088148499,-501320119}, {-2121044568,-335940406}, |
||||
{-2140863681,-168489506}, {-2147483647,188}, {-2140863651,168489881}, |
||||
{-2121044509,335940777}, {-2088148411,501320484}, {-2042378331,663608895}, |
||||
{-1984016181,821806431}, {-1913421900,974937252}, {-1831030728,1122057257}, |
||||
{-1737350633,1262259400}, {-1632959185,1394679287}, {-1518499993,1518500506}, |
||||
{-1394678735,1632959656}, {-1262258813,1737351059}, {-1122056638,1831031107}, |
||||
{-974936606,1913422229}, {-821805761,1984016458}, {-663609179,2042378239}, |
||||
{-501320277,2088148461}, {-335940566,2121044542}, {-168489668,2140863668}, |
||||
}; |
||||
static const ne10_fft_cpx_int32_t ne10_twiddles_120[120] = { |
||||
{0,0}, {2147483647,0}, {2147483647,0}, |
||||
{2147483647,0}, {1961823921,-873460313}, {1436946998,-1595891394}, |
||||
{2147483647,0}, {1436946998,-1595891394}, {-224473265,-2135719496}, |
||||
{2147483647,0}, {663608871,-2042378339}, {-1737350854,-1262259096}, |
||||
{2147483647,0}, {-224473265,-2135719496}, {-2100555935,446487152}, |
||||
{2147483647,0}, {2100555974,-446486968}, {1961823921,-873460313}, |
||||
{1737350743,-1262259248}, {1436946998,-1595891394}, {1073741769,-1859775424}, |
||||
{663608871,-2042378339}, {224473078,-2135719516}, {-224473265,-2135719496}, |
||||
{-663609049,-2042378281}, {-1073741932,-1859775330}, {-1436947137,-1595891268}, |
||||
{-1737350854,-1262259096}, {-1961823997,-873460141}, {-2100556013,-446486785}, |
||||
{2147483647,0}, {2144540595,-112390613}, {2135719506,-224473172}, |
||||
{2121044558,-335940465}, {2100555974,-446486968}, {2074309912,-555809682}, |
||||
{2042378310,-663608960}, {2004848691,-769589332}, {1961823921,-873460313}, |
||||
{1913421927,-974937199}, {1859775377,-1073741851}, {1801031311,-1169603450}, |
||||
{1737350743,-1262259248}, {1668908218,-1351455280}, {1595891331,-1436947067}, |
||||
{1518500216,-1518500282}, {1436946998,-1595891394}, {1351455207,-1668908277}, |
||||
{1262259172,-1737350799}, {1169603371,-1801031362}, {1073741769,-1859775424}, |
||||
{974937230,-1913421912}, {873460227,-1961823959}, {769589125,-2004848771}, |
||||
{663608871,-2042378339}, {555809715,-2074309903}, {446486876,-2100555994}, |
||||
{335940246,-2121044593}, {224473078,-2135719516}, {112390647,-2144540593}, |
||||
{2147483647,0}, {2135719506,-224473172}, {2100555974,-446486968}, |
||||
{2042378310,-663608960}, {1961823921,-873460313}, {1859775377,-1073741851}, |
||||
{1737350743,-1262259248}, {1595891331,-1436947067}, {1436946998,-1595891394}, |
||||
{1262259172,-1737350799}, {1073741769,-1859775424}, {873460227,-1961823959}, |
||||
{663608871,-2042378339}, {446486876,-2100555994}, {224473078,-2135719516}, |
||||
{-94,-2147483647}, {-224473265,-2135719496}, {-446487060,-2100555955}, |
||||
{-663609049,-2042378281}, {-873460398,-1961823883}, {-1073741932,-1859775330}, |
||||
{-1262259116,-1737350839}, {-1436947137,-1595891268}, {-1595891628,-1436946738}, |
||||
{-1737350854,-1262259096}, {-1859775343,-1073741910}, {-1961823997,-873460141}, |
||||
{-2042378447,-663608538}, {-2100556013,-446486785}, {-2135719499,-224473240}, |
||||
{2147483647,0}, {2121044558,-335940465}, {2042378310,-663608960}, |
||||
{1913421927,-974937199}, {1737350743,-1262259248}, {1518500216,-1518500282}, |
||||
{1262259172,-1737350799}, {974937230,-1913421912}, {663608871,-2042378339}, |
||||
{335940246,-2121044593}, {-94,-2147483647}, {-335940431,-2121044564}, |
||||
{-663609049,-2042378281}, {-974937397,-1913421827}, {-1262259116,-1737350839}, |
||||
{-1518500258,-1518500240}, {-1737350854,-1262259096}, {-1913422071,-974936918}, |
||||
{-2042378447,-663608538}, {-2121044568,-335940406}, {-2147483647,188}, |
||||
{-2121044509,335940777}, {-2042378331,663608895}, {-1913421900,974937252}, |
||||
{-1737350633,1262259400}, {-1518499993,1518500506}, {-1262258813,1737351059}, |
||||
{-974936606,1913422229}, {-663609179,2042378239}, {-335940566,2121044542}, |
||||
}; |
||||
static const ne10_fft_cpx_int32_t ne10_twiddles_60[60] = { |
||||
{0,0}, {2147483647,0}, {2147483647,0}, |
||||
{2147483647,0}, {1961823921,-873460313}, {1436946998,-1595891394}, |
||||
{2147483647,0}, {1436946998,-1595891394}, {-224473265,-2135719496}, |
||||
{2147483647,0}, {663608871,-2042378339}, {-1737350854,-1262259096}, |
||||
{2147483647,0}, {-224473265,-2135719496}, {-2100555935,446487152}, |
||||
{2147483647,0}, {2135719506,-224473172}, {2100555974,-446486968}, |
||||
{2042378310,-663608960}, {1961823921,-873460313}, {1859775377,-1073741851}, |
||||
{1737350743,-1262259248}, {1595891331,-1436947067}, {1436946998,-1595891394}, |
||||
{1262259172,-1737350799}, {1073741769,-1859775424}, {873460227,-1961823959}, |
||||
{663608871,-2042378339}, {446486876,-2100555994}, {224473078,-2135719516}, |
||||
{2147483647,0}, {2100555974,-446486968}, {1961823921,-873460313}, |
||||
{1737350743,-1262259248}, {1436946998,-1595891394}, {1073741769,-1859775424}, |
||||
{663608871,-2042378339}, {224473078,-2135719516}, {-224473265,-2135719496}, |
||||
{-663609049,-2042378281}, {-1073741932,-1859775330}, {-1436947137,-1595891268}, |
||||
{-1737350854,-1262259096}, {-1961823997,-873460141}, {-2100556013,-446486785}, |
||||
{2147483647,0}, {2042378310,-663608960}, {1737350743,-1262259248}, |
||||
{1262259172,-1737350799}, {663608871,-2042378339}, {-94,-2147483647}, |
||||
{-663609049,-2042378281}, {-1262259116,-1737350839}, {-1737350854,-1262259096}, |
||||
{-2042378447,-663608538}, {-2147483647,188}, {-2042378331,663608895}, |
||||
{-1737350633,1262259400}, {-1262258813,1737351059}, {-663609179,2042378239}, |
||||
}; |
||||
static const ne10_fft_state_int32_t ne10_fft_state_int32_t_480 = { |
||||
120, |
||||
(ne10_int32_t *)ne10_factors_480, |
||||
(ne10_fft_cpx_int32_t *)ne10_twiddles_480, |
||||
NULL, |
||||
(ne10_fft_cpx_int32_t *)&ne10_twiddles_480[120], |
||||
}; |
||||
static const arch_fft_state cfg_arch_480 = { |
||||
1, |
||||
(void *)&ne10_fft_state_int32_t_480, |
||||
}; |
||||
|
||||
static const ne10_fft_state_int32_t ne10_fft_state_int32_t_240 = { |
||||
60, |
||||
(ne10_int32_t *)ne10_factors_240, |
||||
(ne10_fft_cpx_int32_t *)ne10_twiddles_240, |
||||
NULL, |
||||
(ne10_fft_cpx_int32_t *)&ne10_twiddles_240[60], |
||||
}; |
||||
static const arch_fft_state cfg_arch_240 = { |
||||
1, |
||||
(void *)&ne10_fft_state_int32_t_240, |
||||
}; |
||||
|
||||
static const ne10_fft_state_int32_t ne10_fft_state_int32_t_120 = { |
||||
30, |
||||
(ne10_int32_t *)ne10_factors_120, |
||||
(ne10_fft_cpx_int32_t *)ne10_twiddles_120, |
||||
NULL, |
||||
(ne10_fft_cpx_int32_t *)&ne10_twiddles_120[30], |
||||
}; |
||||
static const arch_fft_state cfg_arch_120 = { |
||||
1, |
||||
(void *)&ne10_fft_state_int32_t_120, |
||||
}; |
||||
|
||||
static const ne10_fft_state_int32_t ne10_fft_state_int32_t_60 = { |
||||
15, |
||||
(ne10_int32_t *)ne10_factors_60, |
||||
(ne10_fft_cpx_int32_t *)ne10_twiddles_60, |
||||
NULL, |
||||
(ne10_fft_cpx_int32_t *)&ne10_twiddles_60[15], |
||||
}; |
||||
static const arch_fft_state cfg_arch_60 = { |
||||
1, |
||||
(void *)&ne10_fft_state_int32_t_60, |
||||
}; |
||||
|
||||
#endif /* end NE10_FFT_PARAMS48000_960 */ |
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,404 @@
|
||||
/* The contents of this file was automatically generated by
|
||||
* dump_mode_arm_ne10.c with arguments: 48000 960 |
||||
* It contains static definitions for some pre-defined modes. */ |
||||
#include <NE10_types.h> |
||||
|
||||
#ifndef NE10_FFT_PARAMS48000_960 |
||||
#define NE10_FFT_PARAMS48000_960 |
||||
static const ne10_int32_t ne10_factors_480[64] = { |
||||
4, 40, 4, 30, 2, 15, 5, 3, 3, 1, 1, 0, 0, 0, 0, |
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
||||
0, 0, 0, 0, }; |
||||
static const ne10_int32_t ne10_factors_240[64] = { |
||||
3, 20, 4, 15, 5, 3, 3, 1, 1, 0, 0, 0, 0, 0, 0, |
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
||||
0, 0, 0, 0, }; |
||||
static const ne10_int32_t ne10_factors_120[64] = { |
||||
3, 10, 2, 15, 5, 3, 3, 1, 1, 0, 0, 0, 0, 0, 0, |
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
||||
0, 0, 0, 0, }; |
||||
static const ne10_int32_t ne10_factors_60[64] = { |
||||
2, 5, 5, 3, 3, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, |
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
||||
0, 0, 0, 0, }; |
||||
static const ne10_fft_cpx_float32_t ne10_twiddles_480[480] = { |
||||
{1.0000000f,0.0000000f}, {1.0000000f,-0.0000000f}, {1.0000000f,-0.0000000f}, |
||||
{1.0000000f,-0.0000000f}, {0.91354543f,-0.40673664f}, {0.66913056f,-0.74314487f}, |
||||
{1.0000000f,-0.0000000f}, {0.66913056f,-0.74314487f}, {-0.10452851f,-0.99452192f}, |
||||
{1.0000000f,-0.0000000f}, {0.30901697f,-0.95105654f}, {-0.80901700f,-0.58778518f}, |
||||
{1.0000000f,-0.0000000f}, {-0.10452851f,-0.99452192f}, {-0.97814757f,0.20791179f}, |
||||
{1.0000000f,-0.0000000f}, {0.97814763f,-0.20791170f}, {0.91354543f,-0.40673664f}, |
||||
{0.80901700f,-0.58778524f}, {0.66913056f,-0.74314487f}, {0.49999997f,-0.86602545f}, |
||||
{0.30901697f,-0.95105654f}, {0.10452842f,-0.99452192f}, {-0.10452851f,-0.99452192f}, |
||||
{-0.30901703f,-0.95105648f}, {-0.50000006f,-0.86602533f}, {-0.66913068f,-0.74314475f}, |
||||
{-0.80901700f,-0.58778518f}, {-0.91354549f,-0.40673658f}, {-0.97814763f,-0.20791161f}, |
||||
{1.0000000f,-0.0000000f}, {0.99862951f,-0.052335959f}, {0.99452192f,-0.10452846f}, |
||||
{0.98768836f,-0.15643448f}, {0.97814763f,-0.20791170f}, {0.96592581f,-0.25881904f}, |
||||
{0.95105648f,-0.30901700f}, {0.93358040f,-0.35836795f}, {0.91354543f,-0.40673664f}, |
||||
{0.89100653f,-0.45399052f}, {0.86602545f,-0.50000000f}, {0.83867055f,-0.54463905f}, |
||||
{0.80901700f,-0.58778524f}, {0.77714598f,-0.62932038f}, {0.74314475f,-0.66913062f}, |
||||
{0.70710677f,-0.70710683f}, {0.66913056f,-0.74314487f}, {0.62932038f,-0.77714598f}, |
||||
{0.58778524f,-0.80901700f}, {0.54463899f,-0.83867055f}, {0.49999997f,-0.86602545f}, |
||||
{0.45399052f,-0.89100653f}, {0.40673661f,-0.91354549f}, {0.35836786f,-0.93358046f}, |
||||
{0.30901697f,-0.95105654f}, {0.25881907f,-0.96592581f}, {0.20791166f,-0.97814763f}, |
||||
{0.15643437f,-0.98768836f}, {0.10452842f,-0.99452192f}, {0.052335974f,-0.99862951f}, |
||||
{1.0000000f,-0.0000000f}, {0.99452192f,-0.10452846f}, {0.97814763f,-0.20791170f}, |
||||
{0.95105648f,-0.30901700f}, {0.91354543f,-0.40673664f}, {0.86602545f,-0.50000000f}, |
||||
{0.80901700f,-0.58778524f}, {0.74314475f,-0.66913062f}, {0.66913056f,-0.74314487f}, |
||||
{0.58778524f,-0.80901700f}, {0.49999997f,-0.86602545f}, {0.40673661f,-0.91354549f}, |
||||
{0.30901697f,-0.95105654f}, {0.20791166f,-0.97814763f}, {0.10452842f,-0.99452192f}, |
||||
{-4.3711388e-08f,-1.0000000f}, {-0.10452851f,-0.99452192f}, {-0.20791174f,-0.97814757f}, |
||||
{-0.30901703f,-0.95105648f}, {-0.40673670f,-0.91354543f}, {-0.50000006f,-0.86602533f}, |
||||
{-0.58778518f,-0.80901700f}, {-0.66913068f,-0.74314475f}, {-0.74314493f,-0.66913044f}, |
||||
{-0.80901700f,-0.58778518f}, {-0.86602539f,-0.50000006f}, {-0.91354549f,-0.40673658f}, |
||||
{-0.95105654f,-0.30901679f}, {-0.97814763f,-0.20791161f}, {-0.99452192f,-0.10452849f}, |
||||
{1.0000000f,-0.0000000f}, {0.98768836f,-0.15643448f}, {0.95105648f,-0.30901700f}, |
||||
{0.89100653f,-0.45399052f}, {0.80901700f,-0.58778524f}, {0.70710677f,-0.70710683f}, |
||||
{0.58778524f,-0.80901700f}, {0.45399052f,-0.89100653f}, {0.30901697f,-0.95105654f}, |
||||
{0.15643437f,-0.98768836f}, {-4.3711388e-08f,-1.0000000f}, {-0.15643445f,-0.98768836f}, |
||||
{-0.30901703f,-0.95105648f}, {-0.45399061f,-0.89100647f}, {-0.58778518f,-0.80901700f}, |
||||
{-0.70710677f,-0.70710677f}, {-0.80901700f,-0.58778518f}, {-0.89100659f,-0.45399037f}, |
||||
{-0.95105654f,-0.30901679f}, {-0.98768836f,-0.15643445f}, {-1.0000000f,8.7422777e-08f}, |
||||
{-0.98768830f,0.15643461f}, {-0.95105654f,0.30901697f}, {-0.89100653f,0.45399055f}, |
||||
{-0.80901694f,0.58778536f}, {-0.70710665f,0.70710689f}, {-0.58778507f,0.80901712f}, |
||||
{-0.45399022f,0.89100665f}, {-0.30901709f,0.95105648f}, {-0.15643452f,0.98768830f}, |
||||
{1.0000000f,-0.0000000f}, {0.99991435f,-0.013089596f}, {0.99965733f,-0.026176950f}, |
||||
{0.99922901f,-0.039259817f}, {0.99862951f,-0.052335959f}, {0.99785894f,-0.065403134f}, |
||||
{0.99691731f,-0.078459099f}, {0.99580491f,-0.091501623f}, {0.99452192f,-0.10452846f}, |
||||
{0.99306846f,-0.11753740f}, {0.99144489f,-0.13052620f}, {0.98965138f,-0.14349262f}, |
||||
{0.98768836f,-0.15643448f}, {0.98555607f,-0.16934951f}, {0.98325491f,-0.18223552f}, |
||||
{0.98078525f,-0.19509032f}, {0.97814763f,-0.20791170f}, {0.97534233f,-0.22069745f}, |
||||
{0.97236991f,-0.23344538f}, {0.96923089f,-0.24615330f}, {0.96592581f,-0.25881904f}, |
||||
{0.96245521f,-0.27144045f}, {0.95881975f,-0.28401536f}, {0.95501995f,-0.29654160f}, |
||||
{0.95105648f,-0.30901700f}, {0.94693011f,-0.32143945f}, {0.94264150f,-0.33380687f}, |
||||
{0.93819129f,-0.34611708f}, {0.93358040f,-0.35836795f}, {0.92880952f,-0.37055743f}, |
||||
{0.92387956f,-0.38268346f}, {0.91879117f,-0.39474389f}, {0.91354543f,-0.40673664f}, |
||||
{0.90814316f,-0.41865975f}, {0.90258527f,-0.43051112f}, {0.89687270f,-0.44228873f}, |
||||
{0.89100653f,-0.45399052f}, {0.88498765f,-0.46561453f}, {0.87881708f,-0.47715878f}, |
||||
{0.87249601f,-0.48862126f}, {0.86602545f,-0.50000000f}, {0.85940641f,-0.51129311f}, |
||||
{0.85264015f,-0.52249855f}, {0.84572786f,-0.53361452f}, {0.83867055f,-0.54463905f}, |
||||
{0.83146960f,-0.55557024f}, {0.82412618f,-0.56640625f}, {0.81664151f,-0.57714522f}, |
||||
{0.80901700f,-0.58778524f}, {0.80125380f,-0.59832460f}, {0.79335332f,-0.60876143f}, |
||||
{0.78531694f,-0.61909395f}, {0.77714598f,-0.62932038f}, {0.76884180f,-0.63943899f}, |
||||
{0.76040596f,-0.64944810f}, {0.75183982f,-0.65934587f}, {0.74314475f,-0.66913062f}, |
||||
{0.73432249f,-0.67880076f}, {0.72537434f,-0.68835455f}, {0.71630192f,-0.69779050f}, |
||||
{0.70710677f,-0.70710683f}, {0.69779044f,-0.71630198f}, {0.68835455f,-0.72537440f}, |
||||
{0.67880070f,-0.73432255f}, {0.66913056f,-0.74314487f}, {0.65934581f,-0.75183982f}, |
||||
{0.64944804f,-0.76040596f}, {0.63943899f,-0.76884186f}, {0.62932038f,-0.77714598f}, |
||||
{0.61909395f,-0.78531694f}, {0.60876137f,-0.79335338f}, {0.59832460f,-0.80125386f}, |
||||
{0.58778524f,-0.80901700f}, {0.57714516f,-0.81664151f}, {0.56640625f,-0.82412618f}, |
||||
{0.55557019f,-0.83146960f}, {0.54463899f,-0.83867055f}, {0.53361452f,-0.84572786f}, |
||||
{0.52249849f,-0.85264015f}, {0.51129311f,-0.85940641f}, {0.49999997f,-0.86602545f}, |
||||
{0.48862118f,-0.87249601f}, {0.47715876f,-0.87881708f}, {0.46561447f,-0.88498765f}, |
||||
{0.45399052f,-0.89100653f}, {0.44228867f,-0.89687276f}, {0.43051103f,-0.90258533f}, |
||||
{0.41865975f,-0.90814316f}, {0.40673661f,-0.91354549f}, {0.39474380f,-0.91879129f}, |
||||
{0.38268343f,-0.92387956f}, {0.37055740f,-0.92880958f}, {0.35836786f,-0.93358046f}, |
||||
{0.34611705f,-0.93819135f}, {0.33380681f,-0.94264150f}, {0.32143947f,-0.94693011f}, |
||||
{0.30901697f,-0.95105654f}, {0.29654151f,-0.95501995f}, {0.28401533f,-0.95881975f}, |
||||
{0.27144039f,-0.96245527f}, {0.25881907f,-0.96592581f}, {0.24615327f,-0.96923089f}, |
||||
{0.23344530f,-0.97236991f}, {0.22069745f,-0.97534233f}, {0.20791166f,-0.97814763f}, |
||||
{0.19509023f,-0.98078531f}, {0.18223552f,-0.98325491f}, {0.16934945f,-0.98555607f}, |
||||
{0.15643437f,-0.98768836f}, {0.14349259f,-0.98965138f}, {0.13052613f,-0.99144489f}, |
||||
{0.11753740f,-0.99306846f}, {0.10452842f,-0.99452192f}, {0.091501534f,-0.99580491f}, |
||||
{0.078459084f,-0.99691731f}, {0.065403074f,-0.99785894f}, {0.052335974f,-0.99862951f}, |
||||
{0.039259788f,-0.99922901f}, {0.026176875f,-0.99965733f}, {0.013089597f,-0.99991435f}, |
||||
{1.0000000f,-0.0000000f}, {0.99965733f,-0.026176950f}, {0.99862951f,-0.052335959f}, |
||||
{0.99691731f,-0.078459099f}, {0.99452192f,-0.10452846f}, {0.99144489f,-0.13052620f}, |
||||
{0.98768836f,-0.15643448f}, {0.98325491f,-0.18223552f}, {0.97814763f,-0.20791170f}, |
||||
{0.97236991f,-0.23344538f}, {0.96592581f,-0.25881904f}, {0.95881975f,-0.28401536f}, |
||||
{0.95105648f,-0.30901700f}, {0.94264150f,-0.33380687f}, {0.93358040f,-0.35836795f}, |
||||
{0.92387956f,-0.38268346f}, {0.91354543f,-0.40673664f}, {0.90258527f,-0.43051112f}, |
||||
{0.89100653f,-0.45399052f}, {0.87881708f,-0.47715878f}, {0.86602545f,-0.50000000f}, |
||||
{0.85264015f,-0.52249855f}, {0.83867055f,-0.54463905f}, {0.82412618f,-0.56640625f}, |
||||
{0.80901700f,-0.58778524f}, {0.79335332f,-0.60876143f}, {0.77714598f,-0.62932038f}, |
||||
{0.76040596f,-0.64944810f}, {0.74314475f,-0.66913062f}, {0.72537434f,-0.68835455f}, |
||||
{0.70710677f,-0.70710683f}, {0.68835455f,-0.72537440f}, {0.66913056f,-0.74314487f}, |
||||
{0.64944804f,-0.76040596f}, {0.62932038f,-0.77714598f}, {0.60876137f,-0.79335338f}, |
||||
{0.58778524f,-0.80901700f}, {0.56640625f,-0.82412618f}, {0.54463899f,-0.83867055f}, |
||||
{0.52249849f,-0.85264015f}, {0.49999997f,-0.86602545f}, {0.47715876f,-0.87881708f}, |
||||
{0.45399052f,-0.89100653f}, {0.43051103f,-0.90258533f}, {0.40673661f,-0.91354549f}, |
||||
{0.38268343f,-0.92387956f}, {0.35836786f,-0.93358046f}, {0.33380681f,-0.94264150f}, |
||||
{0.30901697f,-0.95105654f}, {0.28401533f,-0.95881975f}, {0.25881907f,-0.96592581f}, |
||||
{0.23344530f,-0.97236991f}, {0.20791166f,-0.97814763f}, {0.18223552f,-0.98325491f}, |
||||
{0.15643437f,-0.98768836f}, {0.13052613f,-0.99144489f}, {0.10452842f,-0.99452192f}, |
||||
{0.078459084f,-0.99691731f}, {0.052335974f,-0.99862951f}, {0.026176875f,-0.99965733f}, |
||||
{-4.3711388e-08f,-1.0000000f}, {-0.026176963f,-0.99965733f}, {-0.052336060f,-0.99862951f}, |
||||
{-0.078459173f,-0.99691731f}, {-0.10452851f,-0.99452192f}, {-0.13052621f,-0.99144489f}, |
||||
{-0.15643445f,-0.98768836f}, {-0.18223560f,-0.98325491f}, {-0.20791174f,-0.97814757f}, |
||||
{-0.23344538f,-0.97236991f}, {-0.25881916f,-0.96592581f}, {-0.28401542f,-0.95881969f}, |
||||
{-0.30901703f,-0.95105648f}, {-0.33380687f,-0.94264150f}, {-0.35836795f,-0.93358040f}, |
||||
{-0.38268352f,-0.92387950f}, {-0.40673670f,-0.91354543f}, {-0.43051112f,-0.90258527f}, |
||||
{-0.45399061f,-0.89100647f}, {-0.47715873f,-0.87881708f}, {-0.50000006f,-0.86602533f}, |
||||
{-0.52249867f,-0.85264009f}, {-0.54463905f,-0.83867055f}, {-0.56640631f,-0.82412612f}, |
||||
{-0.58778518f,-0.80901700f}, {-0.60876143f,-0.79335332f}, {-0.62932050f,-0.77714586f}, |
||||
{-0.64944804f,-0.76040596f}, {-0.66913068f,-0.74314475f}, {-0.68835467f,-0.72537428f}, |
||||
{-0.70710677f,-0.70710677f}, {-0.72537446f,-0.68835449f}, {-0.74314493f,-0.66913044f}, |
||||
{-0.76040596f,-0.64944804f}, {-0.77714604f,-0.62932026f}, {-0.79335332f,-0.60876143f}, |
||||
{-0.80901700f,-0.58778518f}, {-0.82412624f,-0.56640613f}, {-0.83867055f,-0.54463899f}, |
||||
{-0.85264021f,-0.52249849f}, {-0.86602539f,-0.50000006f}, {-0.87881714f,-0.47715873f}, |
||||
{-0.89100659f,-0.45399037f}, {-0.90258527f,-0.43051112f}, {-0.91354549f,-0.40673658f}, |
||||
{-0.92387956f,-0.38268328f}, {-0.93358040f,-0.35836792f}, {-0.94264150f,-0.33380675f}, |
||||
{-0.95105654f,-0.30901679f}, {-0.95881975f,-0.28401530f}, {-0.96592587f,-0.25881892f}, |
||||
{-0.97236991f,-0.23344538f}, {-0.97814763f,-0.20791161f}, {-0.98325491f,-0.18223536f}, |
||||
{-0.98768836f,-0.15643445f}, {-0.99144489f,-0.13052608f}, {-0.99452192f,-0.10452849f}, |
||||
{-0.99691737f,-0.078459039f}, {-0.99862957f,-0.052335810f}, {-0.99965733f,-0.026176952f}, |
||||
{1.0000000f,-0.0000000f}, {0.99922901f,-0.039259817f}, {0.99691731f,-0.078459099f}, |
||||
{0.99306846f,-0.11753740f}, {0.98768836f,-0.15643448f}, {0.98078525f,-0.19509032f}, |
||||
{0.97236991f,-0.23344538f}, {0.96245521f,-0.27144045f}, {0.95105648f,-0.30901700f}, |
||||
{0.93819129f,-0.34611708f}, {0.92387956f,-0.38268346f}, {0.90814316f,-0.41865975f}, |
||||
{0.89100653f,-0.45399052f}, {0.87249601f,-0.48862126f}, {0.85264015f,-0.52249855f}, |
||||
{0.83146960f,-0.55557024f}, {0.80901700f,-0.58778524f}, {0.78531694f,-0.61909395f}, |
||||
{0.76040596f,-0.64944810f}, {0.73432249f,-0.67880076f}, {0.70710677f,-0.70710683f}, |
||||
{0.67880070f,-0.73432255f}, {0.64944804f,-0.76040596f}, {0.61909395f,-0.78531694f}, |
||||
{0.58778524f,-0.80901700f}, {0.55557019f,-0.83146960f}, {0.52249849f,-0.85264015f}, |
||||
{0.48862118f,-0.87249601f}, {0.45399052f,-0.89100653f}, {0.41865975f,-0.90814316f}, |
||||
{0.38268343f,-0.92387956f}, {0.34611705f,-0.93819135f}, {0.30901697f,-0.95105654f}, |
||||
{0.27144039f,-0.96245527f}, {0.23344530f,-0.97236991f}, {0.19509023f,-0.98078531f}, |
||||
{0.15643437f,-0.98768836f}, {0.11753740f,-0.99306846f}, {0.078459084f,-0.99691731f}, |
||||
{0.039259788f,-0.99922901f}, {-4.3711388e-08f,-1.0000000f}, {-0.039259877f,-0.99922901f}, |
||||
{-0.078459173f,-0.99691731f}, {-0.11753749f,-0.99306846f}, {-0.15643445f,-0.98768836f}, |
||||
{-0.19509032f,-0.98078525f}, {-0.23344538f,-0.97236991f}, {-0.27144048f,-0.96245521f}, |
||||
{-0.30901703f,-0.95105648f}, {-0.34611711f,-0.93819129f}, {-0.38268352f,-0.92387950f}, |
||||
{-0.41865984f,-0.90814310f}, {-0.45399061f,-0.89100647f}, {-0.48862135f,-0.87249595f}, |
||||
{-0.52249867f,-0.85264009f}, {-0.55557036f,-0.83146954f}, {-0.58778518f,-0.80901700f}, |
||||
{-0.61909389f,-0.78531694f}, {-0.64944804f,-0.76040596f}, {-0.67880076f,-0.73432249f}, |
||||
{-0.70710677f,-0.70710677f}, {-0.73432249f,-0.67880070f}, {-0.76040596f,-0.64944804f}, |
||||
{-0.78531694f,-0.61909389f}, {-0.80901700f,-0.58778518f}, {-0.83146966f,-0.55557019f}, |
||||
{-0.85264021f,-0.52249849f}, {-0.87249607f,-0.48862115f}, {-0.89100659f,-0.45399037f}, |
||||
{-0.90814322f,-0.41865960f}, {-0.92387956f,-0.38268328f}, {-0.93819135f,-0.34611690f}, |
||||
{-0.95105654f,-0.30901679f}, {-0.96245521f,-0.27144048f}, {-0.97236991f,-0.23344538f}, |
||||
{-0.98078531f,-0.19509031f}, {-0.98768836f,-0.15643445f}, {-0.99306846f,-0.11753736f}, |
||||
{-0.99691737f,-0.078459039f}, {-0.99922901f,-0.039259743f}, {-1.0000000f,8.7422777e-08f}, |
||||
{-0.99922901f,0.039259918f}, {-0.99691731f,0.078459218f}, {-0.99306846f,0.11753753f}, |
||||
{-0.98768830f,0.15643461f}, {-0.98078525f,0.19509049f}, {-0.97236985f,0.23344554f}, |
||||
{-0.96245515f,0.27144065f}, {-0.95105654f,0.30901697f}, {-0.93819135f,0.34611705f}, |
||||
{-0.92387956f,0.38268346f}, {-0.90814316f,0.41865975f}, {-0.89100653f,0.45399055f}, |
||||
{-0.87249601f,0.48862129f}, {-0.85264015f,0.52249861f}, {-0.83146960f,0.55557030f}, |
||||
{-0.80901694f,0.58778536f}, {-0.78531688f,0.61909401f}, {-0.76040590f,0.64944816f}, |
||||
{-0.73432243f,0.67880082f}, {-0.70710665f,0.70710689f}, {-0.67880058f,0.73432261f}, |
||||
{-0.64944792f,0.76040608f}, {-0.61909378f,0.78531706f}, {-0.58778507f,0.80901712f}, |
||||
{-0.55557001f,0.83146977f}, {-0.52249837f,0.85264033f}, {-0.48862100f,0.87249613f}, |
||||
{-0.45399022f,0.89100665f}, {-0.41865945f,0.90814328f}, {-0.38268313f,0.92387968f}, |
||||
{-0.34611672f,0.93819147f}, {-0.30901709f,0.95105648f}, {-0.27144054f,0.96245521f}, |
||||
{-0.23344545f,0.97236991f}, {-0.19509038f,0.98078525f}, {-0.15643452f,0.98768830f}, |
||||
{-0.11753743f,0.99306846f}, {-0.078459114f,0.99691731f}, {-0.039259821f,0.99922901f}, |
||||
}; |
||||
static const ne10_fft_cpx_float32_t ne10_twiddles_240[240] = { |
||||
{1.0000000f,0.0000000f}, {1.0000000f,-0.0000000f}, {1.0000000f,-0.0000000f}, |
||||
{1.0000000f,-0.0000000f}, {0.91354543f,-0.40673664f}, {0.66913056f,-0.74314487f}, |
||||
{1.0000000f,-0.0000000f}, {0.66913056f,-0.74314487f}, {-0.10452851f,-0.99452192f}, |
||||
{1.0000000f,-0.0000000f}, {0.30901697f,-0.95105654f}, {-0.80901700f,-0.58778518f}, |
||||
{1.0000000f,-0.0000000f}, {-0.10452851f,-0.99452192f}, {-0.97814757f,0.20791179f}, |
||||
{1.0000000f,-0.0000000f}, {0.99452192f,-0.10452846f}, {0.97814763f,-0.20791170f}, |
||||
{0.95105648f,-0.30901700f}, {0.91354543f,-0.40673664f}, {0.86602545f,-0.50000000f}, |
||||
{0.80901700f,-0.58778524f}, {0.74314475f,-0.66913062f}, {0.66913056f,-0.74314487f}, |
||||
{0.58778524f,-0.80901700f}, {0.49999997f,-0.86602545f}, {0.40673661f,-0.91354549f}, |
||||
{0.30901697f,-0.95105654f}, {0.20791166f,-0.97814763f}, {0.10452842f,-0.99452192f}, |
||||
{1.0000000f,-0.0000000f}, {0.97814763f,-0.20791170f}, {0.91354543f,-0.40673664f}, |
||||
{0.80901700f,-0.58778524f}, {0.66913056f,-0.74314487f}, {0.49999997f,-0.86602545f}, |
||||
{0.30901697f,-0.95105654f}, {0.10452842f,-0.99452192f}, {-0.10452851f,-0.99452192f}, |
||||
{-0.30901703f,-0.95105648f}, {-0.50000006f,-0.86602533f}, {-0.66913068f,-0.74314475f}, |
||||
{-0.80901700f,-0.58778518f}, {-0.91354549f,-0.40673658f}, {-0.97814763f,-0.20791161f}, |
||||
{1.0000000f,-0.0000000f}, {0.95105648f,-0.30901700f}, {0.80901700f,-0.58778524f}, |
||||
{0.58778524f,-0.80901700f}, {0.30901697f,-0.95105654f}, {-4.3711388e-08f,-1.0000000f}, |
||||
{-0.30901703f,-0.95105648f}, {-0.58778518f,-0.80901700f}, {-0.80901700f,-0.58778518f}, |
||||
{-0.95105654f,-0.30901679f}, {-1.0000000f,8.7422777e-08f}, {-0.95105654f,0.30901697f}, |
||||
{-0.80901694f,0.58778536f}, {-0.58778507f,0.80901712f}, {-0.30901709f,0.95105648f}, |
||||
{1.0000000f,-0.0000000f}, {0.99965733f,-0.026176950f}, {0.99862951f,-0.052335959f}, |
||||
{0.99691731f,-0.078459099f}, {0.99452192f,-0.10452846f}, {0.99144489f,-0.13052620f}, |
||||
{0.98768836f,-0.15643448f}, {0.98325491f,-0.18223552f}, {0.97814763f,-0.20791170f}, |
||||
{0.97236991f,-0.23344538f}, {0.96592581f,-0.25881904f}, {0.95881975f,-0.28401536f}, |
||||
{0.95105648f,-0.30901700f}, {0.94264150f,-0.33380687f}, {0.93358040f,-0.35836795f}, |
||||
{0.92387956f,-0.38268346f}, {0.91354543f,-0.40673664f}, {0.90258527f,-0.43051112f}, |
||||
{0.89100653f,-0.45399052f}, {0.87881708f,-0.47715878f}, {0.86602545f,-0.50000000f}, |
||||
{0.85264015f,-0.52249855f}, {0.83867055f,-0.54463905f}, {0.82412618f,-0.56640625f}, |
||||
{0.80901700f,-0.58778524f}, {0.79335332f,-0.60876143f}, {0.77714598f,-0.62932038f}, |
||||
{0.76040596f,-0.64944810f}, {0.74314475f,-0.66913062f}, {0.72537434f,-0.68835455f}, |
||||
{0.70710677f,-0.70710683f}, {0.68835455f,-0.72537440f}, {0.66913056f,-0.74314487f}, |
||||
{0.64944804f,-0.76040596f}, {0.62932038f,-0.77714598f}, {0.60876137f,-0.79335338f}, |
||||
{0.58778524f,-0.80901700f}, {0.56640625f,-0.82412618f}, {0.54463899f,-0.83867055f}, |
||||
{0.52249849f,-0.85264015f}, {0.49999997f,-0.86602545f}, {0.47715876f,-0.87881708f}, |
||||
{0.45399052f,-0.89100653f}, {0.43051103f,-0.90258533f}, {0.40673661f,-0.91354549f}, |
||||
{0.38268343f,-0.92387956f}, {0.35836786f,-0.93358046f}, {0.33380681f,-0.94264150f}, |
||||
{0.30901697f,-0.95105654f}, {0.28401533f,-0.95881975f}, {0.25881907f,-0.96592581f}, |
||||
{0.23344530f,-0.97236991f}, {0.20791166f,-0.97814763f}, {0.18223552f,-0.98325491f}, |
||||
{0.15643437f,-0.98768836f}, {0.13052613f,-0.99144489f}, {0.10452842f,-0.99452192f}, |
||||
{0.078459084f,-0.99691731f}, {0.052335974f,-0.99862951f}, {0.026176875f,-0.99965733f}, |
||||
{1.0000000f,-0.0000000f}, {0.99862951f,-0.052335959f}, {0.99452192f,-0.10452846f}, |
||||
{0.98768836f,-0.15643448f}, {0.97814763f,-0.20791170f}, {0.96592581f,-0.25881904f}, |
||||
{0.95105648f,-0.30901700f}, {0.93358040f,-0.35836795f}, {0.91354543f,-0.40673664f}, |
||||
{0.89100653f,-0.45399052f}, {0.86602545f,-0.50000000f}, {0.83867055f,-0.54463905f}, |
||||
{0.80901700f,-0.58778524f}, {0.77714598f,-0.62932038f}, {0.74314475f,-0.66913062f}, |
||||
{0.70710677f,-0.70710683f}, {0.66913056f,-0.74314487f}, {0.62932038f,-0.77714598f}, |
||||
{0.58778524f,-0.80901700f}, {0.54463899f,-0.83867055f}, {0.49999997f,-0.86602545f}, |
||||
{0.45399052f,-0.89100653f}, {0.40673661f,-0.91354549f}, {0.35836786f,-0.93358046f}, |
||||
{0.30901697f,-0.95105654f}, {0.25881907f,-0.96592581f}, {0.20791166f,-0.97814763f}, |
||||
{0.15643437f,-0.98768836f}, {0.10452842f,-0.99452192f}, {0.052335974f,-0.99862951f}, |
||||
{-4.3711388e-08f,-1.0000000f}, {-0.052336060f,-0.99862951f}, {-0.10452851f,-0.99452192f}, |
||||
{-0.15643445f,-0.98768836f}, {-0.20791174f,-0.97814757f}, {-0.25881916f,-0.96592581f}, |
||||
{-0.30901703f,-0.95105648f}, {-0.35836795f,-0.93358040f}, {-0.40673670f,-0.91354543f}, |
||||
{-0.45399061f,-0.89100647f}, {-0.50000006f,-0.86602533f}, {-0.54463905f,-0.83867055f}, |
||||
{-0.58778518f,-0.80901700f}, {-0.62932050f,-0.77714586f}, {-0.66913068f,-0.74314475f}, |
||||
{-0.70710677f,-0.70710677f}, {-0.74314493f,-0.66913044f}, {-0.77714604f,-0.62932026f}, |
||||
{-0.80901700f,-0.58778518f}, {-0.83867055f,-0.54463899f}, {-0.86602539f,-0.50000006f}, |
||||
{-0.89100659f,-0.45399037f}, {-0.91354549f,-0.40673658f}, {-0.93358040f,-0.35836792f}, |
||||
{-0.95105654f,-0.30901679f}, {-0.96592587f,-0.25881892f}, {-0.97814763f,-0.20791161f}, |
||||
{-0.98768836f,-0.15643445f}, {-0.99452192f,-0.10452849f}, {-0.99862957f,-0.052335810f}, |
||||
{1.0000000f,-0.0000000f}, {0.99691731f,-0.078459099f}, {0.98768836f,-0.15643448f}, |
||||
{0.97236991f,-0.23344538f}, {0.95105648f,-0.30901700f}, {0.92387956f,-0.38268346f}, |
||||
{0.89100653f,-0.45399052f}, {0.85264015f,-0.52249855f}, {0.80901700f,-0.58778524f}, |
||||
{0.76040596f,-0.64944810f}, {0.70710677f,-0.70710683f}, {0.64944804f,-0.76040596f}, |
||||
{0.58778524f,-0.80901700f}, {0.52249849f,-0.85264015f}, {0.45399052f,-0.89100653f}, |
||||
{0.38268343f,-0.92387956f}, {0.30901697f,-0.95105654f}, {0.23344530f,-0.97236991f}, |
||||
{0.15643437f,-0.98768836f}, {0.078459084f,-0.99691731f}, {-4.3711388e-08f,-1.0000000f}, |
||||
{-0.078459173f,-0.99691731f}, {-0.15643445f,-0.98768836f}, {-0.23344538f,-0.97236991f}, |
||||
{-0.30901703f,-0.95105648f}, {-0.38268352f,-0.92387950f}, {-0.45399061f,-0.89100647f}, |
||||
{-0.52249867f,-0.85264009f}, {-0.58778518f,-0.80901700f}, {-0.64944804f,-0.76040596f}, |
||||
{-0.70710677f,-0.70710677f}, {-0.76040596f,-0.64944804f}, {-0.80901700f,-0.58778518f}, |
||||
{-0.85264021f,-0.52249849f}, {-0.89100659f,-0.45399037f}, {-0.92387956f,-0.38268328f}, |
||||
{-0.95105654f,-0.30901679f}, {-0.97236991f,-0.23344538f}, {-0.98768836f,-0.15643445f}, |
||||
{-0.99691737f,-0.078459039f}, {-1.0000000f,8.7422777e-08f}, {-0.99691731f,0.078459218f}, |
||||
{-0.98768830f,0.15643461f}, {-0.97236985f,0.23344554f}, {-0.95105654f,0.30901697f}, |
||||
{-0.92387956f,0.38268346f}, {-0.89100653f,0.45399055f}, {-0.85264015f,0.52249861f}, |
||||
{-0.80901694f,0.58778536f}, {-0.76040590f,0.64944816f}, {-0.70710665f,0.70710689f}, |
||||
{-0.64944792f,0.76040608f}, {-0.58778507f,0.80901712f}, {-0.52249837f,0.85264033f}, |
||||
{-0.45399022f,0.89100665f}, {-0.38268313f,0.92387968f}, {-0.30901709f,0.95105648f}, |
||||
{-0.23344545f,0.97236991f}, {-0.15643452f,0.98768830f}, {-0.078459114f,0.99691731f}, |
||||
}; |
||||
static const ne10_fft_cpx_float32_t ne10_twiddles_120[120] = { |
||||
{1.0000000f,0.0000000f}, {1.0000000f,-0.0000000f}, {1.0000000f,-0.0000000f}, |
||||
{1.0000000f,-0.0000000f}, {0.91354543f,-0.40673664f}, {0.66913056f,-0.74314487f}, |
||||
{1.0000000f,-0.0000000f}, {0.66913056f,-0.74314487f}, {-0.10452851f,-0.99452192f}, |
||||
{1.0000000f,-0.0000000f}, {0.30901697f,-0.95105654f}, {-0.80901700f,-0.58778518f}, |
||||
{1.0000000f,-0.0000000f}, {-0.10452851f,-0.99452192f}, {-0.97814757f,0.20791179f}, |
||||
{1.0000000f,-0.0000000f}, {0.97814763f,-0.20791170f}, {0.91354543f,-0.40673664f}, |
||||
{0.80901700f,-0.58778524f}, {0.66913056f,-0.74314487f}, {0.49999997f,-0.86602545f}, |
||||
{0.30901697f,-0.95105654f}, {0.10452842f,-0.99452192f}, {-0.10452851f,-0.99452192f}, |
||||
{-0.30901703f,-0.95105648f}, {-0.50000006f,-0.86602533f}, {-0.66913068f,-0.74314475f}, |
||||
{-0.80901700f,-0.58778518f}, {-0.91354549f,-0.40673658f}, {-0.97814763f,-0.20791161f}, |
||||
{1.0000000f,-0.0000000f}, {0.99862951f,-0.052335959f}, {0.99452192f,-0.10452846f}, |
||||
{0.98768836f,-0.15643448f}, {0.97814763f,-0.20791170f}, {0.96592581f,-0.25881904f}, |
||||
{0.95105648f,-0.30901700f}, {0.93358040f,-0.35836795f}, {0.91354543f,-0.40673664f}, |
||||
{0.89100653f,-0.45399052f}, {0.86602545f,-0.50000000f}, {0.83867055f,-0.54463905f}, |
||||
{0.80901700f,-0.58778524f}, {0.77714598f,-0.62932038f}, {0.74314475f,-0.66913062f}, |
||||
{0.70710677f,-0.70710683f}, {0.66913056f,-0.74314487f}, {0.62932038f,-0.77714598f}, |
||||
{0.58778524f,-0.80901700f}, {0.54463899f,-0.83867055f}, {0.49999997f,-0.86602545f}, |
||||
{0.45399052f,-0.89100653f}, {0.40673661f,-0.91354549f}, {0.35836786f,-0.93358046f}, |
||||
{0.30901697f,-0.95105654f}, {0.25881907f,-0.96592581f}, {0.20791166f,-0.97814763f}, |
||||
{0.15643437f,-0.98768836f}, {0.10452842f,-0.99452192f}, {0.052335974f,-0.99862951f}, |
||||
{1.0000000f,-0.0000000f}, {0.99452192f,-0.10452846f}, {0.97814763f,-0.20791170f}, |
||||
{0.95105648f,-0.30901700f}, {0.91354543f,-0.40673664f}, {0.86602545f,-0.50000000f}, |
||||
{0.80901700f,-0.58778524f}, {0.74314475f,-0.66913062f}, {0.66913056f,-0.74314487f}, |
||||
{0.58778524f,-0.80901700f}, {0.49999997f,-0.86602545f}, {0.40673661f,-0.91354549f}, |
||||
{0.30901697f,-0.95105654f}, {0.20791166f,-0.97814763f}, {0.10452842f,-0.99452192f}, |
||||
{-4.3711388e-08f,-1.0000000f}, {-0.10452851f,-0.99452192f}, {-0.20791174f,-0.97814757f}, |
||||
{-0.30901703f,-0.95105648f}, {-0.40673670f,-0.91354543f}, {-0.50000006f,-0.86602533f}, |
||||
{-0.58778518f,-0.80901700f}, {-0.66913068f,-0.74314475f}, {-0.74314493f,-0.66913044f}, |
||||
{-0.80901700f,-0.58778518f}, {-0.86602539f,-0.50000006f}, {-0.91354549f,-0.40673658f}, |
||||
{-0.95105654f,-0.30901679f}, {-0.97814763f,-0.20791161f}, {-0.99452192f,-0.10452849f}, |
||||
{1.0000000f,-0.0000000f}, {0.98768836f,-0.15643448f}, {0.95105648f,-0.30901700f}, |
||||
{0.89100653f,-0.45399052f}, {0.80901700f,-0.58778524f}, {0.70710677f,-0.70710683f}, |
||||
{0.58778524f,-0.80901700f}, {0.45399052f,-0.89100653f}, {0.30901697f,-0.95105654f}, |
||||
{0.15643437f,-0.98768836f}, {-4.3711388e-08f,-1.0000000f}, {-0.15643445f,-0.98768836f}, |
||||
{-0.30901703f,-0.95105648f}, {-0.45399061f,-0.89100647f}, {-0.58778518f,-0.80901700f}, |
||||
{-0.70710677f,-0.70710677f}, {-0.80901700f,-0.58778518f}, {-0.89100659f,-0.45399037f}, |
||||
{-0.95105654f,-0.30901679f}, {-0.98768836f,-0.15643445f}, {-1.0000000f,8.7422777e-08f}, |
||||
{-0.98768830f,0.15643461f}, {-0.95105654f,0.30901697f}, {-0.89100653f,0.45399055f}, |
||||
{-0.80901694f,0.58778536f}, {-0.70710665f,0.70710689f}, {-0.58778507f,0.80901712f}, |
||||
{-0.45399022f,0.89100665f}, {-0.30901709f,0.95105648f}, {-0.15643452f,0.98768830f}, |
||||
}; |
||||
static const ne10_fft_cpx_float32_t ne10_twiddles_60[60] = { |
||||
{1.0000000f,0.0000000f}, {1.0000000f,-0.0000000f}, {1.0000000f,-0.0000000f}, |
||||
{1.0000000f,-0.0000000f}, {0.91354543f,-0.40673664f}, {0.66913056f,-0.74314487f}, |
||||
{1.0000000f,-0.0000000f}, {0.66913056f,-0.74314487f}, {-0.10452851f,-0.99452192f}, |
||||
{1.0000000f,-0.0000000f}, {0.30901697f,-0.95105654f}, {-0.80901700f,-0.58778518f}, |
||||
{1.0000000f,-0.0000000f}, {-0.10452851f,-0.99452192f}, {-0.97814757f,0.20791179f}, |
||||
{1.0000000f,-0.0000000f}, {0.99452192f,-0.10452846f}, {0.97814763f,-0.20791170f}, |
||||
{0.95105648f,-0.30901700f}, {0.91354543f,-0.40673664f}, {0.86602545f,-0.50000000f}, |
||||
{0.80901700f,-0.58778524f}, {0.74314475f,-0.66913062f}, {0.66913056f,-0.74314487f}, |
||||
{0.58778524f,-0.80901700f}, {0.49999997f,-0.86602545f}, {0.40673661f,-0.91354549f}, |
||||
{0.30901697f,-0.95105654f}, {0.20791166f,-0.97814763f}, {0.10452842f,-0.99452192f}, |
||||
{1.0000000f,-0.0000000f}, {0.97814763f,-0.20791170f}, {0.91354543f,-0.40673664f}, |
||||
{0.80901700f,-0.58778524f}, {0.66913056f,-0.74314487f}, {0.49999997f,-0.86602545f}, |
||||
{0.30901697f,-0.95105654f}, {0.10452842f,-0.99452192f}, {-0.10452851f,-0.99452192f}, |
||||
{-0.30901703f,-0.95105648f}, {-0.50000006f,-0.86602533f}, {-0.66913068f,-0.74314475f}, |
||||
{-0.80901700f,-0.58778518f}, {-0.91354549f,-0.40673658f}, {-0.97814763f,-0.20791161f}, |
||||
{1.0000000f,-0.0000000f}, {0.95105648f,-0.30901700f}, {0.80901700f,-0.58778524f}, |
||||
{0.58778524f,-0.80901700f}, {0.30901697f,-0.95105654f}, {-4.3711388e-08f,-1.0000000f}, |
||||
{-0.30901703f,-0.95105648f}, {-0.58778518f,-0.80901700f}, {-0.80901700f,-0.58778518f}, |
||||
{-0.95105654f,-0.30901679f}, {-1.0000000f,8.7422777e-08f}, {-0.95105654f,0.30901697f}, |
||||
{-0.80901694f,0.58778536f}, {-0.58778507f,0.80901712f}, {-0.30901709f,0.95105648f}, |
||||
}; |
||||
static const ne10_fft_state_float32_t ne10_fft_state_float32_t_480 = { |
||||
120, |
||||
(ne10_int32_t *)ne10_factors_480, |
||||
(ne10_fft_cpx_float32_t *)ne10_twiddles_480, |
||||
NULL, |
||||
(ne10_fft_cpx_float32_t *)&ne10_twiddles_480[120], |
||||
/* is_forward_scaled = true */ |
||||
(ne10_int32_t) 1, |
||||
/* is_backward_scaled = false */ |
||||
(ne10_int32_t) 0, |
||||
}; |
||||
static const arch_fft_state cfg_arch_480 = { |
||||
1, |
||||
(void *)&ne10_fft_state_float32_t_480, |
||||
}; |
||||
|
||||
static const ne10_fft_state_float32_t ne10_fft_state_float32_t_240 = { |
||||
60, |
||||
(ne10_int32_t *)ne10_factors_240, |
||||
(ne10_fft_cpx_float32_t *)ne10_twiddles_240, |
||||
NULL, |
||||
(ne10_fft_cpx_float32_t *)&ne10_twiddles_240[60], |
||||
/* is_forward_scaled = true */ |
||||
(ne10_int32_t) 1, |
||||
/* is_backward_scaled = false */ |
||||
(ne10_int32_t) 0, |
||||
}; |
||||
static const arch_fft_state cfg_arch_240 = { |
||||
1, |
||||
(void *)&ne10_fft_state_float32_t_240, |
||||
}; |
||||
|
||||
static const ne10_fft_state_float32_t ne10_fft_state_float32_t_120 = { |
||||
30, |
||||
(ne10_int32_t *)ne10_factors_120, |
||||
(ne10_fft_cpx_float32_t *)ne10_twiddles_120, |
||||
NULL, |
||||
(ne10_fft_cpx_float32_t *)&ne10_twiddles_120[30], |
||||
/* is_forward_scaled = true */ |
||||
(ne10_int32_t) 1, |
||||
/* is_backward_scaled = false */ |
||||
(ne10_int32_t) 0, |
||||
}; |
||||
static const arch_fft_state cfg_arch_120 = { |
||||
1, |
||||
(void *)&ne10_fft_state_float32_t_120, |
||||
}; |
||||
|
||||
static const ne10_fft_state_float32_t ne10_fft_state_float32_t_60 = { |
||||
15, |
||||
(ne10_int32_t *)ne10_factors_60, |
||||
(ne10_fft_cpx_float32_t *)ne10_twiddles_60, |
||||
NULL, |
||||
(ne10_fft_cpx_float32_t *)&ne10_twiddles_60[15], |
||||
/* is_forward_scaled = true */ |
||||
(ne10_int32_t) 1, |
||||
/* is_backward_scaled = false */ |
||||
(ne10_int32_t) 0, |
||||
}; |
||||
static const arch_fft_state cfg_arch_60 = { |
||||
1, |
||||
(void *)&ne10_fft_state_float32_t_60, |
||||
}; |
||||
|
||||
#endif /* end NE10_FFT_PARAMS48000_960 */ |
||||
@ -0,0 +1,867 @@
|
||||
/* 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" |
||||
#include "pitch.h" |
||||
#include "SigProc_FIX.h" |
||||
|
||||
#if defined(FIXED_POINT) |
||||
void norm_scaleup(celt_norm *X, int N, int shift) { |
||||
int i; |
||||
celt_assert(shift >= 0); |
||||
if (shift <= 0) return; |
||||
for (i=0;i<N;i++) X[i] = SHL32(X[i], shift); |
||||
} |
||||
|
||||
void norm_scaledown(celt_norm *X, int N, int shift) { |
||||
int i; |
||||
celt_assert(shift >= 0); |
||||
if (shift <= 0) return; |
||||
for (i=0;i<N;i++) X[i] = PSHR32(X[i], shift); |
||||
} |
||||
|
||||
opus_val32 celt_inner_prod_norm(const celt_norm *x, const celt_norm *y, int len, int arch) { |
||||
int i; |
||||
opus_val32 sum = 0; |
||||
(void)arch; |
||||
for (i=0;i<len;i++) sum += x[i]*y[i]; |
||||
return sum; |
||||
} |
||||
opus_val32 celt_inner_prod_norm_shift(const celt_norm *x, const celt_norm *y, int len, int arch) { |
||||
int i; |
||||
opus_val64 sum = 0; |
||||
(void)arch; |
||||
for (i=0;i<len;i++) sum += x[i]*(opus_val64)y[i]; |
||||
return sum>>2*(NORM_SHIFT-14); |
||||
} |
||||
#endif |
||||
|
||||
#ifndef OVERRIDE_vq_exp_rotation1 |
||||
static void exp_rotation1(celt_norm *X, int len, int stride, opus_val16 c, opus_val16 s) |
||||
{ |
||||
int i; |
||||
opus_val16 ms; |
||||
celt_norm *Xptr; |
||||
Xptr = X; |
||||
ms = NEG16(s); |
||||
norm_scaledown(X, len, NORM_SHIFT-14); |
||||
for (i=0;i<len-stride;i++) |
||||
{ |
||||
celt_norm x1, x2; |
||||
x1 = Xptr[0]; |
||||
x2 = Xptr[stride]; |
||||
Xptr[stride] = EXTRACT16(PSHR32(MAC16_16(MULT16_16(c, x2), s, x1), 15)); |
||||
*Xptr++ = EXTRACT16(PSHR32(MAC16_16(MULT16_16(c, x1), ms, 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(PSHR32(MAC16_16(MULT16_16(c, x2), s, x1), 15)); |
||||
*Xptr-- = EXTRACT16(PSHR32(MAC16_16(MULT16_16(c, x1), ms, x2), 15)); |
||||
} |
||||
norm_scaleup(X, len, NORM_SHIFT-14); |
||||
} |
||||
#endif /* OVERRIDE_vq_exp_rotation1 */ |
||||
|
||||
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 = celt_udiv(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); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** Normalizes the decoded integer pvq codeword to unit norm. */ |
||||
static void normalise_residual(int * OPUS_RESTRICT iy, celt_norm * OPUS_RESTRICT X, |
||||
int N, opus_val32 Ryy, opus_val32 gain, int shift) |
||||
{ |
||||
int i; |
||||
#ifdef FIXED_POINT |
||||
int k; |
||||
#endif |
||||
opus_val32 t; |
||||
opus_val32 g; |
||||
|
||||
#ifdef FIXED_POINT |
||||
k = celt_ilog2(Ryy)>>1; |
||||
#endif |
||||
t = VSHR32(Ryy, 2*(k-7)-15); |
||||
g = MULT32_32_Q31(celt_rsqrt_norm32(t),gain); |
||||
i=0; |
||||
(void)shift; |
||||
#if defined(FIXED_POINT) && defined(ENABLE_QEXT) |
||||
if (shift>0) { |
||||
int tot_shift = NORM_SHIFT+1-k-shift; |
||||
if (tot_shift >= 0) { |
||||
do X[i] = MULT32_32_Q31(g, SHL32(iy[i], tot_shift)); |
||||
while (++i < N); |
||||
} else { |
||||
do X[i] = MULT32_32_Q31(g, PSHR32(iy[i], -tot_shift)); |
||||
while (++i < N); |
||||
} |
||||
} else |
||||
#endif |
||||
do X[i] = VSHR32(MULT16_32_Q15(iy[i], g), k+15-NORM_SHIFT); |
||||
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 = celt_udiv(N, B); |
||||
collapse_mask = 0; |
||||
i=0; do { |
||||
int j; |
||||
unsigned tmp=0; |
||||
j=0; do { |
||||
tmp |= iy[i*N0+j]; |
||||
} while (++j<N0); |
||||
collapse_mask |= (tmp!=0)<<i; |
||||
} while (++i<B); |
||||
return collapse_mask; |
||||
} |
||||
|
||||
opus_val16 op_pvq_search_c(celt_norm *X, int *iy, int K, int N, int arch) |
||||
{ |
||||
VARDECL(celt_norm, y); |
||||
VARDECL(int, signx); |
||||
int i, j; |
||||
int pulsesLeft; |
||||
opus_val32 sum; |
||||
opus_val32 xy; |
||||
opus_val16 yy; |
||||
SAVE_STACK; |
||||
|
||||
(void)arch; |
||||
ALLOC(y, N, celt_norm); |
||||
ALLOC(signx, N, int); |
||||
#ifdef FIXED_POINT |
||||
{ |
||||
int shift = (celt_ilog2(1+celt_inner_prod_norm_shift(X, X, N, arch))+1)/2; |
||||
shift = IMAX(0, shift+(NORM_SHIFT-14)-14); |
||||
norm_scaledown(X, N, shift); |
||||
} |
||||
#endif |
||||
/* Get rid of the sign */ |
||||
sum = 0; |
||||
j=0; do { |
||||
signx[j] = X[j]<0; |
||||
/* OPT: Make sure the compiler doesn't use a branch on ABS16(). */ |
||||
X[j] = ABS16(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); |
||||
} |
||||
#ifdef FIXED_POINT |
||||
rcp = EXTRACT16(MULT16_32_Q16(K, celt_rcp(sum))); |
||||
#else |
||||
/* Using K+e with e < 1 guarantees we cannot get more than K pulses. */ |
||||
rcp = EXTRACT16(MULT16_32_Q16(K+0.8f, celt_rcp(sum))); |
||||
#endif |
||||
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_sig_assert(pulsesLeft>=0); |
||||
|
||||
/* 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_sig_assert(pulsesLeft<=N+3); |
||||
#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; |
||||
} |
||||
|
||||
for (i=0;i<pulsesLeft;i++) |
||||
{ |
||||
opus_val16 Rxy, Ryy; |
||||
int best_id; |
||||
opus_val32 best_num; |
||||
opus_val16 best_den; |
||||
#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 = ADD16(yy, 1); |
||||
|
||||
/* Calculations for position 0 are out of the loop, in part to reduce
|
||||
mispredicted branches (since the if condition is usually false) |
||||
in the loop. */ |
||||
/* Temporary sums of the new pulse(s) */ |
||||
Rxy = EXTRACT16(SHR32(ADD32(xy, EXTEND32(X[0])),rshift)); |
||||
/* We're multiplying y[j] by two so we don't have to do it here */ |
||||
Ryy = ADD16(yy, y[0]); |
||||
|
||||
/* 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); |
||||
best_den = Ryy; |
||||
best_num = Rxy; |
||||
j=1; |
||||
do { |
||||
/* 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: It's not clear whether a cmov is faster than a branch here
|
||||
since the condition is more often false than true and using |
||||
a cmov introduces data dependencies across iterations. The optimal |
||||
choice may be architecture-dependent. */ |
||||
if (opus_unlikely(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; |
||||
iy[best_id]++; |
||||
} |
||||
|
||||
/* Put the original sign back */ |
||||
j=0; |
||||
do { |
||||
/*iy[j] = signx[j] ? -iy[j] : iy[j];*/ |
||||
/* OPT: The is more likely to be compiled without a branch than the code above
|
||||
but has the same performance otherwise. */ |
||||
iy[j] = (iy[j]^-signx[j]) + signx[j]; |
||||
} while (++j<N); |
||||
RESTORE_STACK; |
||||
return yy; |
||||
} |
||||
|
||||
#ifdef ENABLE_QEXT |
||||
#include "macros.h" |
||||
|
||||
static opus_val32 op_pvq_search_N2(const celt_norm *X, int *iy, int *up_iy, int K, int up, int *refine, int shift) { |
||||
opus_val32 sum; |
||||
opus_val32 rcp_sum; |
||||
int offset; |
||||
sum = ABS32(X[0]) + ABS32(X[1]); |
||||
if (sum < EPSILON) { |
||||
iy[0] = K; |
||||
up_iy[0] = up*K; |
||||
iy[1]=up_iy[1]=0; |
||||
*refine=0; |
||||
#ifdef FIXED_POINT |
||||
return (opus_val64)K*K*up*up>>2*shift; |
||||
#else |
||||
(void)shift; |
||||
return K*(float)K*up*up; |
||||
#endif |
||||
} |
||||
#ifdef FIXED_POINT |
||||
int sum_shift; |
||||
opus_val32 X0; |
||||
sum_shift = 30-celt_ilog2(sum); |
||||
rcp_sum = celt_rcp_norm32(SHL32(sum, sum_shift)); |
||||
X0 = MULT32_32_Q31(SHL32(X[0], sum_shift), rcp_sum); |
||||
iy[0] = PSHR32(MULT32_32_Q31(SHL32(K, 8), X0), 7); |
||||
up_iy[0] = PSHR32(MULT32_32_Q31(SHL32(up*K, 8), X0), 7); |
||||
#else |
||||
rcp_sum = 1.f/sum; |
||||
iy[0] = (int)floor(.5f+K*X[0]*rcp_sum); |
||||
up_iy[0] = (int)floor(.5f+up*K*X[0]*rcp_sum); |
||||
#endif |
||||
up_iy[0] = IMAX(up*iy[0] - (up-1)/2, IMIN(up*iy[0] + (up-1)/2, up_iy[0])); |
||||
offset = up_iy[0] - up*iy[0]; |
||||
iy[1] = K-abs(iy[0]); |
||||
up_iy[1] = up*K-abs(up_iy[0]); |
||||
if (X[1] < 0) { |
||||
iy[1] = -iy[1]; |
||||
up_iy[1] = -up_iy[1]; |
||||
offset = -offset; |
||||
} |
||||
*refine = offset; |
||||
#ifdef FIXED_POINT |
||||
return (up_iy[0]*(opus_val64)up_iy[0] + up_iy[1]*(opus_val64)up_iy[1] + (1<<2*shift>>1))>>2*shift; |
||||
#else |
||||
return up_iy[0]*(opus_val64)up_iy[0] + up_iy[1]*(opus_val64)up_iy[1]; |
||||
#endif |
||||
} |
||||
|
||||
static int op_pvq_refine(const opus_val32 *Xn, int *iy, int *iy0, int K, int up, int margin, int N) { |
||||
int i; |
||||
int dir; |
||||
VARDECL(opus_val32, rounding); |
||||
int iysum = 0; |
||||
SAVE_STACK; |
||||
ALLOC(rounding, N, opus_val32); |
||||
for (i=0;i<N;i++) { |
||||
opus_val32 tmp; |
||||
tmp = MULT32_32_Q31(SHL32(K, 8), Xn[i]); |
||||
#ifdef FIXED_POINT |
||||
iy[i] = (tmp+64) >> 7; |
||||
#else |
||||
iy[i] = (int)floor(.5+tmp); |
||||
#endif |
||||
rounding[i] = tmp - SHL32(iy[i], 7); |
||||
} |
||||
if (iy != iy0) { |
||||
for (i=0;i<N;i++) iy[i] = IMIN(up*iy0[i]+up-1, IMAX(up*iy0[i]-up+1, iy[i])); |
||||
} |
||||
for (i=0;i<N;i++) iysum += iy[i]; |
||||
if (abs(iysum - K) > 32) { |
||||
RESTORE_STACK; |
||||
return 1; |
||||
} |
||||
dir = iysum < K ? 1 : -1; |
||||
while (iysum != K) { |
||||
opus_val32 roundval=-1000000*dir; |
||||
int roundpos=0; |
||||
for (i=0;i<N;i++) { |
||||
if ((rounding[i]-roundval)*dir > 0 && abs(iy[i]-up*iy0[i]) < (margin-1) && !(dir==-1 && iy[i] == 0)) { |
||||
roundval = rounding[i]; |
||||
roundpos = i; |
||||
} |
||||
} |
||||
iy[roundpos] += dir; |
||||
rounding[roundpos] -= SHL32(dir, 15); |
||||
iysum+=dir; |
||||
} |
||||
RESTORE_STACK; |
||||
return 0; |
||||
} |
||||
|
||||
static opus_val32 op_pvq_search_extra(const celt_norm *X, int *iy, int *up_iy, int K, int up, int *refine, int N, int shift) { |
||||
opus_val32 rcp_sum; |
||||
opus_val32 sum=0; |
||||
int i; |
||||
int failed=0; |
||||
opus_val64 yy=0; |
||||
VARDECL(opus_val32, Xn); |
||||
SAVE_STACK; |
||||
for (i=0;i<N;i++) sum += ABS32(X[i]); |
||||
ALLOC(Xn, N, opus_val32); |
||||
if (sum < EPSILON) |
||||
failed = 1; |
||||
else { |
||||
#ifdef FIXED_POINT |
||||
int sum_shift = 30-celt_ilog2(sum); |
||||
rcp_sum = celt_rcp_norm32(SHL32(sum, sum_shift)); |
||||
for (i=0;i<N;i++) { |
||||
Xn[i] = MULT32_32_Q31(SHL32(ABS32(X[i]), sum_shift), rcp_sum); |
||||
} |
||||
#else |
||||
rcp_sum = celt_rcp(sum); |
||||
for (i=0;i<N;i++) { |
||||
Xn[i] = ABS32(X[i])*rcp_sum; |
||||
} |
||||
#endif |
||||
} |
||||
failed = failed || op_pvq_refine(Xn, iy, iy, K, 1, K+1, N); |
||||
failed = failed || op_pvq_refine(Xn, up_iy, iy, up*K, up, up, N); |
||||
if (failed) { |
||||
iy[0] = K; |
||||
for (i=1;i<N;i++) iy[i] = 0; |
||||
up_iy[0] = up*K; |
||||
for (i=1;i<N;i++) up_iy[i] = 0; |
||||
} |
||||
for (i=0;i<N;i++) { |
||||
yy += up_iy[i]*(opus_val64)up_iy[i]; |
||||
if (X[i] < 0) { |
||||
iy[i] = -iy[i]; |
||||
up_iy[i] = -up_iy[i]; |
||||
} |
||||
refine[i] = up_iy[i]-up*iy[i]; |
||||
} |
||||
RESTORE_STACK; |
||||
#ifdef FIXED_POINT |
||||
return (yy + (1<<2*shift>>1))>>2*shift; |
||||
#else |
||||
(void)shift; |
||||
return yy; |
||||
#endif |
||||
} |
||||
#endif |
||||
|
||||
#ifdef ENABLE_QEXT |
||||
/* Take advantage of the fact that "large" refine values are much less likely
|
||||
than smaller ones. */ |
||||
static void ec_enc_refine(ec_enc *enc, opus_int32 refine, opus_int32 up, int extra_bits, int use_entropy) { |
||||
int large; |
||||
large = abs(refine)>up/2; |
||||
ec_enc_bit_logp(enc, large, use_entropy ? 3 : 1); |
||||
if (large) { |
||||
ec_enc_bits(enc, refine < 0, 1); |
||||
ec_enc_bits(enc, abs(refine)-up/2-1, extra_bits-1); |
||||
} else { |
||||
ec_enc_bits(enc, refine+up/2, extra_bits); |
||||
} |
||||
} |
||||
|
||||
static int ec_dec_refine(ec_enc *dec, opus_int32 up, int extra_bits, int use_entropy) { |
||||
int large, refine; |
||||
large = ec_dec_bit_logp(dec, use_entropy ? 3 : 1); |
||||
if (large) { |
||||
int sign = ec_dec_bits(dec, 1); |
||||
refine = ec_dec_bits(dec, extra_bits-1) + up/2+1; |
||||
if (sign) refine = -refine; |
||||
} else { |
||||
refine = (opus_int32)ec_dec_bits(dec, extra_bits)-up/2; |
||||
} |
||||
return refine; |
||||
} |
||||
#endif |
||||
|
||||
unsigned alg_quant(celt_norm *X, int N, int K, int spread, int B, ec_enc *enc, |
||||
opus_val32 gain, int resynth |
||||
ARG_QEXT(ec_enc *ext_enc) ARG_QEXT(int extra_bits), int arch) |
||||
{ |
||||
VARDECL(int, iy); |
||||
opus_val32 yy; |
||||
unsigned collapse_mask; |
||||
#ifdef ENABLE_QEXT |
||||
int yy_shift = 0; |
||||
#endif |
||||
SAVE_STACK; |
||||
|
||||
celt_assert2(K>0, "alg_quant() needs at least one pulse"); |
||||
celt_assert2(N>1, "alg_quant() needs at least two dimensions"); |
||||
|
||||
/* Covers vectorization by up to 4. */ |
||||
ALLOC(iy, N+3, int); |
||||
|
||||
exp_rotation(X, N, 1, B, K, spread); |
||||
|
||||
#ifdef ENABLE_QEXT |
||||
if (N==2 && extra_bits >= 2) { |
||||
int refine; |
||||
int up_iy[2]; |
||||
int up; |
||||
yy_shift = IMAX(0, extra_bits-7); |
||||
up = (1<<extra_bits)-1; |
||||
yy = op_pvq_search_N2(X, iy, up_iy, K, up, &refine, yy_shift); |
||||
collapse_mask = extract_collapse_mask(up_iy, N, B); |
||||
encode_pulses(iy, N, K, enc); |
||||
ec_enc_uint(ext_enc, refine+(up-1)/2, up); |
||||
if (resynth) |
||||
normalise_residual(up_iy, X, N, yy, gain, yy_shift); |
||||
} else if (extra_bits >= 2) { |
||||
int i; |
||||
VARDECL(int, up_iy); |
||||
VARDECL(int, refine); |
||||
int up, use_entropy; |
||||
ALLOC(up_iy, N, int); |
||||
ALLOC(refine, N, int); |
||||
yy_shift = IMAX(0, extra_bits-7); |
||||
up = (1<<extra_bits)-1; |
||||
yy = op_pvq_search_extra(X, iy, up_iy, K, up, refine, N, yy_shift); |
||||
collapse_mask = extract_collapse_mask(up_iy, N, B); |
||||
encode_pulses(iy, N, K, enc); |
||||
use_entropy = (ext_enc->storage*8 - ec_tell(ext_enc)) > (unsigned)(N-1)*(extra_bits+3)+1; |
||||
for (i=0;i<N-1;i++) ec_enc_refine(ext_enc, refine[i], up, extra_bits, use_entropy); |
||||
if (iy[N-1]==0) ec_enc_bits(ext_enc, up_iy[N-1]<0, 1); |
||||
if (resynth) |
||||
normalise_residual(up_iy, X, N, yy, gain, yy_shift); |
||||
} else |
||||
#endif |
||||
{ |
||||
yy = op_pvq_search(X, iy, K, N, arch); |
||||
collapse_mask = extract_collapse_mask(iy, N, B); |
||||
encode_pulses(iy, N, K, enc); |
||||
if (resynth) |
||||
normalise_residual(iy, X, N, yy, gain, 0); |
||||
} |
||||
|
||||
if (resynth) |
||||
exp_rotation(X, N, -1, B, K, spread); |
||||
|
||||
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_val32 gain |
||||
ARG_QEXT(ec_enc *ext_dec) ARG_QEXT(int extra_bits)) |
||||
{ |
||||
opus_val32 Ryy; |
||||
unsigned collapse_mask; |
||||
VARDECL(int, iy); |
||||
int yy_shift=0; |
||||
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); |
||||
Ryy = decode_pulses(iy, N, K, dec); |
||||
#ifdef ENABLE_QEXT |
||||
if (N==2 && extra_bits >= 2) { |
||||
int up; |
||||
int refine; |
||||
yy_shift = IMAX(0, extra_bits-7); |
||||
up = (1<<extra_bits)-1; |
||||
refine = (opus_int32)ec_dec_uint(ext_dec, up) - (up-1)/2; |
||||
iy[0] *= up; |
||||
iy[1] *= up; |
||||
if (iy[1] == 0) { |
||||
iy[1] = (iy[0] > 0) ? -refine : refine; |
||||
iy[0] += (refine*(opus_int64)iy[0] > 0) ? -refine : refine; |
||||
} else if (iy[1] > 0) { |
||||
iy[0] += refine; |
||||
iy[1] -= refine*(iy[0]>0?1:-1); |
||||
} else { |
||||
iy[0] -= refine; |
||||
iy[1] -= refine*(iy[0]>0?1:-1); |
||||
} |
||||
#ifdef FIXED_POINT |
||||
Ryy = (iy[0]*(opus_val64)iy[0] + iy[1]*(opus_val64)iy[1] + (1<<2*yy_shift>>1)) >> 2*yy_shift; |
||||
#else |
||||
Ryy = iy[0]*(opus_val64)iy[0] + iy[1]*(opus_val64)iy[1]; |
||||
#endif |
||||
} else if (extra_bits >= 2) { |
||||
int i; |
||||
opus_val64 yy64; |
||||
VARDECL(int, refine); |
||||
int up, use_entropy; |
||||
int sign=0; |
||||
ALLOC(refine, N, int); |
||||
yy_shift = IMAX(0, extra_bits-7); |
||||
up = (1<<extra_bits)-1; |
||||
use_entropy = (ext_dec->storage*8 - ec_tell(ext_dec)) > (unsigned)(N-1)*(extra_bits+3)+1; |
||||
for (i=0;i<N-1;i++) refine[i] = ec_dec_refine(ext_dec, up, extra_bits, use_entropy); |
||||
if (iy[N-1]==0) sign = ec_dec_bits(ext_dec, 1); |
||||
else sign = iy[N-1] < 0; |
||||
for (i=0;i<N-1;i++) { |
||||
iy[i] = iy[i]*up + refine[i]; |
||||
} |
||||
iy[N-1] = up*K; |
||||
for (i=0;i<N-1;i++) iy[N-1] -= abs(iy[i]); |
||||
if (sign) iy[N-1] = -iy[N-1]; |
||||
yy64 = 0; |
||||
for (i=0;i<N;i++) yy64 += iy[i]*(opus_val64)iy[i]; |
||||
#ifdef FIXED_POINT |
||||
Ryy = (yy64 + (1<<2*yy_shift>>1)) >> 2*yy_shift; |
||||
#else |
||||
Ryy = yy64; |
||||
#endif |
||||
} |
||||
#endif |
||||
normalise_residual(iy, X, N, Ryy, gain, yy_shift); |
||||
exp_rotation(X, N, -1, B, K, spread); |
||||
collapse_mask = extract_collapse_mask(iy, N, B); |
||||
RESTORE_STACK; |
||||
return collapse_mask; |
||||
} |
||||
|
||||
#ifndef OVERRIDE_renormalise_vector |
||||
void renormalise_vector(celt_norm *X, int N, opus_val32 gain, int arch) |
||||
{ |
||||
int i; |
||||
#ifdef FIXED_POINT |
||||
int k; |
||||
#endif |
||||
opus_val32 E; |
||||
opus_val16 g; |
||||
opus_val32 t; |
||||
celt_norm *xptr; |
||||
norm_scaledown(X, N, NORM_SHIFT-14); |
||||
E = EPSILON + celt_inner_prod_norm(X, X, N, arch); |
||||
#ifdef FIXED_POINT |
||||
k = celt_ilog2(E)>>1; |
||||
#endif |
||||
t = VSHR32(E, 2*(k-7)); |
||||
g = MULT32_32_Q31(celt_rsqrt_norm(t),gain); |
||||
|
||||
xptr = X; |
||||
for (i=0;i<N;i++) |
||||
{ |
||||
*xptr = EXTRACT16(PSHR32(MULT16_16(g, *xptr), k+15-14)); |
||||
xptr++; |
||||
} |
||||
norm_scaleup(X, N, NORM_SHIFT-14); |
||||
/*return celt_sqrt(E);*/ |
||||
} |
||||
#endif /* OVERRIDE_renormalise_vector */ |
||||
|
||||
opus_int32 stereo_itheta(const celt_norm *X, const celt_norm *Y, int stereo, int N, int arch) |
||||
{ |
||||
int i; |
||||
int itheta; |
||||
opus_val32 mid, side; |
||||
opus_val32 Emid, Eside; |
||||
|
||||
Emid = Eside = 0; |
||||
if (stereo) |
||||
{ |
||||
for (i=0;i<N;i++) |
||||
{ |
||||
celt_norm m, s; |
||||
m = PSHR32(ADD32(X[i], Y[i]), NORM_SHIFT-13); |
||||
s = PSHR32(SUB32(X[i], Y[i]), NORM_SHIFT-13); |
||||
Emid = MAC16_16(Emid, m, m); |
||||
Eside = MAC16_16(Eside, s, s); |
||||
} |
||||
} else { |
||||
Emid += celt_inner_prod_norm_shift(X, X, N, arch); |
||||
Eside += celt_inner_prod_norm_shift(Y, Y, N, arch); |
||||
} |
||||
mid = celt_sqrt32(Emid); |
||||
side = celt_sqrt32(Eside); |
||||
#if defined(FIXED_POINT) |
||||
itheta = celt_atan2p_norm(side, mid); |
||||
#else |
||||
itheta = (int)floor(.5f+65536.f*16384*celt_atan2p_norm(side,mid)); |
||||
#endif |
||||
|
||||
return itheta; |
||||
} |
||||
|
||||
#ifdef ENABLE_QEXT |
||||
|
||||
static void cubic_synthesis(celt_norm *X, int *iy, int N, int K, int face, int sign, opus_val32 gain) { |
||||
int i; |
||||
opus_val32 sum=0; |
||||
opus_val32 mag; |
||||
#ifdef FIXED_POINT |
||||
int sum_shift; |
||||
int shift = IMAX(celt_ilog2(K) + celt_ilog2(N)/2 - 13, 0); |
||||
#endif |
||||
for (i=0;i<N;i++) { |
||||
X[i] = (1+2*iy[i])-K; |
||||
} |
||||
X[face] = sign ? -K : K; |
||||
for (i=0;i<N;i++) { |
||||
sum += PSHR32(MULT16_16(X[i],X[i]), 2*shift); |
||||
} |
||||
#ifdef FIXED_POINT |
||||
sum_shift = (29-celt_ilog2(sum))>>1; |
||||
mag = celt_rsqrt_norm32(SHL32(sum, 2*sum_shift+1)); |
||||
for (i=0;i<N;i++) { |
||||
X[i] = VSHR32(MULT16_32_Q15(X[i],MULT32_32_Q31(mag,gain)), shift-sum_shift+29-NORM_SHIFT); |
||||
} |
||||
#else |
||||
mag = 1.f/sqrt(sum); |
||||
for (i=0;i<N;i++) { |
||||
X[i] *= mag*gain; |
||||
} |
||||
#endif |
||||
} |
||||
|
||||
unsigned cubic_quant(celt_norm *X, int N, int res, int B, ec_enc *enc, opus_val32 gain, int resynth) { |
||||
int i; |
||||
int face=0; |
||||
int K; |
||||
VARDECL(int, iy); |
||||
celt_norm faceval=-1; |
||||
opus_val32 norm; |
||||
int sign; |
||||
SAVE_STACK; |
||||
ALLOC(iy, N, int); |
||||
K = 1<<res; |
||||
/* Using odd K on transients to avoid adding pre-echo. */ |
||||
if (B!=1) K=IMAX(1, K-1); |
||||
if (K==1) { |
||||
if (resynth) OPUS_CLEAR(X, N); |
||||
RESTORE_STACK; |
||||
return 0; |
||||
} |
||||
for (i=0;i<N;i++) { |
||||
if (ABS32(X[i]) > faceval) { |
||||
faceval = ABS32(X[i]); |
||||
face = i; |
||||
} |
||||
} |
||||
sign = X[face]<0; |
||||
ec_enc_uint(enc, face, N); |
||||
ec_enc_bits(enc, sign, 1); |
||||
#ifdef FIXED_POINT |
||||
if (faceval != 0) { |
||||
int face_shift = 30-celt_ilog2(faceval); |
||||
norm = celt_rcp_norm32(SHL32(faceval, face_shift)); |
||||
norm = MULT16_32_Q15(K, norm); |
||||
for (i=0;i<N;i++) { |
||||
/* By computing X[i]+faceval inside the shift, the result is guaranteed non-negative. */ |
||||
iy[i] = IMIN(K-1, (MULT32_32_Q31(SHL32(X[i]+faceval, face_shift-1), norm)) >> 15); |
||||
} |
||||
} else { |
||||
OPUS_CLEAR(iy, N); |
||||
} |
||||
#else |
||||
norm = .5f*K/(faceval+EPSILON); |
||||
for (i=0;i<N;i++) { |
||||
iy[i] = IMIN(K-1, (int)floor((X[i]+faceval)*norm)); |
||||
} |
||||
#endif |
||||
for (i=0;i<N;i++) { |
||||
if (i != face) ec_enc_bits(enc, iy[i], res); |
||||
} |
||||
if (resynth) { |
||||
cubic_synthesis(X, iy, N, K, face, sign, gain); |
||||
} |
||||
RESTORE_STACK; |
||||
return (1<<B)-1; |
||||
} |
||||
|
||||
unsigned cubic_unquant(celt_norm *X, int N, int res, int B, ec_dec *dec, opus_val32 gain) { |
||||
int i; |
||||
int face; |
||||
int sign; |
||||
int K; |
||||
VARDECL(int, iy); |
||||
SAVE_STACK; |
||||
ALLOC(iy, N, int); |
||||
K = 1<<res; |
||||
/* Using odd K on transients to avoid adding pre-echo. */ |
||||
if (B!=1) K=IMAX(1, K-1); |
||||
if (K==1) { |
||||
OPUS_CLEAR(X, N); |
||||
RESTORE_STACK; |
||||
return 0; |
||||
} |
||||
face = ec_dec_uint(dec, N); |
||||
sign = ec_dec_bits(dec, 1); |
||||
for (i=0;i<N;i++) { |
||||
if (i != face) iy[i] = ec_dec_bits(dec, res); |
||||
} |
||||
iy[face]=0; |
||||
cubic_synthesis(X, iy, N, K, face, sign, gain); |
||||
RESTORE_STACK; |
||||
return (1<<B)-1; |
||||
} |
||||
#endif |
||||
@ -0,0 +1,98 @@
|
||||
/* 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" |
||||
|
||||
#if (defined(OPUS_X86_MAY_HAVE_SSE2) && !defined(FIXED_POINT)) |
||||
#include "x86/vq_sse.h" |
||||
#endif |
||||
|
||||
#if defined(FIXED_POINT) |
||||
opus_val32 celt_inner_prod_norm(const celt_norm *x, const celt_norm *y, int len, int arch); |
||||
opus_val32 celt_inner_prod_norm_shift(const celt_norm *x, const celt_norm *y, int len, int arch); |
||||
|
||||
void norm_scaleup(celt_norm *X, int N, int shift); |
||||
void norm_scaledown(celt_norm *X, int N, int shift); |
||||
|
||||
#else |
||||
#define celt_inner_prod_norm celt_inner_prod |
||||
#define celt_inner_prod_norm_shift celt_inner_prod |
||||
#define norm_scaleup(X, N, shift) |
||||
#define norm_scaledown(X, N, shift) |
||||
#endif |
||||
|
||||
void exp_rotation(celt_norm *X, int len, int dir, int stride, int K, int spread); |
||||
|
||||
opus_val16 op_pvq_search_c(celt_norm *X, int *iy, int K, int N, int arch); |
||||
|
||||
#if !defined(OVERRIDE_OP_PVQ_SEARCH) |
||||
#define op_pvq_search(x, iy, K, N, arch) \ |
||||
(op_pvq_search_c(x, iy, K, N, arch)) |
||||
#endif |
||||
|
||||
/** 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 N Number of samples to encode |
||||
* @param K Number of pulses to use |
||||
* @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, |
||||
opus_val32 gain, int resynth |
||||
ARG_QEXT(ec_enc *ext_enc) ARG_QEXT(int extra_bits), int arch); |
||||
|
||||
/** Algebraic pulse decoder
|
||||
* @param X Decoded normalised spectrum (returned) |
||||
* @param N Number of samples to decode |
||||
* @param K Number of pulses to use |
||||
* @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_val32 gain |
||||
ARG_QEXT(ec_enc *ext_dec) ARG_QEXT(int extra_bits)); |
||||
|
||||
void renormalise_vector(celt_norm *X, int N, opus_val32 gain, int arch); |
||||
|
||||
opus_int32 stereo_itheta(const celt_norm *X, const celt_norm *Y, int stereo, int N, int arch); |
||||
|
||||
unsigned cubic_quant(celt_norm *X, int N, int K, int B, ec_enc *enc, opus_val32 gain, int resynth); |
||||
unsigned cubic_unquant(celt_norm *X, int N, int K, int B, ec_dec *dec, opus_val32 gain); |
||||
|
||||
#endif /* VQ_H */ |
||||
@ -0,0 +1,67 @@
|
||||
/* Copyright (c) 2014, Cisco Systems, INC
|
||||
Written by XiangMingZhu WeiZhou MinPeng YanWang |
||||
|
||||
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_LPC_SSE_H |
||||
#define CELT_LPC_SSE_H |
||||
|
||||
#ifdef HAVE_CONFIG_H |
||||
#include "config.h" |
||||
#endif |
||||
|
||||
#if defined(OPUS_X86_MAY_HAVE_SSE4_1) && defined(FIXED_POINT) |
||||
|
||||
void celt_fir_sse4_1( |
||||
const opus_val16 *x, |
||||
const opus_val16 *num, |
||||
opus_val16 *y, |
||||
int N, |
||||
int ord, |
||||
int arch); |
||||
|
||||
#if defined(OPUS_X86_PRESUME_SSE4_1) |
||||
#define OVERRIDE_CELT_FIR |
||||
#define celt_fir(x, num, y, N, ord, arch) \ |
||||
((void)arch, celt_fir_sse4_1(x, num, y, N, ord, arch)) |
||||
|
||||
#elif defined(OPUS_HAVE_RTCD) |
||||
|
||||
extern void (*const CELT_FIR_IMPL[OPUS_ARCHMASK + 1])( |
||||
const opus_val16 *x, |
||||
const opus_val16 *num, |
||||
opus_val16 *y, |
||||
int N, |
||||
int ord, |
||||
int arch); |
||||
|
||||
#define OVERRIDE_CELT_FIR |
||||
# define celt_fir(x, num, y, N, ord, arch) \ |
||||
((*CELT_FIR_IMPL[(arch) & OPUS_ARCHMASK])(x, num, y, N, ord, arch)) |
||||
|
||||
#endif |
||||
#endif |
||||
|
||||
#endif |
||||
@ -0,0 +1,96 @@
|
||||
/* Copyright (c) 2014, Cisco Systems, INC
|
||||
Written by XiangMingZhu WeiZhou MinPeng YanWang |
||||
|
||||
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 <xmmintrin.h> |
||||
#include <emmintrin.h> |
||||
#include <smmintrin.h> |
||||
#include "celt_lpc.h" |
||||
#include "stack_alloc.h" |
||||
#include "mathops.h" |
||||
#include "pitch.h" |
||||
#include "x86cpu.h" |
||||
|
||||
#if defined(FIXED_POINT) |
||||
|
||||
void celt_fir_sse4_1(const opus_val16 *x, |
||||
const opus_val16 *num, |
||||
opus_val16 *y, |
||||
int N, |
||||
int ord, |
||||
int arch) |
||||
{ |
||||
int i,j; |
||||
VARDECL(opus_val16, rnum); |
||||
|
||||
__m128i vecNoA; |
||||
opus_int32 noA ; |
||||
SAVE_STACK; |
||||
|
||||
ALLOC(rnum, ord, opus_val16); |
||||
for(i=0;i<ord;i++) |
||||
rnum[i] = num[ord-i-1]; |
||||
noA = EXTEND32(1) << SIG_SHIFT >> 1; |
||||
vecNoA = _mm_set_epi32(noA, noA, noA, noA); |
||||
|
||||
for (i=0;i<N-3;i+=4) |
||||
{ |
||||
opus_val32 sums[4] = {0}; |
||||
__m128i vecSum, vecX; |
||||
#if defined(OPUS_CHECK_ASM) |
||||
{ |
||||
opus_val32 sums_c[4] = {0}; |
||||
xcorr_kernel_c(rnum, x+i-ord, sums_c, ord); |
||||
#endif |
||||
xcorr_kernel(rnum, x+i-ord, sums, ord, arch); |
||||
#if defined(OPUS_CHECK_ASM) |
||||
celt_assert(memcmp(sums, sums_c, sizeof(sums)) == 0); |
||||
} |
||||
#endif |
||||
vecSum = _mm_loadu_si128((__m128i *)(void*)sums); |
||||
vecSum = _mm_add_epi32(vecSum, vecNoA); |
||||
vecSum = _mm_srai_epi32(vecSum, SIG_SHIFT); |
||||
vecX = OP_CVTEPI16_EPI32_M64(x + i); |
||||
vecSum = _mm_add_epi32(vecSum, vecX); |
||||
vecSum = _mm_packs_epi32(vecSum, vecSum); |
||||
_mm_storel_epi64((__m128i *)(void *)(y + i), vecSum); |
||||
} |
||||
for (;i<N;i++) |
||||
{ |
||||
opus_val32 sum = 0; |
||||
for (j=0;j<ord;j++) |
||||
sum = MAC16_16(sum, rnum[j], x[i+j-ord]); |
||||
y[i] = SATURATE16(ADD32(EXTEND32(x[i]), PSHR32(sum, SIG_SHIFT))); |
||||
} |
||||
|
||||
RESTORE_STACK; |
||||
} |
||||
|
||||
#endif |
||||
@ -0,0 +1,101 @@
|
||||
/* Copyright (c) 2023 Amazon */ |
||||
/*
|
||||
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 <immintrin.h> |
||||
#include "x86cpu.h" |
||||
#include "pitch.h" |
||||
|
||||
#if defined(OPUS_X86_MAY_HAVE_AVX2) && !defined(FIXED_POINT) |
||||
|
||||
/* Like the "regular" xcorr_kernel(), but computes 8 results at a time. */ |
||||
static void xcorr_kernel_avx(const float *x, const float *y, float sum[8], int len) |
||||
{ |
||||
__m256 xsum0, xsum1, xsum2, xsum3, xsum4, xsum5, xsum6, xsum7; |
||||
xsum7 = xsum6 = xsum5 = xsum4 = xsum3 = xsum2 = xsum1 = xsum0 = _mm256_setzero_ps(); |
||||
int i; |
||||
__m256 x0; |
||||
/* Compute 8 inner products using partial sums. */ |
||||
for (i=0;i<len-7;i+=8) |
||||
{ |
||||
x0 = _mm256_loadu_ps(x+i); |
||||
xsum0 = _mm256_fmadd_ps(x0, _mm256_loadu_ps(y+i ), xsum0); |
||||
xsum1 = _mm256_fmadd_ps(x0, _mm256_loadu_ps(y+i+1), xsum1); |
||||
xsum2 = _mm256_fmadd_ps(x0, _mm256_loadu_ps(y+i+2), xsum2); |
||||
xsum3 = _mm256_fmadd_ps(x0, _mm256_loadu_ps(y+i+3), xsum3); |
||||
xsum4 = _mm256_fmadd_ps(x0, _mm256_loadu_ps(y+i+4), xsum4); |
||||
xsum5 = _mm256_fmadd_ps(x0, _mm256_loadu_ps(y+i+5), xsum5); |
||||
xsum6 = _mm256_fmadd_ps(x0, _mm256_loadu_ps(y+i+6), xsum6); |
||||
xsum7 = _mm256_fmadd_ps(x0, _mm256_loadu_ps(y+i+7), xsum7); |
||||
} |
||||
if (i != len) { |
||||
static const int mask[15] = {-1, -1, -1, -1, -1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0}; |
||||
__m256i m; |
||||
m = _mm256_loadu_si256((__m256i*)(void*)(mask + 7+i-len)); |
||||
x0 = _mm256_maskload_ps(x+i, m); |
||||
xsum0 = _mm256_fmadd_ps(x0, _mm256_maskload_ps(y+i , m), xsum0); |
||||
xsum1 = _mm256_fmadd_ps(x0, _mm256_maskload_ps(y+i+1, m), xsum1); |
||||
xsum2 = _mm256_fmadd_ps(x0, _mm256_maskload_ps(y+i+2, m), xsum2); |
||||
xsum3 = _mm256_fmadd_ps(x0, _mm256_maskload_ps(y+i+3, m), xsum3); |
||||
xsum4 = _mm256_fmadd_ps(x0, _mm256_maskload_ps(y+i+4, m), xsum4); |
||||
xsum5 = _mm256_fmadd_ps(x0, _mm256_maskload_ps(y+i+5, m), xsum5); |
||||
xsum6 = _mm256_fmadd_ps(x0, _mm256_maskload_ps(y+i+6, m), xsum6); |
||||
xsum7 = _mm256_fmadd_ps(x0, _mm256_maskload_ps(y+i+7, m), xsum7); |
||||
} |
||||
/* 8 horizontal adds. */ |
||||
/* Compute [0 4] [1 5] [2 6] [3 7] */ |
||||
xsum0 = _mm256_add_ps(_mm256_permute2f128_ps(xsum0, xsum4, 2<<4), _mm256_permute2f128_ps(xsum0, xsum4, 1 | (3<<4))); |
||||
xsum1 = _mm256_add_ps(_mm256_permute2f128_ps(xsum1, xsum5, 2<<4), _mm256_permute2f128_ps(xsum1, xsum5, 1 | (3<<4))); |
||||
xsum2 = _mm256_add_ps(_mm256_permute2f128_ps(xsum2, xsum6, 2<<4), _mm256_permute2f128_ps(xsum2, xsum6, 1 | (3<<4))); |
||||
xsum3 = _mm256_add_ps(_mm256_permute2f128_ps(xsum3, xsum7, 2<<4), _mm256_permute2f128_ps(xsum3, xsum7, 1 | (3<<4))); |
||||
/* Compute [0 1 4 5] [2 3 6 7] */ |
||||
xsum0 = _mm256_hadd_ps(xsum0, xsum1); |
||||
xsum1 = _mm256_hadd_ps(xsum2, xsum3); |
||||
/* Compute [0 1 2 3 4 5 6 7] */ |
||||
xsum0 = _mm256_hadd_ps(xsum0, xsum1); |
||||
_mm256_storeu_ps(sum, xsum0); |
||||
} |
||||
|
||||
void celt_pitch_xcorr_avx2(const float *_x, const float *_y, float *xcorr, int len, int max_pitch, int arch) |
||||
{ |
||||
int i; |
||||
celt_assert(max_pitch>0); |
||||
(void)arch; |
||||
for (i=0;i<max_pitch-7;i+=8) |
||||
{ |
||||
xcorr_kernel_avx(_x, _y+i, &xcorr[i], len); |
||||
} |
||||
for (;i<max_pitch;i++) |
||||
{ |
||||
xcorr[i] = celt_inner_prod(_x, _y+i, len, arch); |
||||
} |
||||
} |
||||
|
||||
#endif |
||||
@ -0,0 +1,185 @@
|
||||
/* Copyright (c) 2014, Cisco Systems, INC
|
||||
Written by XiangMingZhu WeiZhou MinPeng YanWang |
||||
|
||||
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 "macros.h" |
||||
#include "celt_lpc.h" |
||||
#include "stack_alloc.h" |
||||
#include "mathops.h" |
||||
#include "pitch.h" |
||||
|
||||
#if defined(OPUS_X86_MAY_HAVE_SSE) && !defined(FIXED_POINT) |
||||
|
||||
#include <xmmintrin.h> |
||||
#include "arch.h" |
||||
|
||||
void xcorr_kernel_sse(const opus_val16 *x, const opus_val16 *y, opus_val32 sum[4], int len) |
||||
{ |
||||
int j; |
||||
__m128 xsum1, xsum2; |
||||
xsum1 = _mm_loadu_ps(sum); |
||||
xsum2 = _mm_setzero_ps(); |
||||
|
||||
for (j = 0; j < len-3; j += 4) |
||||
{ |
||||
__m128 x0 = _mm_loadu_ps(x+j); |
||||
__m128 yj = _mm_loadu_ps(y+j); |
||||
__m128 y3 = _mm_loadu_ps(y+j+3); |
||||
|
||||
xsum1 = _mm_add_ps(xsum1,_mm_mul_ps(_mm_shuffle_ps(x0,x0,0x00),yj)); |
||||
xsum2 = _mm_add_ps(xsum2,_mm_mul_ps(_mm_shuffle_ps(x0,x0,0x55), |
||||
_mm_shuffle_ps(yj,y3,0x49))); |
||||
xsum1 = _mm_add_ps(xsum1,_mm_mul_ps(_mm_shuffle_ps(x0,x0,0xaa), |
||||
_mm_shuffle_ps(yj,y3,0x9e))); |
||||
xsum2 = _mm_add_ps(xsum2,_mm_mul_ps(_mm_shuffle_ps(x0,x0,0xff),y3)); |
||||
} |
||||
if (j < len) |
||||
{ |
||||
xsum1 = _mm_add_ps(xsum1,_mm_mul_ps(_mm_load1_ps(x+j),_mm_loadu_ps(y+j))); |
||||
if (++j < len) |
||||
{ |
||||
xsum2 = _mm_add_ps(xsum2,_mm_mul_ps(_mm_load1_ps(x+j),_mm_loadu_ps(y+j))); |
||||
if (++j < len) |
||||
{ |
||||
xsum1 = _mm_add_ps(xsum1,_mm_mul_ps(_mm_load1_ps(x+j),_mm_loadu_ps(y+j))); |
||||
} |
||||
} |
||||
} |
||||
_mm_storeu_ps(sum,_mm_add_ps(xsum1,xsum2)); |
||||
} |
||||
|
||||
|
||||
void dual_inner_prod_sse(const opus_val16 *x, const opus_val16 *y01, const opus_val16 *y02, |
||||
int N, opus_val32 *xy1, opus_val32 *xy2) |
||||
{ |
||||
int i; |
||||
__m128 xsum1, xsum2; |
||||
xsum1 = _mm_setzero_ps(); |
||||
xsum2 = _mm_setzero_ps(); |
||||
for (i=0;i<N-3;i+=4) |
||||
{ |
||||
__m128 xi = _mm_loadu_ps(x+i); |
||||
__m128 y1i = _mm_loadu_ps(y01+i); |
||||
__m128 y2i = _mm_loadu_ps(y02+i); |
||||
xsum1 = _mm_add_ps(xsum1,_mm_mul_ps(xi, y1i)); |
||||
xsum2 = _mm_add_ps(xsum2,_mm_mul_ps(xi, y2i)); |
||||
} |
||||
/* Horizontal sum */ |
||||
xsum1 = _mm_add_ps(xsum1, _mm_movehl_ps(xsum1, xsum1)); |
||||
xsum1 = _mm_add_ss(xsum1, _mm_shuffle_ps(xsum1, xsum1, 0x55)); |
||||
_mm_store_ss(xy1, xsum1); |
||||
xsum2 = _mm_add_ps(xsum2, _mm_movehl_ps(xsum2, xsum2)); |
||||
xsum2 = _mm_add_ss(xsum2, _mm_shuffle_ps(xsum2, xsum2, 0x55)); |
||||
_mm_store_ss(xy2, xsum2); |
||||
for (;i<N;i++) |
||||
{ |
||||
*xy1 = MAC16_16(*xy1, x[i], y01[i]); |
||||
*xy2 = MAC16_16(*xy2, x[i], y02[i]); |
||||
} |
||||
} |
||||
|
||||
opus_val32 celt_inner_prod_sse(const opus_val16 *x, const opus_val16 *y, |
||||
int N) |
||||
{ |
||||
int i; |
||||
float xy; |
||||
__m128 sum; |
||||
sum = _mm_setzero_ps(); |
||||
/* FIXME: We should probably go 8-way and use 2 sums. */ |
||||
for (i=0;i<N-3;i+=4) |
||||
{ |
||||
__m128 xi = _mm_loadu_ps(x+i); |
||||
__m128 yi = _mm_loadu_ps(y+i); |
||||
sum = _mm_add_ps(sum,_mm_mul_ps(xi, yi)); |
||||
} |
||||
/* Horizontal sum */ |
||||
sum = _mm_add_ps(sum, _mm_movehl_ps(sum, sum)); |
||||
sum = _mm_add_ss(sum, _mm_shuffle_ps(sum, sum, 0x55)); |
||||
_mm_store_ss(&xy, sum); |
||||
for (;i<N;i++) |
||||
{ |
||||
xy = MAC16_16(xy, x[i], y[i]); |
||||
} |
||||
return xy; |
||||
} |
||||
|
||||
void comb_filter_const_sse(opus_val32 *y, opus_val32 *x, int T, int N, |
||||
opus_val16 g10, opus_val16 g11, opus_val16 g12) |
||||
{ |
||||
int i; |
||||
__m128 x0v; |
||||
__m128 g10v, g11v, g12v; |
||||
g10v = _mm_load1_ps(&g10); |
||||
g11v = _mm_load1_ps(&g11); |
||||
g12v = _mm_load1_ps(&g12); |
||||
x0v = _mm_loadu_ps(&x[-T-2]); |
||||
for (i=0;i<N-3;i+=4) |
||||
{ |
||||
__m128 yi, yi2, x1v, x2v, x3v, x4v; |
||||
const opus_val32 *xp = &x[i-T-2]; |
||||
yi = _mm_loadu_ps(x+i); |
||||
x4v = _mm_loadu_ps(xp+4); |
||||
#if 0 |
||||
/* Slower version with all loads */ |
||||
x1v = _mm_loadu_ps(xp+1); |
||||
x2v = _mm_loadu_ps(xp+2); |
||||
x3v = _mm_loadu_ps(xp+3); |
||||
#else |
||||
x2v = _mm_shuffle_ps(x0v, x4v, 0x4e); |
||||
x1v = _mm_shuffle_ps(x0v, x2v, 0x99); |
||||
x3v = _mm_shuffle_ps(x2v, x4v, 0x99); |
||||
#endif |
||||
|
||||
yi = _mm_add_ps(yi, _mm_mul_ps(g10v,x2v)); |
||||
#if 0 /* Set to 1 to make it bit-exact with the non-SSE version */
|
||||
yi = _mm_add_ps(yi, _mm_mul_ps(g11v,_mm_add_ps(x3v,x1v))); |
||||
yi = _mm_add_ps(yi, _mm_mul_ps(g12v,_mm_add_ps(x4v,x0v))); |
||||
#else |
||||
/* Use partial sums */ |
||||
yi2 = _mm_add_ps(_mm_mul_ps(g11v,_mm_add_ps(x3v,x1v)), |
||||
_mm_mul_ps(g12v,_mm_add_ps(x4v,x0v))); |
||||
yi = _mm_add_ps(yi, yi2); |
||||
#endif |
||||
x0v=x4v; |
||||
_mm_storeu_ps(y+i, yi); |
||||
} |
||||
#ifdef CUSTOM_MODES |
||||
for (;i<N;i++) |
||||
{ |
||||
y[i] = x[i] |
||||
+ MULT16_32_Q15(g10,x[i-T]) |
||||
+ MULT16_32_Q15(g11,ADD32(x[i-T+1],x[i-T-1])) |
||||
+ MULT16_32_Q15(g12,ADD32(x[i-T+2],x[i-T-2])); |
||||
} |
||||
#endif |
||||
} |
||||
|
||||
|
||||
#endif |
||||
@ -0,0 +1,216 @@
|
||||
/* Copyright (c) 2013 Jean-Marc Valin and John Ridges
|
||||
Copyright (c) 2014, Cisco Systems, INC MingXiang WeiZhou MinPeng YanWang*/ |
||||
/**
|
||||
@file pitch_sse.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_SSE_H |
||||
#define PITCH_SSE_H |
||||
|
||||
#if defined(HAVE_CONFIG_H) |
||||
#include "config.h" |
||||
#endif |
||||
|
||||
#if defined(OPUS_X86_MAY_HAVE_SSE4_1) && defined(FIXED_POINT) |
||||
void xcorr_kernel_sse4_1( |
||||
const opus_int16 *x, |
||||
const opus_int16 *y, |
||||
opus_val32 sum[4], |
||||
int len); |
||||
#endif |
||||
|
||||
#if defined(OPUS_X86_MAY_HAVE_SSE) && !defined(FIXED_POINT) |
||||
void xcorr_kernel_sse( |
||||
const opus_val16 *x, |
||||
const opus_val16 *y, |
||||
opus_val32 sum[4], |
||||
int len); |
||||
#endif |
||||
|
||||
#if defined(OPUS_X86_PRESUME_SSE4_1) && defined(FIXED_POINT) |
||||
#define OVERRIDE_XCORR_KERNEL |
||||
#define xcorr_kernel(x, y, sum, len, arch) \ |
||||
((void)arch, xcorr_kernel_sse4_1(x, y, sum, len)) |
||||
|
||||
#elif defined(OPUS_X86_PRESUME_SSE) && !defined(FIXED_POINT) |
||||
#define OVERRIDE_XCORR_KERNEL |
||||
#define xcorr_kernel(x, y, sum, len, arch) \ |
||||
((void)arch, xcorr_kernel_sse(x, y, sum, len)) |
||||
|
||||
#elif defined(OPUS_HAVE_RTCD) && ((defined(OPUS_X86_MAY_HAVE_SSE4_1) && defined(FIXED_POINT)) || (defined(OPUS_X86_MAY_HAVE_SSE) && !defined(FIXED_POINT))) |
||||
|
||||
extern void (*const XCORR_KERNEL_IMPL[OPUS_ARCHMASK + 1])( |
||||
const opus_val16 *x, |
||||
const opus_val16 *y, |
||||
opus_val32 sum[4], |
||||
int len); |
||||
|
||||
#define OVERRIDE_XCORR_KERNEL |
||||
#define xcorr_kernel(x, y, sum, len, arch) \ |
||||
((*XCORR_KERNEL_IMPL[(arch) & OPUS_ARCHMASK])(x, y, sum, len)) |
||||
|
||||
#endif |
||||
|
||||
#if defined(OPUS_X86_MAY_HAVE_SSE4_1) && defined(FIXED_POINT) |
||||
opus_val32 celt_inner_prod_sse4_1( |
||||
const opus_int16 *x, |
||||
const opus_int16 *y, |
||||
int N); |
||||
#endif |
||||
|
||||
#if defined(OPUS_X86_MAY_HAVE_SSE2) && defined(FIXED_POINT) |
||||
opus_val32 celt_inner_prod_sse2( |
||||
const opus_int16 *x, |
||||
const opus_int16 *y, |
||||
int N); |
||||
#endif |
||||
|
||||
#if defined(OPUS_X86_MAY_HAVE_SSE) && !defined(FIXED_POINT) |
||||
opus_val32 celt_inner_prod_sse( |
||||
const opus_val16 *x, |
||||
const opus_val16 *y, |
||||
int N); |
||||
#endif |
||||
|
||||
|
||||
#if defined(OPUS_X86_PRESUME_SSE4_1) && defined(FIXED_POINT) |
||||
#define OVERRIDE_CELT_INNER_PROD |
||||
#define celt_inner_prod(x, y, N, arch) \ |
||||
((void)arch, celt_inner_prod_sse4_1(x, y, N)) |
||||
|
||||
#elif defined(OPUS_X86_PRESUME_SSE2) && defined(FIXED_POINT) && !defined(OPUS_X86_MAY_HAVE_SSE4_1) |
||||
#define OVERRIDE_CELT_INNER_PROD |
||||
#define celt_inner_prod(x, y, N, arch) \ |
||||
((void)arch, celt_inner_prod_sse2(x, y, N)) |
||||
|
||||
#elif defined(OPUS_X86_PRESUME_SSE) && !defined(FIXED_POINT) |
||||
#define OVERRIDE_CELT_INNER_PROD |
||||
#define celt_inner_prod(x, y, N, arch) \ |
||||
((void)arch, celt_inner_prod_sse(x, y, N)) |
||||
|
||||
|
||||
#elif defined(OPUS_HAVE_RTCD) && (((defined(OPUS_X86_MAY_HAVE_SSE4_1) || defined(OPUS_X86_MAY_HAVE_SSE2)) && defined(FIXED_POINT)) || \ |
||||
(defined(OPUS_X86_MAY_HAVE_SSE) && !defined(FIXED_POINT))) |
||||
|
||||
extern opus_val32 (*const CELT_INNER_PROD_IMPL[OPUS_ARCHMASK + 1])( |
||||
const opus_val16 *x, |
||||
const opus_val16 *y, |
||||
int N); |
||||
|
||||
#define OVERRIDE_CELT_INNER_PROD |
||||
#define celt_inner_prod(x, y, N, arch) \ |
||||
((*CELT_INNER_PROD_IMPL[(arch) & OPUS_ARCHMASK])(x, y, N)) |
||||
|
||||
#endif |
||||
|
||||
#if defined(OPUS_X86_MAY_HAVE_SSE) && !defined(FIXED_POINT) |
||||
|
||||
void dual_inner_prod_sse(const opus_val16 *x, |
||||
const opus_val16 *y01, |
||||
const opus_val16 *y02, |
||||
int N, |
||||
opus_val32 *xy1, |
||||
opus_val32 *xy2); |
||||
|
||||
void comb_filter_const_sse(opus_val32 *y, |
||||
opus_val32 *x, |
||||
int T, |
||||
int N, |
||||
opus_val16 g10, |
||||
opus_val16 g11, |
||||
opus_val16 g12); |
||||
|
||||
|
||||
#if defined(OPUS_X86_PRESUME_SSE) |
||||
#define OVERRIDE_DUAL_INNER_PROD |
||||
#define OVERRIDE_COMB_FILTER_CONST |
||||
# define dual_inner_prod(x, y01, y02, N, xy1, xy2, arch) \ |
||||
((void)(arch),dual_inner_prod_sse(x, y01, y02, N, xy1, xy2)) |
||||
|
||||
# define comb_filter_const(y, x, T, N, g10, g11, g12, arch) \ |
||||
((void)(arch),comb_filter_const_sse(y, x, T, N, g10, g11, g12)) |
||||
#elif defined(OPUS_HAVE_RTCD) |
||||
|
||||
#define OVERRIDE_DUAL_INNER_PROD |
||||
#define OVERRIDE_COMB_FILTER_CONST |
||||
extern void (*const DUAL_INNER_PROD_IMPL[OPUS_ARCHMASK + 1])( |
||||
const opus_val16 *x, |
||||
const opus_val16 *y01, |
||||
const opus_val16 *y02, |
||||
int N, |
||||
opus_val32 *xy1, |
||||
opus_val32 *xy2); |
||||
|
||||
#define dual_inner_prod(x, y01, y02, N, xy1, xy2, arch) \ |
||||
((*DUAL_INNER_PROD_IMPL[(arch) & OPUS_ARCHMASK])(x, y01, y02, N, xy1, xy2)) |
||||
|
||||
extern void (*const COMB_FILTER_CONST_IMPL[OPUS_ARCHMASK + 1])( |
||||
opus_val32 *y, |
||||
opus_val32 *x, |
||||
int T, |
||||
int N, |
||||
opus_val16 g10, |
||||
opus_val16 g11, |
||||
opus_val16 g12); |
||||
|
||||
#define comb_filter_const(y, x, T, N, g10, g11, g12, arch) \ |
||||
((*COMB_FILTER_CONST_IMPL[(arch) & OPUS_ARCHMASK])(y, x, T, N, g10, g11, g12)) |
||||
|
||||
#define NON_STATIC_COMB_FILTER_CONST_C |
||||
|
||||
#endif |
||||
|
||||
void celt_pitch_xcorr_avx2(const float *_x, const float *_y, float *xcorr, int len, int max_pitch, int arch); |
||||
|
||||
#if defined(OPUS_X86_PRESUME_AVX2) |
||||
|
||||
#define OVERRIDE_PITCH_XCORR |
||||
# define celt_pitch_xcorr celt_pitch_xcorr_avx2 |
||||
|
||||
#elif defined(OPUS_HAVE_RTCD) && defined(OPUS_X86_MAY_HAVE_AVX2) |
||||
|
||||
#define OVERRIDE_PITCH_XCORR |
||||
extern void (*const PITCH_XCORR_IMPL[OPUS_ARCHMASK + 1])( |
||||
const float *_x, |
||||
const float *_y, |
||||
float *xcorr, |
||||
int len, |
||||
int max_pitch, |
||||
int arch |
||||
); |
||||
|
||||
#define celt_pitch_xcorr(_x, _y, xcorr, len, max_pitch, arch) \ |
||||
((*PITCH_XCORR_IMPL[(arch) & OPUS_ARCHMASK])(_x, _y, xcorr, len, max_pitch, arch)) |
||||
|
||||
|
||||
#endif /* OPUS_X86_PRESUME_AVX2 && !OPUS_HAVE_RTCD */ |
||||
|
||||
#endif /* OPUS_X86_MAY_HAVE_SSE && !FIXED_POINT */ |
||||
|
||||
#endif |
||||
@ -0,0 +1,95 @@
|
||||
/* Copyright (c) 2014, Cisco Systems, INC
|
||||
Written by XiangMingZhu WeiZhou MinPeng YanWang |
||||
|
||||
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 <xmmintrin.h> |
||||
#include <emmintrin.h> |
||||
|
||||
#include "macros.h" |
||||
#include "celt_lpc.h" |
||||
#include "stack_alloc.h" |
||||
#include "mathops.h" |
||||
#include "pitch.h" |
||||
|
||||
#if defined(OPUS_X86_MAY_HAVE_SSE2) && defined(FIXED_POINT) |
||||
opus_val32 celt_inner_prod_sse2(const opus_val16 *x, const opus_val16 *y, |
||||
int N) |
||||
{ |
||||
opus_int i, dataSize16; |
||||
opus_int32 sum; |
||||
|
||||
__m128i inVec1_76543210, inVec1_FEDCBA98, acc1; |
||||
__m128i inVec2_76543210, inVec2_FEDCBA98, acc2; |
||||
|
||||
sum = 0; |
||||
dataSize16 = N & ~15; |
||||
|
||||
acc1 = _mm_setzero_si128(); |
||||
acc2 = _mm_setzero_si128(); |
||||
|
||||
for (i=0;i<dataSize16;i+=16) |
||||
{ |
||||
inVec1_76543210 = _mm_loadu_si128((__m128i *)(void*)(&x[i + 0])); |
||||
inVec2_76543210 = _mm_loadu_si128((__m128i *)(void*)(&y[i + 0])); |
||||
|
||||
inVec1_FEDCBA98 = _mm_loadu_si128((__m128i *)(void*)(&x[i + 8])); |
||||
inVec2_FEDCBA98 = _mm_loadu_si128((__m128i *)(void*)(&y[i + 8])); |
||||
|
||||
inVec1_76543210 = _mm_madd_epi16(inVec1_76543210, inVec2_76543210); |
||||
inVec1_FEDCBA98 = _mm_madd_epi16(inVec1_FEDCBA98, inVec2_FEDCBA98); |
||||
|
||||
acc1 = _mm_add_epi32(acc1, inVec1_76543210); |
||||
acc2 = _mm_add_epi32(acc2, inVec1_FEDCBA98); |
||||
} |
||||
|
||||
acc1 = _mm_add_epi32( acc1, acc2 ); |
||||
|
||||
if (N - i >= 8) |
||||
{ |
||||
inVec1_76543210 = _mm_loadu_si128((__m128i *)(void*)(&x[i + 0])); |
||||
inVec2_76543210 = _mm_loadu_si128((__m128i *)(void*)(&y[i + 0])); |
||||
|
||||
inVec1_76543210 = _mm_madd_epi16(inVec1_76543210, inVec2_76543210); |
||||
|
||||
acc1 = _mm_add_epi32(acc1, inVec1_76543210); |
||||
i += 8; |
||||
} |
||||
|
||||
acc1 = _mm_add_epi32(acc1, _mm_unpackhi_epi64( acc1, acc1)); |
||||
acc1 = _mm_add_epi32(acc1, _mm_shufflelo_epi16( acc1, 0x0E)); |
||||
sum += _mm_cvtsi128_si32(acc1); |
||||
|
||||
for (;i<N;i++) { |
||||
sum = silk_SMLABB(sum, x[i], y[i]); |
||||
} |
||||
|
||||
return sum; |
||||
} |
||||
#endif |
||||
@ -0,0 +1,240 @@
|
||||
/* Copyright (c) 2014, Cisco Systems, INC
|
||||
Written by XiangMingZhu WeiZhou MinPeng YanWang |
||||
|
||||
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 <xmmintrin.h> |
||||
#include <emmintrin.h> |
||||
|
||||
#include "macros.h" |
||||
#include "celt_lpc.h" |
||||
#include "stack_alloc.h" |
||||
#include "mathops.h" |
||||
#include "pitch.h" |
||||
|
||||
#if defined(OPUS_X86_MAY_HAVE_SSE4_1) && defined(FIXED_POINT) |
||||
#include <smmintrin.h> |
||||
#include "x86cpu.h" |
||||
|
||||
opus_val32 celt_inner_prod_sse4_1(const opus_val16 *x, const opus_val16 *y, |
||||
int N) |
||||
{ |
||||
opus_int i, dataSize16; |
||||
opus_int32 sum; |
||||
__m128i inVec1_76543210, inVec1_FEDCBA98, acc1; |
||||
__m128i inVec2_76543210, inVec2_FEDCBA98, acc2; |
||||
__m128i inVec1_3210, inVec2_3210; |
||||
|
||||
sum = 0; |
||||
dataSize16 = N & ~15; |
||||
|
||||
acc1 = _mm_setzero_si128(); |
||||
acc2 = _mm_setzero_si128(); |
||||
|
||||
for (i=0;i<dataSize16;i+=16) { |
||||
inVec1_76543210 = _mm_loadu_si128((__m128i *)(void*)(&x[i + 0])); |
||||
inVec2_76543210 = _mm_loadu_si128((__m128i *)(void*)(&y[i + 0])); |
||||
|
||||
inVec1_FEDCBA98 = _mm_loadu_si128((__m128i *)(void*)(&x[i + 8])); |
||||
inVec2_FEDCBA98 = _mm_loadu_si128((__m128i *)(void*)(&y[i + 8])); |
||||
|
||||
inVec1_76543210 = _mm_madd_epi16(inVec1_76543210, inVec2_76543210); |
||||
inVec1_FEDCBA98 = _mm_madd_epi16(inVec1_FEDCBA98, inVec2_FEDCBA98); |
||||
|
||||
acc1 = _mm_add_epi32(acc1, inVec1_76543210); |
||||
acc2 = _mm_add_epi32(acc2, inVec1_FEDCBA98); |
||||
} |
||||
|
||||
acc1 = _mm_add_epi32(acc1, acc2); |
||||
|
||||
if (N - i >= 8) |
||||
{ |
||||
inVec1_76543210 = _mm_loadu_si128((__m128i *)(void*)(&x[i + 0])); |
||||
inVec2_76543210 = _mm_loadu_si128((__m128i *)(void*)(&y[i + 0])); |
||||
|
||||
inVec1_76543210 = _mm_madd_epi16(inVec1_76543210, inVec2_76543210); |
||||
|
||||
acc1 = _mm_add_epi32(acc1, inVec1_76543210); |
||||
i += 8; |
||||
} |
||||
|
||||
if (N - i >= 4) |
||||
{ |
||||
inVec1_3210 = OP_CVTEPI16_EPI32_M64(&x[i + 0]); |
||||
inVec2_3210 = OP_CVTEPI16_EPI32_M64(&y[i + 0]); |
||||
|
||||
inVec1_3210 = _mm_mullo_epi32(inVec1_3210, inVec2_3210); |
||||
|
||||
acc1 = _mm_add_epi32(acc1, inVec1_3210); |
||||
i += 4; |
||||
} |
||||
|
||||
acc1 = _mm_add_epi32(acc1, _mm_unpackhi_epi64(acc1, acc1)); |
||||
acc1 = _mm_add_epi32(acc1, _mm_shufflelo_epi16(acc1, 0x0E)); |
||||
|
||||
sum += _mm_cvtsi128_si32(acc1); |
||||
|
||||
for (;i<N;i++) |
||||
{ |
||||
sum = silk_SMLABB(sum, x[i], y[i]); |
||||
} |
||||
|
||||
return sum; |
||||
} |
||||
|
||||
void xcorr_kernel_sse4_1(const opus_val16 * x, const opus_val16 * y, opus_val32 sum[ 4 ], int len) |
||||
{ |
||||
int j; |
||||
|
||||
__m128i vecX, vecX0, vecX1, vecX2, vecX3; |
||||
__m128i vecY0, vecY1, vecY2, vecY3; |
||||
__m128i sum0, sum1, sum2, sum3, vecSum; |
||||
__m128i initSum; |
||||
|
||||
#ifdef OPUS_CHECK_ASM |
||||
opus_val32 sum_c[4]; |
||||
for (j=0;j<4;j++) { |
||||
sum_c[j] = sum[j]; |
||||
} |
||||
xcorr_kernel_c(x, y, sum_c, len); |
||||
#endif |
||||
|
||||
celt_assert(len >= 3); |
||||
|
||||
sum0 = _mm_setzero_si128(); |
||||
sum1 = _mm_setzero_si128(); |
||||
sum2 = _mm_setzero_si128(); |
||||
sum3 = _mm_setzero_si128(); |
||||
|
||||
for (j=0;j<(len-7);j+=8) |
||||
{ |
||||
vecX = _mm_loadu_si128((__m128i *)(void*)(&x[j + 0])); |
||||
vecY0 = _mm_loadu_si128((__m128i *)(void*)(&y[j + 0])); |
||||
vecY1 = _mm_loadu_si128((__m128i *)(void*)(&y[j + 1])); |
||||
vecY2 = _mm_loadu_si128((__m128i *)(void*)(&y[j + 2])); |
||||
vecY3 = _mm_loadu_si128((__m128i *)(void*)(&y[j + 3])); |
||||
|
||||
sum0 = _mm_add_epi32(sum0, _mm_madd_epi16(vecX, vecY0)); |
||||
sum1 = _mm_add_epi32(sum1, _mm_madd_epi16(vecX, vecY1)); |
||||
sum2 = _mm_add_epi32(sum2, _mm_madd_epi16(vecX, vecY2)); |
||||
sum3 = _mm_add_epi32(sum3, _mm_madd_epi16(vecX, vecY3)); |
||||
} |
||||
|
||||
sum0 = _mm_add_epi32(sum0, _mm_unpackhi_epi64( sum0, sum0)); |
||||
sum0 = _mm_add_epi32(sum0, _mm_shufflelo_epi16( sum0, 0x0E)); |
||||
|
||||
sum1 = _mm_add_epi32(sum1, _mm_unpackhi_epi64( sum1, sum1)); |
||||
sum1 = _mm_add_epi32(sum1, _mm_shufflelo_epi16( sum1, 0x0E)); |
||||
|
||||
sum2 = _mm_add_epi32(sum2, _mm_unpackhi_epi64( sum2, sum2)); |
||||
sum2 = _mm_add_epi32(sum2, _mm_shufflelo_epi16( sum2, 0x0E)); |
||||
|
||||
sum3 = _mm_add_epi32(sum3, _mm_unpackhi_epi64( sum3, sum3)); |
||||
sum3 = _mm_add_epi32(sum3, _mm_shufflelo_epi16( sum3, 0x0E)); |
||||
|
||||
vecSum = _mm_unpacklo_epi64(_mm_unpacklo_epi32(sum0, sum1), |
||||
_mm_unpacklo_epi32(sum2, sum3)); |
||||
|
||||
for (;j<(len-3);j+=4) |
||||
{ |
||||
vecX = OP_CVTEPI16_EPI32_M64(&x[j + 0]); |
||||
vecX0 = _mm_shuffle_epi32(vecX, 0x00); |
||||
vecX1 = _mm_shuffle_epi32(vecX, 0x55); |
||||
vecX2 = _mm_shuffle_epi32(vecX, 0xaa); |
||||
vecX3 = _mm_shuffle_epi32(vecX, 0xff); |
||||
|
||||
vecY0 = OP_CVTEPI16_EPI32_M64(&y[j + 0]); |
||||
vecY1 = OP_CVTEPI16_EPI32_M64(&y[j + 1]); |
||||
vecY2 = OP_CVTEPI16_EPI32_M64(&y[j + 2]); |
||||
vecY3 = OP_CVTEPI16_EPI32_M64(&y[j + 3]); |
||||
|
||||
sum0 = _mm_mullo_epi32(vecX0, vecY0); |
||||
sum1 = _mm_mullo_epi32(vecX1, vecY1); |
||||
sum2 = _mm_mullo_epi32(vecX2, vecY2); |
||||
sum3 = _mm_mullo_epi32(vecX3, vecY3); |
||||
|
||||
sum0 = _mm_add_epi32(sum0, sum1); |
||||
sum2 = _mm_add_epi32(sum2, sum3); |
||||
vecSum = _mm_add_epi32(vecSum, sum0); |
||||
vecSum = _mm_add_epi32(vecSum, sum2); |
||||
} |
||||
|
||||
vecX = OP_CVTEPI16_EPI32_M64(&x[len - 4]); |
||||
if (len - j == 3) |
||||
{ |
||||
vecX0 = _mm_shuffle_epi32(vecX, 0x55); |
||||
vecX1 = _mm_shuffle_epi32(vecX, 0xaa); |
||||
vecX2 = _mm_shuffle_epi32(vecX, 0xff); |
||||
|
||||
vecY0 = OP_CVTEPI16_EPI32_M64(&y[j + 0]); |
||||
vecY1 = OP_CVTEPI16_EPI32_M64(&y[j + 1]); |
||||
vecY2 = OP_CVTEPI16_EPI32_M64(&y[j + 2]); |
||||
|
||||
sum0 = _mm_mullo_epi32(vecX0, vecY0); |
||||
sum1 = _mm_mullo_epi32(vecX1, vecY1); |
||||
sum2 = _mm_mullo_epi32(vecX2, vecY2); |
||||
|
||||
vecSum = _mm_add_epi32(vecSum, sum0); |
||||
vecSum = _mm_add_epi32(vecSum, sum1); |
||||
vecSum = _mm_add_epi32(vecSum, sum2); |
||||
} |
||||
else if (len - j == 2) |
||||
{ |
||||
vecX0 = _mm_shuffle_epi32(vecX, 0xaa); |
||||
vecX1 = _mm_shuffle_epi32(vecX, 0xff); |
||||
|
||||
vecY0 = OP_CVTEPI16_EPI32_M64(&y[j + 0]); |
||||
vecY1 = OP_CVTEPI16_EPI32_M64(&y[j + 1]); |
||||
|
||||
sum0 = _mm_mullo_epi32(vecX0, vecY0); |
||||
sum1 = _mm_mullo_epi32(vecX1, vecY1); |
||||
|
||||
vecSum = _mm_add_epi32(vecSum, sum0); |
||||
vecSum = _mm_add_epi32(vecSum, sum1); |
||||
} |
||||
else if (len - j == 1) |
||||
{ |
||||
vecX0 = _mm_shuffle_epi32(vecX, 0xff); |
||||
|
||||
vecY0 = OP_CVTEPI16_EPI32_M64(&y[j + 0]); |
||||
|
||||
sum0 = _mm_mullo_epi32(vecX0, vecY0); |
||||
|
||||
vecSum = _mm_add_epi32(vecSum, sum0); |
||||
} |
||||
|
||||
initSum = _mm_loadu_si128((__m128i *)(void*)(&sum[0])); |
||||
initSum = _mm_add_epi32(initSum, vecSum); |
||||
_mm_storeu_si128((__m128i *)(void*)sum, initSum); |
||||
|
||||
#ifdef OPUS_CHECK_ASM |
||||
celt_assert(!memcmp(sum_c, sum, sizeof(sum_c))); |
||||
#endif |
||||
} |
||||
#endif |
||||
@ -0,0 +1,52 @@
|
||||
/* Copyright (c) 2016 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 VQ_SSE_H |
||||
#define VQ_SSE_H |
||||
|
||||
#if defined(OPUS_X86_MAY_HAVE_SSE2) && !defined(FIXED_POINT) |
||||
|
||||
opus_val16 op_pvq_search_sse2(celt_norm *_X, int *iy, int K, int N, int arch); |
||||
|
||||
#if defined(OPUS_X86_PRESUME_SSE2) |
||||
|
||||
#define OVERRIDE_OP_PVQ_SEARCH |
||||
#define op_pvq_search(x, iy, K, N, arch) \ |
||||
(op_pvq_search_sse2(x, iy, K, N, arch)) |
||||
|
||||
#elif defined(OPUS_HAVE_RTCD) |
||||
|
||||
#define OVERRIDE_OP_PVQ_SEARCH |
||||
extern opus_val16 (*const OP_PVQ_SEARCH_IMPL[OPUS_ARCHMASK + 1])( |
||||
celt_norm *_X, int *iy, int K, int N, int arch); |
||||
|
||||
# define op_pvq_search(X, iy, K, N, arch) \ |
||||
((*OP_PVQ_SEARCH_IMPL[(arch) & OPUS_ARCHMASK])(X, iy, K, N, arch)) |
||||
|
||||
#endif |
||||
#endif |
||||
|
||||
#endif |
||||
@ -0,0 +1,217 @@
|
||||
/* Copyright (c) 2007-2008 CSIRO
|
||||
Copyright (c) 2007-2009 Xiph.Org Foundation |
||||
Copyright (c) 2007-2016 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 <xmmintrin.h> |
||||
#include <emmintrin.h> |
||||
#include "celt_lpc.h" |
||||
#include "stack_alloc.h" |
||||
#include "mathops.h" |
||||
#include "vq.h" |
||||
#include "x86cpu.h" |
||||
|
||||
|
||||
#ifndef FIXED_POINT |
||||
|
||||
opus_val16 op_pvq_search_sse2(celt_norm *_X, int *iy, int K, int N, int arch) |
||||
{ |
||||
int i, j; |
||||
int pulsesLeft; |
||||
float xy, yy; |
||||
VARDECL(celt_norm, y); |
||||
VARDECL(celt_norm, X); |
||||
VARDECL(float, signy); |
||||
__m128 signmask; |
||||
__m128 sums; |
||||
__m128i fours; |
||||
SAVE_STACK; |
||||
|
||||
(void)arch; |
||||
/* All bits set to zero, except for the sign bit. */ |
||||
signmask = _mm_set_ps1(-0.f); |
||||
fours = _mm_set_epi32(4, 4, 4, 4); |
||||
ALLOC(y, N+3, celt_norm); |
||||
ALLOC(X, N+3, celt_norm); |
||||
ALLOC(signy, N+3, float); |
||||
|
||||
OPUS_COPY(X, _X, N); |
||||
X[N] = X[N+1] = X[N+2] = 0; |
||||
sums = _mm_setzero_ps(); |
||||
for (j=0;j<N;j+=4) |
||||
{ |
||||
__m128 x4, s4; |
||||
x4 = _mm_loadu_ps(&X[j]); |
||||
s4 = _mm_cmplt_ps(x4, _mm_setzero_ps()); |
||||
/* Get rid of the sign */ |
||||
x4 = _mm_andnot_ps(signmask, x4); |
||||
sums = _mm_add_ps(sums, x4); |
||||
/* Clear y and iy in case we don't do the projection. */ |
||||
_mm_storeu_ps(&y[j], _mm_setzero_ps()); |
||||
_mm_storeu_si128((__m128i*)(void*)&iy[j], _mm_setzero_si128()); |
||||
_mm_storeu_ps(&X[j], x4); |
||||
_mm_storeu_ps(&signy[j], s4); |
||||
} |
||||
sums = _mm_add_ps(sums, _mm_shuffle_ps(sums, sums, _MM_SHUFFLE(1, 0, 3, 2))); |
||||
sums = _mm_add_ps(sums, _mm_shuffle_ps(sums, sums, _MM_SHUFFLE(2, 3, 0, 1))); |
||||
|
||||
xy = yy = 0; |
||||
|
||||
pulsesLeft = K; |
||||
|
||||
/* Do a pre-search by projecting on the pyramid */ |
||||
if (K > (N>>1)) |
||||
{ |
||||
__m128i pulses_sum; |
||||
__m128 yy4, xy4; |
||||
__m128 rcp4; |
||||
opus_val32 sum = _mm_cvtss_f32(sums); |
||||
/* If X is too small, just replace it with a pulse at 0 */ |
||||
/* Prevents infinities and NaNs from causing too many pulses
|
||||
to be allocated. 64 is an approximation of infinity here. */ |
||||
if (!(sum > EPSILON && sum < 64)) |
||||
{ |
||||
X[0] = QCONST16(1.f,14); |
||||
j=1; do |
||||
X[j]=0; |
||||
while (++j<N); |
||||
sums = _mm_set_ps1(1.f); |
||||
} |
||||
/* Using K+e with e < 1 guarantees we cannot get more than K pulses. */ |
||||
rcp4 = _mm_mul_ps(_mm_set_ps1((float)(K+.8)), _mm_rcp_ps(sums)); |
||||
xy4 = yy4 = _mm_setzero_ps(); |
||||
pulses_sum = _mm_setzero_si128(); |
||||
for (j=0;j<N;j+=4) |
||||
{ |
||||
__m128 rx4, x4, y4; |
||||
__m128i iy4; |
||||
x4 = _mm_loadu_ps(&X[j]); |
||||
rx4 = _mm_mul_ps(x4, rcp4); |
||||
iy4 = _mm_cvttps_epi32(rx4); |
||||
pulses_sum = _mm_add_epi32(pulses_sum, iy4); |
||||
_mm_storeu_si128((__m128i*)(void*)&iy[j], iy4); |
||||
y4 = _mm_cvtepi32_ps(iy4); |
||||
xy4 = _mm_add_ps(xy4, _mm_mul_ps(x4, y4)); |
||||
yy4 = _mm_add_ps(yy4, _mm_mul_ps(y4, y4)); |
||||
/* double the y[] vector so we don't have to do it in the search loop. */ |
||||
_mm_storeu_ps(&y[j], _mm_add_ps(y4, y4)); |
||||
} |
||||
pulses_sum = _mm_add_epi32(pulses_sum, _mm_shuffle_epi32(pulses_sum, _MM_SHUFFLE(1, 0, 3, 2))); |
||||
pulses_sum = _mm_add_epi32(pulses_sum, _mm_shuffle_epi32(pulses_sum, _MM_SHUFFLE(2, 3, 0, 1))); |
||||
pulsesLeft -= _mm_cvtsi128_si32(pulses_sum); |
||||
xy4 = _mm_add_ps(xy4, _mm_shuffle_ps(xy4, xy4, _MM_SHUFFLE(1, 0, 3, 2))); |
||||
xy4 = _mm_add_ps(xy4, _mm_shuffle_ps(xy4, xy4, _MM_SHUFFLE(2, 3, 0, 1))); |
||||
xy = _mm_cvtss_f32(xy4); |
||||
yy4 = _mm_add_ps(yy4, _mm_shuffle_ps(yy4, yy4, _MM_SHUFFLE(1, 0, 3, 2))); |
||||
yy4 = _mm_add_ps(yy4, _mm_shuffle_ps(yy4, yy4, _MM_SHUFFLE(2, 3, 0, 1))); |
||||
yy = _mm_cvtss_f32(yy4); |
||||
} |
||||
X[N] = X[N+1] = X[N+2] = -100; |
||||
y[N] = y[N+1] = y[N+2] = 100; |
||||
celt_sig_assert(pulsesLeft>=0); |
||||
|
||||
/* This should never happen, but just in case it does (e.g. on silence)
|
||||
we fill the first bin with pulses. */ |
||||
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; |
||||
} |
||||
|
||||
for (i=0;i<pulsesLeft;i++) |
||||
{ |
||||
int best_id; |
||||
__m128 xy4, yy4; |
||||
__m128 max, max2; |
||||
__m128i count; |
||||
__m128i pos; |
||||
/* The squared magnitude term gets added anyway, so we might as well
|
||||
add it outside the loop */ |
||||
yy = ADD16(yy, 1); |
||||
xy4 = _mm_load1_ps(&xy); |
||||
yy4 = _mm_load1_ps(&yy); |
||||
max = _mm_setzero_ps(); |
||||
pos = _mm_setzero_si128(); |
||||
count = _mm_set_epi32(3, 2, 1, 0); |
||||
for (j=0;j<N;j+=4) |
||||
{ |
||||
__m128 x4, y4, r4; |
||||
x4 = _mm_loadu_ps(&X[j]); |
||||
y4 = _mm_loadu_ps(&y[j]); |
||||
x4 = _mm_add_ps(x4, xy4); |
||||
y4 = _mm_add_ps(y4, yy4); |
||||
y4 = _mm_rsqrt_ps(y4); |
||||
r4 = _mm_mul_ps(x4, y4); |
||||
/* Update the index of the max. */ |
||||
pos = _mm_max_epi16(pos, _mm_and_si128(count, _mm_castps_si128(_mm_cmpgt_ps(r4, max)))); |
||||
/* Update the max. */ |
||||
max = _mm_max_ps(max, r4); |
||||
/* Update the indices (+4) */ |
||||
count = _mm_add_epi32(count, fours); |
||||
} |
||||
/* Horizontal max */ |
||||
max2 = _mm_max_ps(max, _mm_shuffle_ps(max, max, _MM_SHUFFLE(1, 0, 3, 2))); |
||||
max2 = _mm_max_ps(max2, _mm_shuffle_ps(max2, max2, _MM_SHUFFLE(2, 3, 0, 1))); |
||||
/* Now that max2 contains the max at all positions, look at which value(s) of the
|
||||
partial max is equal to the global max. */ |
||||
pos = _mm_and_si128(pos, _mm_castps_si128(_mm_cmpeq_ps(max, max2))); |
||||
pos = _mm_max_epi16(pos, _mm_unpackhi_epi64(pos, pos)); |
||||
pos = _mm_max_epi16(pos, _mm_shufflelo_epi16(pos, _MM_SHUFFLE(1, 0, 3, 2))); |
||||
best_id = _mm_cvtsi128_si32(pos); |
||||
|
||||
/* 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; |
||||
iy[best_id]++; |
||||
} |
||||
|
||||
/* Put the original sign back */ |
||||
for (j=0;j<N;j+=4) |
||||
{ |
||||
__m128i y4; |
||||
__m128i s4; |
||||
y4 = _mm_loadu_si128((__m128i*)(void*)&iy[j]); |
||||
s4 = _mm_castps_si128(_mm_loadu_ps(&signy[j])); |
||||
y4 = _mm_xor_si128(_mm_add_epi32(y4, s4), s4); |
||||
_mm_storeu_si128((__m128i*)(void*)&iy[j], y4); |
||||
} |
||||
RESTORE_STACK; |
||||
return yy; |
||||
} |
||||
|
||||
#endif |
||||
@ -0,0 +1,47 @@
|
||||
/* Copyright (c) 2023 Amazon */ |
||||
/*
|
||||
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 FOUNDATION 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 _MSC_VER |
||||
|
||||
# ifdef OPUS_X86_MAY_HAVE_SSE |
||||
# ifndef __SSE__ |
||||
# define __SSE__ |
||||
# endif |
||||
# endif |
||||
|
||||
# ifdef OPUS_X86_MAY_HAVE_SSE2 |
||||
# ifndef __SSE2__ |
||||
# define __SSE2__ |
||||
# endif |
||||
# endif |
||||
|
||||
# ifdef OPUS_X86_MAY_HAVE_SSE4_1 |
||||
# ifndef __SSE4_1__ |
||||
# define __SSE4_1__ |
||||
# endif |
||||
# endif |
||||
|
||||
#endif |
||||
@ -0,0 +1,187 @@
|
||||
/* Copyright (c) 2014, Cisco Systems, INC
|
||||
Written by XiangMingZhu WeiZhou MinPeng YanWang |
||||
|
||||
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 "x86/x86cpu.h" |
||||
#include "celt_lpc.h" |
||||
#include "pitch.h" |
||||
#include "pitch_sse.h" |
||||
#include "vq.h" |
||||
|
||||
#if defined(OPUS_HAVE_RTCD) |
||||
|
||||
# if defined(FIXED_POINT) |
||||
|
||||
#if defined(OPUS_X86_MAY_HAVE_SSE4_1) && !defined(OPUS_X86_PRESUME_SSE4_1) |
||||
|
||||
void (*const CELT_FIR_IMPL[OPUS_ARCHMASK + 1])( |
||||
const opus_val16 *x, |
||||
const opus_val16 *num, |
||||
opus_val16 *y, |
||||
int N, |
||||
int ord, |
||||
int arch |
||||
) = { |
||||
celt_fir_c, /* non-sse */ |
||||
celt_fir_c, |
||||
celt_fir_c, |
||||
MAY_HAVE_SSE4_1(celt_fir), /* sse4.1 */ |
||||
MAY_HAVE_SSE4_1(celt_fir) /* avx */ |
||||
}; |
||||
|
||||
void (*const XCORR_KERNEL_IMPL[OPUS_ARCHMASK + 1])( |
||||
const opus_val16 *x, |
||||
const opus_val16 *y, |
||||
opus_val32 sum[4], |
||||
int len |
||||
) = { |
||||
xcorr_kernel_c, /* non-sse */ |
||||
xcorr_kernel_c, |
||||
xcorr_kernel_c, |
||||
MAY_HAVE_SSE4_1(xcorr_kernel), /* sse4.1 */ |
||||
MAY_HAVE_SSE4_1(xcorr_kernel) /* avx */ |
||||
}; |
||||
|
||||
#endif |
||||
|
||||
#if (defined(OPUS_X86_MAY_HAVE_SSE4_1) && !defined(OPUS_X86_PRESUME_SSE4_1)) || \ |
||||
(!defined(OPUS_X86_MAY_HAVE_SSE_4_1) && defined(OPUS_X86_MAY_HAVE_SSE2) && !defined(OPUS_X86_PRESUME_SSE2)) |
||||
|
||||
opus_val32 (*const CELT_INNER_PROD_IMPL[OPUS_ARCHMASK + 1])( |
||||
const opus_val16 *x, |
||||
const opus_val16 *y, |
||||
int N |
||||
) = { |
||||
celt_inner_prod_c, /* non-sse */ |
||||
celt_inner_prod_c, |
||||
MAY_HAVE_SSE2(celt_inner_prod), |
||||
MAY_HAVE_SSE4_1(celt_inner_prod), /* sse4.1 */ |
||||
MAY_HAVE_SSE4_1(celt_inner_prod) /* avx */ |
||||
}; |
||||
|
||||
#endif |
||||
|
||||
# else |
||||
|
||||
#if defined(OPUS_X86_MAY_HAVE_AVX2) && !defined(OPUS_X86_PRESUME_AVX2) |
||||
|
||||
void (*const PITCH_XCORR_IMPL[OPUS_ARCHMASK + 1])( |
||||
const float *_x, |
||||
const float *_y, |
||||
float *xcorr, |
||||
int len, |
||||
int max_pitch, |
||||
int arch |
||||
) = { |
||||
celt_pitch_xcorr_c, /* non-sse */ |
||||
celt_pitch_xcorr_c, |
||||
celt_pitch_xcorr_c, |
||||
celt_pitch_xcorr_c, |
||||
MAY_HAVE_AVX2(celt_pitch_xcorr) |
||||
}; |
||||
|
||||
#endif |
||||
|
||||
|
||||
#if defined(OPUS_X86_MAY_HAVE_SSE) && !defined(OPUS_X86_PRESUME_SSE) |
||||
|
||||
void (*const XCORR_KERNEL_IMPL[OPUS_ARCHMASK + 1])( |
||||
const opus_val16 *x, |
||||
const opus_val16 *y, |
||||
opus_val32 sum[4], |
||||
int len |
||||
) = { |
||||
xcorr_kernel_c, /* non-sse */ |
||||
MAY_HAVE_SSE(xcorr_kernel), |
||||
MAY_HAVE_SSE(xcorr_kernel), |
||||
MAY_HAVE_SSE(xcorr_kernel), |
||||
MAY_HAVE_SSE(xcorr_kernel) |
||||
}; |
||||
|
||||
opus_val32 (*const CELT_INNER_PROD_IMPL[OPUS_ARCHMASK + 1])( |
||||
const opus_val16 *x, |
||||
const opus_val16 *y, |
||||
int N |
||||
) = { |
||||
celt_inner_prod_c, /* non-sse */ |
||||
MAY_HAVE_SSE(celt_inner_prod), |
||||
MAY_HAVE_SSE(celt_inner_prod), |
||||
MAY_HAVE_SSE(celt_inner_prod), |
||||
MAY_HAVE_SSE(celt_inner_prod) |
||||
}; |
||||
|
||||
void (*const DUAL_INNER_PROD_IMPL[OPUS_ARCHMASK + 1])( |
||||
const opus_val16 *x, |
||||
const opus_val16 *y01, |
||||
const opus_val16 *y02, |
||||
int N, |
||||
opus_val32 *xy1, |
||||
opus_val32 *xy2 |
||||
) = { |
||||
dual_inner_prod_c, /* non-sse */ |
||||
MAY_HAVE_SSE(dual_inner_prod), |
||||
MAY_HAVE_SSE(dual_inner_prod), |
||||
MAY_HAVE_SSE(dual_inner_prod), |
||||
MAY_HAVE_SSE(dual_inner_prod) |
||||
}; |
||||
|
||||
void (*const COMB_FILTER_CONST_IMPL[OPUS_ARCHMASK + 1])( |
||||
opus_val32 *y, |
||||
opus_val32 *x, |
||||
int T, |
||||
int N, |
||||
opus_val16 g10, |
||||
opus_val16 g11, |
||||
opus_val16 g12 |
||||
) = { |
||||
comb_filter_const_c, /* non-sse */ |
||||
MAY_HAVE_SSE(comb_filter_const), |
||||
MAY_HAVE_SSE(comb_filter_const), |
||||
MAY_HAVE_SSE(comb_filter_const), |
||||
MAY_HAVE_SSE(comb_filter_const) |
||||
}; |
||||
|
||||
|
||||
#endif |
||||
|
||||
#if defined(OPUS_X86_MAY_HAVE_SSE2) && !defined(OPUS_X86_PRESUME_SSE2) |
||||
opus_val16 (*const OP_PVQ_SEARCH_IMPL[OPUS_ARCHMASK + 1])( |
||||
celt_norm *_X, int *iy, int K, int N, int arch |
||||
) = { |
||||
op_pvq_search_c, /* non-sse */ |
||||
op_pvq_search_c, |
||||
MAY_HAVE_SSE2(op_pvq_search), |
||||
MAY_HAVE_SSE2(op_pvq_search), |
||||
MAY_HAVE_SSE2(op_pvq_search) |
||||
}; |
||||
#endif |
||||
|
||||
#endif |
||||
#endif |
||||
@ -0,0 +1,184 @@
|
||||
/* Copyright (c) 2014, Cisco Systems, INC
|
||||
Written by XiangMingZhu WeiZhou MinPeng YanWang |
||||
|
||||
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 "cpu_support.h" |
||||
#include "macros.h" |
||||
#include "main.h" |
||||
#include "pitch.h" |
||||
#include "x86cpu.h" |
||||
|
||||
#if defined(OPUS_HAVE_RTCD) && \ |
||||
((defined(OPUS_X86_MAY_HAVE_SSE) && !defined(OPUS_X86_PRESUME_SSE)) || \
|
||||
(defined(OPUS_X86_MAY_HAVE_SSE2) && !defined(OPUS_X86_PRESUME_SSE2)) || \
|
||||
(defined(OPUS_X86_MAY_HAVE_SSE4_1) && !defined(OPUS_X86_PRESUME_SSE4_1)) || \
|
||||
(defined(OPUS_X86_MAY_HAVE_AVX2) && !defined(OPUS_X86_PRESUME_AVX2))) |
||||
|
||||
#if defined(_MSC_VER) |
||||
|
||||
#include <intrin.h> |
||||
static _inline void cpuid(unsigned int CPUInfo[4], unsigned int InfoType) |
||||
{ |
||||
__cpuid((int*)CPUInfo, InfoType); |
||||
} |
||||
|
||||
#else |
||||
|
||||
#if defined(CPU_INFO_BY_C) |
||||
#include <cpuid.h> |
||||
#endif |
||||
|
||||
static void cpuid(unsigned int CPUInfo[4], unsigned int InfoType) |
||||
{ |
||||
#if defined(CPU_INFO_BY_ASM) |
||||
#if defined(__i386__) && defined(__PIC__) |
||||
/* %ebx is PIC register in 32-bit, so mustn't clobber it. */ |
||||
__asm__ __volatile__ ( |
||||
"xchg %%ebx, %1\n" |
||||
"cpuid\n" |
||||
"xchg %%ebx, %1\n": |
||||
"=a" (CPUInfo[0]), |
||||
"=r" (CPUInfo[1]), |
||||
"=c" (CPUInfo[2]), |
||||
"=d" (CPUInfo[3]) : |
||||
/* We clear ECX to avoid a valgrind false-positive prior to v3.17.0. */ |
||||
"0" (InfoType), "2" (0) |
||||
); |
||||
#else |
||||
__asm__ __volatile__ ( |
||||
"cpuid": |
||||
"=a" (CPUInfo[0]), |
||||
"=b" (CPUInfo[1]), |
||||
"=c" (CPUInfo[2]), |
||||
"=d" (CPUInfo[3]) : |
||||
/* We clear ECX to avoid a valgrind false-positive prior to v3.17.0. */ |
||||
"0" (InfoType), "2" (0) |
||||
); |
||||
#endif |
||||
#elif defined(CPU_INFO_BY_C) |
||||
/* We use __get_cpuid_count to clear ECX to avoid a valgrind false-positive
|
||||
prior to v3.17.0.*/ |
||||
if (!__get_cpuid_count(InfoType, 0, &(CPUInfo[0]), &(CPUInfo[1]), &(CPUInfo[2]), &(CPUInfo[3]))) { |
||||
/* Our function cannot fail, but __get_cpuid{_count} can.
|
||||
Returning all zeroes will effectively disable all SIMD, which is |
||||
what we want on CPUs that don't support CPUID. */ |
||||
CPUInfo[3] = CPUInfo[2] = CPUInfo[1] = CPUInfo[0] = 0; |
||||
} |
||||
#else |
||||
# error "Configured to use x86 RTCD, but no CPU detection method available. " \ |
||||
"Reconfigure with --disable-rtcd (or send patches)." |
||||
#endif |
||||
} |
||||
|
||||
#endif |
||||
|
||||
typedef struct CPU_Feature{ |
||||
/* SIMD: 128-bit */ |
||||
int HW_SSE; |
||||
int HW_SSE2; |
||||
int HW_SSE41; |
||||
/* SIMD: 256-bit */ |
||||
int HW_AVX2; |
||||
} CPU_Feature; |
||||
|
||||
static void opus_cpu_feature_check(CPU_Feature *cpu_feature) |
||||
{ |
||||
unsigned int info[4]; |
||||
unsigned int nIds = 0; |
||||
|
||||
cpuid(info, 0); |
||||
nIds = info[0]; |
||||
|
||||
if (nIds >= 1){ |
||||
cpuid(info, 1); |
||||
cpu_feature->HW_SSE = (info[3] & (1 << 25)) != 0; |
||||
cpu_feature->HW_SSE2 = (info[3] & (1 << 26)) != 0; |
||||
cpu_feature->HW_SSE41 = (info[2] & (1 << 19)) != 0; |
||||
cpu_feature->HW_AVX2 = (info[2] & (1 << 28)) != 0 && (info[2] & (1 << 12)) != 0; |
||||
if (cpu_feature->HW_AVX2 && nIds >= 7) { |
||||
cpuid(info, 7); |
||||
cpu_feature->HW_AVX2 = cpu_feature->HW_AVX2 && (info[1] & (1 << 5)) != 0; |
||||
} else { |
||||
cpu_feature->HW_AVX2 = 0; |
||||
} |
||||
} |
||||
else { |
||||
cpu_feature->HW_SSE = 0; |
||||
cpu_feature->HW_SSE2 = 0; |
||||
cpu_feature->HW_SSE41 = 0; |
||||
cpu_feature->HW_AVX2 = 0; |
||||
} |
||||
} |
||||
|
||||
static int opus_select_arch_impl(void) |
||||
{ |
||||
CPU_Feature cpu_feature; |
||||
int arch; |
||||
|
||||
opus_cpu_feature_check(&cpu_feature); |
||||
|
||||
arch = 0; |
||||
if (!cpu_feature.HW_SSE) |
||||
{ |
||||
return arch; |
||||
} |
||||
arch++; |
||||
|
||||
if (!cpu_feature.HW_SSE2) |
||||
{ |
||||
return arch; |
||||
} |
||||
arch++; |
||||
|
||||
if (!cpu_feature.HW_SSE41) |
||||
{ |
||||
return arch; |
||||
} |
||||
arch++; |
||||
|
||||
if (!cpu_feature.HW_AVX2) |
||||
{ |
||||
return arch; |
||||
} |
||||
arch++; |
||||
|
||||
return arch; |
||||
} |
||||
|
||||
int opus_select_arch(void) { |
||||
int arch = opus_select_arch_impl(); |
||||
#ifdef FUZZING |
||||
/* Randomly downgrade the architecture. */ |
||||
arch = rand()%(arch+1); |
||||
#endif |
||||
return arch; |
||||
} |
||||
|
||||
#endif |
||||
@ -0,0 +1,112 @@
|
||||
/* Copyright (c) 2014, Cisco Systems, INC
|
||||
Written by XiangMingZhu WeiZhou MinPeng YanWang |
||||
|
||||
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(X86CPU_H) |
||||
# define X86CPU_H |
||||
|
||||
# if defined(OPUS_X86_MAY_HAVE_SSE) |
||||
# define MAY_HAVE_SSE(name) name ## _sse |
||||
# else |
||||
# define MAY_HAVE_SSE(name) name ## _c |
||||
# endif |
||||
|
||||
# if defined(OPUS_X86_MAY_HAVE_SSE2) |
||||
# define MAY_HAVE_SSE2(name) name ## _sse2 |
||||
# else |
||||
# define MAY_HAVE_SSE2(name) name ## _c |
||||
# endif |
||||
|
||||
# if defined(OPUS_X86_MAY_HAVE_SSE4_1) |
||||
# define MAY_HAVE_SSE4_1(name) name ## _sse4_1 |
||||
# else |
||||
# define MAY_HAVE_SSE4_1(name) name ## _c |
||||
# endif |
||||
|
||||
# if defined(OPUS_X86_MAY_HAVE_AVX2) |
||||
# define MAY_HAVE_AVX2(name) name ## _avx2 |
||||
# else |
||||
# define MAY_HAVE_AVX2(name) name ## _c |
||||
# endif |
||||
|
||||
# if defined(OPUS_HAVE_RTCD) && \ |
||||
((defined(OPUS_X86_MAY_HAVE_SSE) && !defined(OPUS_X86_PRESUME_SSE)) || \
|
||||
(defined(OPUS_X86_MAY_HAVE_SSE2) && !defined(OPUS_X86_PRESUME_SSE2)) || \
|
||||
(defined(OPUS_X86_MAY_HAVE_SSE4_1) && !defined(OPUS_X86_PRESUME_SSE4_1)) || \
|
||||
(defined(OPUS_X86_MAY_HAVE_AVX2) && !defined(OPUS_X86_PRESUME_AVX2))) |
||||
int opus_select_arch(void); |
||||
# endif |
||||
|
||||
# if defined(OPUS_X86_MAY_HAVE_SSE2) |
||||
# include "opus_defines.h" |
||||
|
||||
/*MOVD should not impose any alignment restrictions, but the C standard does,
|
||||
and UBSan will report errors if we actually make unaligned accesses. |
||||
Use this to work around those restrictions (which should hopefully all get |
||||
optimized to a single MOVD instruction). |
||||
GCC implemented _mm_loadu_si32() since GCC 11; HOWEVER, there is a bug! |
||||
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99754
|
||||
LLVM implemented _mm_loadu_si32() since Clang 8.0, however the |
||||
__clang_major__ version number macro is unreliable, as vendors |
||||
(specifically, Apple) will use different numbering schemes than upstream. |
||||
Clang's advice is "use feature detection", but they do not provide feature |
||||
detection support for specific SIMD functions. |
||||
We follow the approach from the SIMDe project and instead detect unrelated |
||||
features that should be available in the version we want (see |
||||
<https://github.com/simd-everywhere/simde/blob/master/simde/simde-detect-clang.h>).*/
|
||||
# if defined(__clang__) |
||||
# if __has_warning("-Wextra-semi-stmt") || \ |
||||
__has_builtin(__builtin_rotateleft32) |
||||
# define OPUS_CLANG_8 (1) |
||||
# endif |
||||
# endif |
||||
# if !defined(_MSC_VER) && !OPUS_GNUC_PREREQ(11,3) && !defined(OPUS_CLANG_8) |
||||
# include <string.h> |
||||
# include <emmintrin.h> |
||||
|
||||
# ifdef _mm_loadu_si32 |
||||
# undef _mm_loadu_si32 |
||||
# endif |
||||
# define _mm_loadu_si32 WORKAROUND_mm_loadu_si32 |
||||
static inline __m128i WORKAROUND_mm_loadu_si32(void const* mem_addr) { |
||||
int val; |
||||
memcpy(&val, mem_addr, sizeof(val)); |
||||
return _mm_cvtsi32_si128(val); |
||||
} |
||||
# elif defined(_MSC_VER) |
||||
/* MSVC needs this for _mm_loadu_si32 */ |
||||
# include <immintrin.h> |
||||
# endif |
||||
|
||||
# define OP_CVTEPI8_EPI32_M32(x) \ |
||||
(_mm_cvtepi8_epi32(_mm_loadu_si32(x))) |
||||
|
||||
# define OP_CVTEPI16_EPI32_M64(x) \ |
||||
(_mm_cvtepi16_epi32(_mm_loadl_epi64((__m128i *)(void*)(x)))) |
||||
|
||||
# endif |
||||
|
||||
#endif |
||||
@ -0,0 +1,381 @@
|
||||
/* 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 |
||||
|
||||
#if defined(CUSTOM_MODES) || defined(ENABLE_OPUS_CUSTOM_API) |
||||
# define OPUS_CUSTOM_EXPORT OPUS_EXPORT |
||||
# define OPUS_CUSTOM_EXPORT_STATIC OPUS_EXPORT |
||||
#else |
||||
# define OPUS_CUSTOM_EXPORT |
||||
# ifdef OPUS_BUILD |
||||
# define OPUS_CUSTOM_EXPORT_STATIC static OPUS_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. The mode MUST NOT BE DESTROYED until the encoders and |
||||
decoders that use it are destroyed as well. |
||||
@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); |
||||
|
||||
|
||||
#if !defined(OPUS_BUILD) || defined(CELT_ENCODER_C) |
||||
|
||||
/* 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); |
||||
|
||||
#if defined(CUSTOM_MODES) || defined(ENABLE_OPUS_CUSTOM_API) |
||||
/** 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 int opus_custom_encoder_init( |
||||
OpusCustomEncoder *st, |
||||
const OpusCustomMode *mode, |
||||
int channels |
||||
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2); |
||||
# endif |
||||
#endif |
||||
|
||||
|
||||
/** 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); |
||||
|
||||
|
||||
/** Destroys 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); |
||||
|
||||
/** Encodes a frame of audio.
|
||||
* @param [in] st <tt>OpusCustomEncoder*</tt>: Encoder state |
||||
* @param [in] pcm <tt>opus_int32*</tt>: PCM audio in signed 32-bit format (native endian) representing (or slightly exceeding) 24-bit values. |
||||
* 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_encode24( |
||||
OpusCustomEncoder *st, |
||||
const opus_int32 *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); |
||||
|
||||
|
||||
#if !defined(OPUS_BUILD) || defined(CELT_DECODER_C) |
||||
/* 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); |
||||
|
||||
/** 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); |
||||
|
||||
#endif |
||||
|
||||
|
||||
/** 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); |
||||
|
||||
/** Destroys a 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); |
||||
|
||||
/** 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_int32*</tt>: Output signal (interleaved if 2 channels) representing (or slightly exceeding) 24-bit values. length |
||||
* is frame_size*channels*sizeof(opus_int32) |
||||
* @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_decode24( |
||||
OpusCustomDecoder *st, |
||||
const unsigned char *data, |
||||
int len, |
||||
opus_int32 *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,867 @@
|
||||
/* 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 |
||||
/** Not enough bytes allocated in the buffer @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(_WIN32) |
||||
# if defined(OPUS_BUILD) && defined(DLL_EXPORT) |
||||
# define OPUS_EXPORT __declspec(dllexport) |
||||
# else |
||||
# define OPUS_EXPORT |
||||
# endif |
||||
# elif defined(__GNUC__) && defined(OPUS_BUILD) |
||||
# define OPUS_EXPORT __attribute__ ((visibility ("default"))) |
||||
# 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 |
||||
|
||||
#if (!defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L) ) |
||||
# if OPUS_GNUC_PREREQ(2,7) |
||||
# define OPUS_INLINE __inline__ |
||||
# elif (defined(_MSC_VER)) |
||||
# define OPUS_INLINE __inline |
||||
# else |
||||
# define OPUS_INLINE |
||||
# endif |
||||
#else |
||||
# define OPUS_INLINE inline |
||||
#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 |
||||
#define OPUS_SET_EXPERT_FRAME_DURATION_REQUEST 4040 |
||||
#define OPUS_GET_EXPERT_FRAME_DURATION_REQUEST 4041 |
||||
#define OPUS_SET_PREDICTION_DISABLED_REQUEST 4042 |
||||
#define OPUS_GET_PREDICTION_DISABLED_REQUEST 4043 |
||||
/* Don't use 4045, it's already taken by OPUS_GET_GAIN_REQUEST */ |
||||
#define OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST 4046 |
||||
#define OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST 4047 |
||||
#define OPUS_GET_IN_DTX_REQUEST 4049 |
||||
#define OPUS_SET_DRED_DURATION_REQUEST 4050 |
||||
#define OPUS_GET_DRED_DURATION_REQUEST 4051 |
||||
#define OPUS_SET_DNN_BLOB_REQUEST 4052 |
||||
/*#define OPUS_GET_DNN_BLOB_REQUEST 4053 */ |
||||
#define OPUS_SET_OSCE_BWE_REQUEST 4054 |
||||
#define OPUS_GET_OSCE_BWE_REQUEST 4055 |
||||
#define OPUS_SET_QEXT_REQUEST 4056 |
||||
#define OPUS_GET_QEXT_REQUEST 4057 |
||||
#define OPUS_SET_IGNORE_EXTENSIONS_REQUEST 4058 |
||||
#define OPUS_GET_IGNORE_EXTENSIONS_REQUEST 4059 |
||||
|
||||
/** Defines for the presence of extended APIs. */ |
||||
#define OPUS_HAVE_OPUS_PROJECTION_H |
||||
|
||||
/* 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)) |
||||
|
||||
#ifdef DISABLE_PTR_CHECK |
||||
/* Disable checks to prevent ubsan from complaining about NULL checks
|
||||
in test_opus_api. */ |
||||
#define opus_check_int_ptr(ptr) (ptr) |
||||
#define opus_check_uint_ptr(ptr) (ptr) |
||||
#define opus_check_uint8_ptr(ptr) (ptr) |
||||
#define opus_check_val16_ptr(ptr) (ptr) |
||||
#define opus_check_void_ptr(ptr) (ptr) |
||||
#else |
||||
#define opus_check_int_ptr(ptr) ((ptr) + ((ptr) - (opus_int32*)(ptr))) |
||||
#define opus_check_uint_ptr(ptr) ((ptr) + ((ptr) - (opus_uint32*)(ptr))) |
||||
#define opus_check_uint8_ptr(ptr) ((ptr) + ((ptr) - (opus_uint8*)(ptr))) |
||||
#define opus_check_val16_ptr(ptr) ((ptr) + ((ptr) - (opus_val16*)(ptr))) |
||||
#define opus_check_void_ptr(x) ((void)((void *)0 == (x)), (x)) |
||||
#endif |
||||
/** @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 |
||||
/** Experts only: forces SILK encoding; don't allocate CELT state at all. Disables OPUS_SET_APPLICATION. */ |
||||
#define OPUS_APPLICATION_RESTRICTED_SILK 2052 |
||||
/** Experts only: forces CELT encoding; don't allocate SILK state at all. Disables OPUS_SET_APPLICATION. */ |
||||
#define OPUS_APPLICATION_RESTRICTED_CELT 2053 |
||||
|
||||
#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*/ |
||||
|
||||
#define OPUS_FRAMESIZE_ARG 5000 /**< Select frame size from the argument (default) */ |
||||
#define OPUS_FRAMESIZE_2_5_MS 5001 /**< Use 2.5 ms frames */ |
||||
#define OPUS_FRAMESIZE_5_MS 5002 /**< Use 5 ms frames */ |
||||
#define OPUS_FRAMESIZE_10_MS 5003 /**< Use 10 ms frames */ |
||||
#define OPUS_FRAMESIZE_20_MS 5004 /**< Use 20 ms frames */ |
||||
#define OPUS_FRAMESIZE_40_MS 5005 /**< Use 40 ms frames */ |
||||
#define OPUS_FRAMESIZE_60_MS 5006 /**< Use 60 ms frames */ |
||||
#define OPUS_FRAMESIZE_80_MS 5007 /**< Use 80 ms frames */ |
||||
#define OPUS_FRAMESIZE_100_MS 5008 /**< Use 100 ms frames */ |
||||
#define OPUS_FRAMESIZE_120_MS 5009 /**< Use 120 ms frames */ |
||||
|
||||
/**@}*/ |
||||
|
||||
|
||||
/** @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. |
||||
* @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 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>Inband FEC enabled. If the packet loss rate is sufficiently high, Opus will automatically switch to SILK even at high rates to enable use of that FEC.</dd> |
||||
* <dt>2</dt><dd>Inband FEC enabled, but does not necessarily switch to SILK if we have music.</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. If the packet loss rate is sufficiently high, Opus will automatically switch to SILK even at high rates to enable use of that FEC.</dd> |
||||
* <dt>2</dt><dd>Inband FEC enabled, but does not necessarily switch to SILK if we have music.</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 trigger progressively more loss resistant behavior in the encoder |
||||
* at the expense of quality at a given bitrate in the absence of packet loss, 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. |
||||
* It represents the number of significant bits of linear intensity below |
||||
* which the signal contains ignorable quantization or other noise. |
||||
* |
||||
* For example, OPUS_SET_LSB_DEPTH(14) would be an appropriate setting |
||||
* for G.711 u-law input. OPUS_SET_LSB_DEPTH(16) would be appropriate |
||||
* for 16-bit linear pcm input with opus_encode_float(). |
||||
* |
||||
* When using opus_encode() instead of opus_encode_float(), or when libopus |
||||
* is compiled for fixed-point, the encoder uses the minimum of the value |
||||
* set here and the value 16. |
||||
* |
||||
* @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) |
||||
|
||||
/** Configures the encoder's use of variable duration frames.
|
||||
* When variable duration is enabled, the encoder is free to use a shorter frame |
||||
* size than the one requested in the opus_encode*() call. |
||||
* It is then the user's responsibility |
||||
* to verify how much audio was encoded by checking the ToC byte of the encoded |
||||
* packet. The part of the audio that was not encoded needs to be resent to the |
||||
* encoder for the next call. Do not use this option unless you <b>really</b> |
||||
* know what you are doing. |
||||
* @see OPUS_GET_EXPERT_FRAME_DURATION |
||||
* @param[in] x <tt>opus_int32</tt>: Allowed values: |
||||
* <dl> |
||||
* <dt>OPUS_FRAMESIZE_ARG</dt><dd>Select frame size from the argument (default).</dd> |
||||
* <dt>OPUS_FRAMESIZE_2_5_MS</dt><dd>Use 2.5 ms frames.</dd> |
||||
* <dt>OPUS_FRAMESIZE_5_MS</dt><dd>Use 5 ms frames.</dd> |
||||
* <dt>OPUS_FRAMESIZE_10_MS</dt><dd>Use 10 ms frames.</dd> |
||||
* <dt>OPUS_FRAMESIZE_20_MS</dt><dd>Use 20 ms frames.</dd> |
||||
* <dt>OPUS_FRAMESIZE_40_MS</dt><dd>Use 40 ms frames.</dd> |
||||
* <dt>OPUS_FRAMESIZE_60_MS</dt><dd>Use 60 ms frames.</dd> |
||||
* <dt>OPUS_FRAMESIZE_80_MS</dt><dd>Use 80 ms frames.</dd> |
||||
* <dt>OPUS_FRAMESIZE_100_MS</dt><dd>Use 100 ms frames.</dd> |
||||
* <dt>OPUS_FRAMESIZE_120_MS</dt><dd>Use 120 ms frames.</dd> |
||||
* </dl> |
||||
* @hideinitializer */ |
||||
#define OPUS_SET_EXPERT_FRAME_DURATION(x) OPUS_SET_EXPERT_FRAME_DURATION_REQUEST, opus_check_int(x) |
||||
/** Gets the encoder's configured use of variable duration frames.
|
||||
* @see OPUS_SET_EXPERT_FRAME_DURATION |
||||
* @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values: |
||||
* <dl> |
||||
* <dt>OPUS_FRAMESIZE_ARG</dt><dd>Select frame size from the argument (default).</dd> |
||||
* <dt>OPUS_FRAMESIZE_2_5_MS</dt><dd>Use 2.5 ms frames.</dd> |
||||
* <dt>OPUS_FRAMESIZE_5_MS</dt><dd>Use 5 ms frames.</dd> |
||||
* <dt>OPUS_FRAMESIZE_10_MS</dt><dd>Use 10 ms frames.</dd> |
||||
* <dt>OPUS_FRAMESIZE_20_MS</dt><dd>Use 20 ms frames.</dd> |
||||
* <dt>OPUS_FRAMESIZE_40_MS</dt><dd>Use 40 ms frames.</dd> |
||||
* <dt>OPUS_FRAMESIZE_60_MS</dt><dd>Use 60 ms frames.</dd> |
||||
* <dt>OPUS_FRAMESIZE_80_MS</dt><dd>Use 80 ms frames.</dd> |
||||
* <dt>OPUS_FRAMESIZE_100_MS</dt><dd>Use 100 ms frames.</dd> |
||||
* <dt>OPUS_FRAMESIZE_120_MS</dt><dd>Use 120 ms frames.</dd> |
||||
* </dl> |
||||
* @hideinitializer */ |
||||
#define OPUS_GET_EXPERT_FRAME_DURATION(x) OPUS_GET_EXPERT_FRAME_DURATION_REQUEST, opus_check_int_ptr(x) |
||||
|
||||
/** If set to 1, disables almost all use of prediction, making frames almost
|
||||
* completely independent. This reduces quality. |
||||
* @see OPUS_GET_PREDICTION_DISABLED |
||||
* @param[in] x <tt>opus_int32</tt>: Allowed values: |
||||
* <dl> |
||||
* <dt>0</dt><dd>Enable prediction (default).</dd> |
||||
* <dt>1</dt><dd>Disable prediction.</dd> |
||||
* </dl> |
||||
* @hideinitializer */ |
||||
#define OPUS_SET_PREDICTION_DISABLED(x) OPUS_SET_PREDICTION_DISABLED_REQUEST, opus_check_int(x) |
||||
/** Gets the encoder's configured prediction status.
|
||||
* @see OPUS_SET_PREDICTION_DISABLED |
||||
* @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values: |
||||
* <dl> |
||||
* <dt>0</dt><dd>Prediction enabled (default).</dd> |
||||
* <dt>1</dt><dd>Prediction disabled.</dd> |
||||
* </dl> |
||||
* @hideinitializer */ |
||||
#define OPUS_GET_PREDICTION_DISABLED(x) OPUS_GET_PREDICTION_DISABLED_REQUEST, opus_check_int_ptr(x) |
||||
|
||||
/** If non-zero, enables Deep Redundancy (DRED) and use the specified maximum number of 10-ms redundant frames
|
||||
* @hideinitializer */ |
||||
#define OPUS_SET_DRED_DURATION(x) OPUS_SET_DRED_DURATION_REQUEST, opus_check_int(x) |
||||
/** Gets the encoder's configured Deep Redundancy (DRED) maximum number of frames.
|
||||
* @hideinitializer */ |
||||
#define OPUS_GET_DRED_DURATION(x) OPUS_GET_DRED_DURATION_REQUEST, opus_check_int_ptr(x) |
||||
|
||||
/** Provide external DNN weights from binary object (only when explicitly built without the weights)
|
||||
* @hideinitializer */ |
||||
#define OPUS_SET_DNN_BLOB(data, len) OPUS_SET_DNN_BLOB_REQUEST, opus_check_void_ptr(data), opus_check_int(len) |
||||
|
||||
/** If set to 1, enables quality extension (QEXT), otherwise disables it (default). Warning: This will *hurt* audio quality unless operating at
|
||||
a very high bitrate. |
||||
* @hideinitializer */ |
||||
#define OPUS_SET_QEXT(x) OPUS_SET_QEXT_REQUEST, opus_check_int(x) |
||||
/** Gets the encoder's configured quality extension (QEXT).
|
||||
* @hideinitializer */ |
||||
#define OPUS_GET_QEXT(x) OPUS_GET_QEXT_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 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) |
||||
|
||||
/** 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) |
||||
|
||||
/** If set to 1, disables the use of phase inversion for intensity stereo,
|
||||
* improving the quality of mono downmixes, but slightly reducing normal |
||||
* stereo quality. Disabling phase inversion in the decoder does not comply |
||||
* with RFC 6716, although it does not cause any interoperability issue and |
||||
* is expected to become part of the Opus standard once RFC 6716 is updated |
||||
* by draft-ietf-codec-opus-update. |
||||
* @see OPUS_GET_PHASE_INVERSION_DISABLED |
||||
* @param[in] x <tt>opus_int32</tt>: Allowed values: |
||||
* <dl> |
||||
* <dt>0</dt><dd>Enable phase inversion (default).</dd> |
||||
* <dt>1</dt><dd>Disable phase inversion.</dd> |
||||
* </dl> |
||||
* @hideinitializer */ |
||||
#define OPUS_SET_PHASE_INVERSION_DISABLED(x) OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST, opus_check_int(x) |
||||
/** Gets the encoder's configured phase inversion status.
|
||||
* @see OPUS_SET_PHASE_INVERSION_DISABLED |
||||
* @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values: |
||||
* <dl> |
||||
* <dt>0</dt><dd>Stereo phase inversion enabled (default).</dd> |
||||
* <dt>1</dt><dd>Stereo phase inversion disabled.</dd> |
||||
* </dl> |
||||
* @hideinitializer */ |
||||
#define OPUS_GET_PHASE_INVERSION_DISABLED(x) OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST, opus_check_int_ptr(x) |
||||
/** Gets the DTX state of the encoder.
|
||||
* Returns whether the last encoded frame was either a comfort noise update |
||||
* during DTX or not encoded because of DTX. |
||||
* @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values: |
||||
* <dl> |
||||
* <dt>0</dt><dd>The encoder is not in DTX.</dd> |
||||
* <dt>1</dt><dd>The encoder is in DTX.</dd> |
||||
* </dl> |
||||
* @hideinitializer */ |
||||
#define OPUS_GET_IN_DTX(x) OPUS_GET_IN_DTX_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) |
||||
|
||||
/** 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) |
||||
|
||||
/** 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) |
||||
|
||||
/** Enables blind bandwidth extension for wideband signals if decoding sampling rate is 48 kHz.
|
||||
* @param[in] x <tt>opus_int32 </tt>: 1 enables bandwidth extension, 0 disables it. |
||||
* The default is 0. |
||||
* |
||||
* @hideinitializer */ |
||||
#define OPUS_SET_OSCE_BWE(x) OPUS_SET_OSCE_BWE_REQUEST, opus_check_int(x) |
||||
/** Gets blind bandwidth extension flag for wideband signals if decoding sampling rate is 48 kHz.
|
||||
* @param[out] x <tt>opus_int32 *</tt>: 1 if bwe enabled, 0 if disabled. |
||||
* |
||||
* @hideinitializer */ |
||||
#define OPUS_GET_OSCE_BWE(x) OPUS_GET_OSCE_BWE_REQUEST, opus_check_int_ptr(x) |
||||
|
||||
/** If set to 1, the decoder will ignore all extensions found in the padding area
|
||||
* (does not affect DRED, which is decoded separately). |
||||
* @hideinitializer */ |
||||
#define OPUS_SET_IGNORE_EXTENSIONS(x) OPUS_SET_IGNORE_EXTENSIONS_REQUEST, opus_check_int(x) |
||||
/** Gets whether the decoder is ignoring extensions.
|
||||
* @hideinitializer */ |
||||
#define OPUS_GET_IGNORE_EXTENSIONS(x) OPUS_GET_IGNORE_EXTENSIONS_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.
|
||||
* |
||||
* Applications may look for the substring "-fixed" in the version string to |
||||
* determine whether they have a fixed-point or floating-point build at |
||||
* runtime. |
||||
* |
||||
* @returns Version string |
||||
*/ |
||||
OPUS_EXPORT const char *opus_get_version_string(void); |
||||
/**@}*/ |
||||
|
||||
#ifdef __cplusplus |
||||
} |
||||
#endif |
||||
|
||||
#endif /* OPUS_DEFINES_H */ |
||||
@ -0,0 +1,736 @@
|
||||
/* 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 |
||||
* <a href="https://tools.ietf.org/html/rfc7845">RFC 7845</a> |
||||
* and is based on the self-delimited Opus framing described in Appendix B of |
||||
* <a href="https://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="https://www.xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-810004.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 outputting 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 |
||||
); |
||||
|
||||
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_multistream_surround_encoder_get_size( |
||||
int channels, |
||||
int mapping_family |
||||
); |
||||
|
||||
|
||||
/** 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); |
||||
|
||||
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusMSEncoder *opus_multistream_surround_encoder_create( |
||||
opus_int32 Fs, |
||||
int channels, |
||||
int mapping_family, |
||||
int *streams, |
||||
int *coupled_streams, |
||||
unsigned char *mapping, |
||||
int application, |
||||
int *error |
||||
) OPUS_ARG_NONNULL(4) OPUS_ARG_NONNULL(5) OPUS_ARG_NONNULL(6); |
||||
|
||||
/** 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); |
||||
|
||||
OPUS_EXPORT int opus_multistream_surround_encoder_init( |
||||
OpusMSEncoder *st, |
||||
opus_int32 Fs, |
||||
int channels, |
||||
int mapping_family, |
||||
int *streams, |
||||
int *coupled_streams, |
||||
unsigned char *mapping, |
||||
int application |
||||
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(5) OPUS_ARG_NONNULL(6) OPUS_ARG_NONNULL(7); |
||||
|
||||
/** 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.
|
||||
* @param st <tt>OpusMSEncoder*</tt>: Multistream encoder state. |
||||
* @param[in] pcm <tt>const opus_int32*</tt>: The input signal as interleaved |
||||
* samples representing (or slightly exceeding) 24-bit values. |
||||
* 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_encode24( |
||||
OpusMSEncoder *st, |
||||
const opus_int32 *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); |
||||
|
||||
/** Initialize 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.
|
||||
* @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_int32*</tt>: Output signal, with interleaved |
||||
* samples representing (or slightly exceeding) 24-bit values. |
||||
* 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_decode24( |
||||
OpusMSDecoder *st, |
||||
const unsigned char *data, |
||||
opus_int32 len, |
||||
opus_int32 *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,643 @@
|
||||
/* Copyright (c) 2017 Google Inc.
|
||||
Written by Andrew Allen */ |
||||
/*
|
||||
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_projection.h |
||||
* @brief Opus projection reference API |
||||
*/ |
||||
|
||||
#ifndef OPUS_PROJECTION_H |
||||
#define OPUS_PROJECTION_H |
||||
|
||||
#include "opus_multistream.h" |
||||
|
||||
#ifdef __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
/** @cond OPUS_INTERNAL_DOC */ |
||||
|
||||
/** These are the actual encoder and decoder CTL ID numbers.
|
||||
* They should not be used directly by applications.c |
||||
* In general, SETs should be even and GETs should be odd.*/ |
||||
/**@{*/ |
||||
#define OPUS_PROJECTION_GET_DEMIXING_MATRIX_GAIN_REQUEST 6001 |
||||
#define OPUS_PROJECTION_GET_DEMIXING_MATRIX_SIZE_REQUEST 6003 |
||||
#define OPUS_PROJECTION_GET_DEMIXING_MATRIX_REQUEST 6005 |
||||
/**@}*/ |
||||
|
||||
|
||||
/** @endcond */ |
||||
|
||||
/** @defgroup opus_projection_ctls Projection specific encoder and decoder CTLs
|
||||
* |
||||
* These are convenience macros that are specific to the |
||||
* opus_projection_encoder_ctl() and opus_projection_decoder_ctl() |
||||
* interface. |
||||
* The CTLs from @ref opus_genericctls, @ref opus_encoderctls, |
||||
* @ref opus_decoderctls, and @ref opus_multistream_ctls may be applied to a |
||||
* projection encoder or decoder as well. |
||||
*/ |
||||
/**@{*/ |
||||
|
||||
/** Gets the gain (in dB. S7.8-format) of the demixing matrix from the encoder.
|
||||
* @param[out] x <tt>opus_int32 *</tt>: Returns the gain (in dB. S7.8-format) |
||||
* of the demixing matrix. |
||||
* @hideinitializer |
||||
*/ |
||||
#define OPUS_PROJECTION_GET_DEMIXING_MATRIX_GAIN(x) OPUS_PROJECTION_GET_DEMIXING_MATRIX_GAIN_REQUEST, opus_check_int_ptr(x) |
||||
|
||||
|
||||
/** Gets the size in bytes of the demixing matrix from the encoder.
|
||||
* @param[out] x <tt>opus_int32 *</tt>: Returns the size in bytes of the |
||||
* demixing matrix. |
||||
* @hideinitializer |
||||
*/ |
||||
#define OPUS_PROJECTION_GET_DEMIXING_MATRIX_SIZE(x) OPUS_PROJECTION_GET_DEMIXING_MATRIX_SIZE_REQUEST, opus_check_int_ptr(x) |
||||
|
||||
|
||||
/** Copies the demixing matrix to the supplied pointer location.
|
||||
* @param[out] x <tt>unsigned char *</tt>: Returns the demixing matrix to the |
||||
* supplied pointer location. |
||||
* @param y <tt>opus_int32</tt>: The size in bytes of the reserved memory at the |
||||
* pointer location. |
||||
* @hideinitializer |
||||
*/ |
||||
#define OPUS_PROJECTION_GET_DEMIXING_MATRIX(x,y) OPUS_PROJECTION_GET_DEMIXING_MATRIX_REQUEST, x, opus_check_int(y) |
||||
|
||||
|
||||
/**@}*/ |
||||
|
||||
/** Opus projection encoder state.
|
||||
* This contains the complete state of a projection Opus encoder. |
||||
* It is position independent and can be freely copied. |
||||
* @see opus_projection_ambisonics_encoder_create |
||||
*/ |
||||
typedef struct OpusProjectionEncoder OpusProjectionEncoder; |
||||
|
||||
|
||||
/** Opus projection decoder state.
|
||||
* This contains the complete state of a projection Opus decoder. |
||||
* It is position independent and can be freely copied. |
||||
* @see opus_projection_decoder_create |
||||
* @see opus_projection_decoder_init |
||||
*/ |
||||
typedef struct OpusProjectionDecoder OpusProjectionDecoder; |
||||
|
||||
|
||||
/**\name Projection encoder functions */ |
||||
/**@{*/ |
||||
|
||||
/** Gets the size of an OpusProjectionEncoder structure.
|
||||
* @param channels <tt>int</tt>: The total number of input channels to encode. |
||||
* This must be no more than 255. |
||||
* @param mapping_family <tt>int</tt>: The mapping family to use for selecting |
||||
* the appropriate projection. |
||||
* @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_projection_ambisonics_encoder_get_size( |
||||
int channels, |
||||
int mapping_family |
||||
); |
||||
|
||||
|
||||
/** Allocates and initializes a projection encoder state.
|
||||
* Call opus_projection_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 mapping_family <tt>int</tt>: The mapping family to use for selecting |
||||
* the appropriate projection. |
||||
* @param[out] streams <tt>int *</tt>: The total number of streams that will |
||||
* be encoded from the input. |
||||
* @param[out] coupled_streams <tt>int *</tt>: Number of coupled (2 channel) |
||||
* streams that will be encoded from the input. |
||||
* @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 OpusProjectionEncoder *opus_projection_ambisonics_encoder_create( |
||||
opus_int32 Fs, |
||||
int channels, |
||||
int mapping_family, |
||||
int *streams, |
||||
int *coupled_streams, |
||||
int application, |
||||
int *error |
||||
) OPUS_ARG_NONNULL(4) OPUS_ARG_NONNULL(5); |
||||
|
||||
|
||||
/** Initialize a previously allocated projection encoder state.
|
||||
* The memory pointed to by \a st must be at least the size returned by |
||||
* opus_projection_ambisonics_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_projection_ambisonics_encoder_create |
||||
* @see opus_projection_ambisonics_encoder_get_size |
||||
* @param st <tt>OpusProjectionEncoder*</tt>: Projection 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 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_projection_ambisonics_encoder_init( |
||||
OpusProjectionEncoder *st, |
||||
opus_int32 Fs, |
||||
int channels, |
||||
int mapping_family, |
||||
int *streams, |
||||
int *coupled_streams, |
||||
int application |
||||
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(5) OPUS_ARG_NONNULL(6); |
||||
|
||||
|
||||
/** Encodes a projection Opus frame.
|
||||
* @param st <tt>OpusProjectionEncoder*</tt>: Projection 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_projection_encode( |
||||
OpusProjectionEncoder *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 projection Opus frame.
|
||||
* @param st <tt>OpusProjectionEncoder*</tt>: Projection encoder state. |
||||
* @param[in] pcm <tt>const opus_int32*</tt>: The input signal as interleaved |
||||
* samples representing (or slightly exceeding) 24-bit values. |
||||
* 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_projection_encode24( |
||||
OpusProjectionEncoder *st, |
||||
const opus_int32 *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 projection Opus frame from floating point input.
|
||||
* @param st <tt>OpusProjectionEncoder*</tt>: Projection 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_projection_encode_float( |
||||
OpusProjectionEncoder *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>OpusProjectionEncoder</code> allocated by
|
||||
* opus_projection_ambisonics_encoder_create(). |
||||
* @param st <tt>OpusProjectionEncoder*</tt>: Projection encoder state to be freed. |
||||
*/ |
||||
OPUS_EXPORT void opus_projection_encoder_destroy(OpusProjectionEncoder *st); |
||||
|
||||
|
||||
/** Perform a CTL function on a projection Opus encoder.
|
||||
* |
||||
* Generally the request and subsequent arguments are generated by a |
||||
* convenience macro. |
||||
* @param st <tt>OpusProjectionEncoder*</tt>: Projection 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, @ref opus_multistream_ctls, or |
||||
* @ref opus_projection_ctls |
||||
* @see opus_genericctls |
||||
* @see opus_encoderctls |
||||
* @see opus_multistream_ctls |
||||
* @see opus_projection_ctls |
||||
*/ |
||||
OPUS_EXPORT int opus_projection_encoder_ctl(OpusProjectionEncoder *st, int request, ...) OPUS_ARG_NONNULL(1); |
||||
|
||||
|
||||
/**@}*/ |
||||
|
||||
/**\name Projection decoder functions */ |
||||
/**@{*/ |
||||
|
||||
/** Gets the size of an <code>OpusProjectionDecoder</code> structure.
|
||||
* @param channels <tt>int</tt>: The total number of output channels. |
||||
* This must be no more than 255. |
||||
* @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_projection_decoder_get_size( |
||||
int channels, |
||||
int streams, |
||||
int coupled_streams |
||||
); |
||||
|
||||
|
||||
/** Allocates and initializes a projection decoder state.
|
||||
* Call opus_projection_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] demixing_matrix <tt>const unsigned char[demixing_matrix_size]</tt>: Demixing matrix |
||||
* that mapping from coded channels to output channels, |
||||
* as described in @ref opus_projection and |
||||
* @ref opus_projection_ctls. |
||||
* @param demixing_matrix_size <tt>opus_int32</tt>: The size in bytes of the |
||||
* demixing matrix, as |
||||
* described in @ref |
||||
* opus_projection_ctls. |
||||
* @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 OpusProjectionDecoder *opus_projection_decoder_create( |
||||
opus_int32 Fs, |
||||
int channels, |
||||
int streams, |
||||
int coupled_streams, |
||||
unsigned char *demixing_matrix, |
||||
opus_int32 demixing_matrix_size, |
||||
int *error |
||||
) OPUS_ARG_NONNULL(5); |
||||
|
||||
|
||||
/** Initialize a previously allocated projection decoder state object.
|
||||
* The memory pointed to by \a st must be at least the size returned by |
||||
* opus_projection_decoder_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_projection_decoder_create |
||||
* @see opus_projection_deocder_get_size |
||||
* @param st <tt>OpusProjectionDecoder*</tt>: Projection 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] demixing_matrix <tt>const unsigned char[demixing_matrix_size]</tt>: Demixing matrix |
||||
* that mapping from coded channels to output channels, |
||||
* as described in @ref opus_projection and |
||||
* @ref opus_projection_ctls. |
||||
* @param demixing_matrix_size <tt>opus_int32</tt>: The size in bytes of the |
||||
* demixing matrix, as |
||||
* described in @ref |
||||
* opus_projection_ctls. |
||||
* @returns #OPUS_OK on success, or an error code (see @ref opus_errorcodes) |
||||
* on failure. |
||||
*/ |
||||
OPUS_EXPORT int opus_projection_decoder_init( |
||||
OpusProjectionDecoder *st, |
||||
opus_int32 Fs, |
||||
int channels, |
||||
int streams, |
||||
int coupled_streams, |
||||
unsigned char *demixing_matrix, |
||||
opus_int32 demixing_matrix_size |
||||
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(6); |
||||
|
||||
|
||||
/** Decode a projection Opus packet.
|
||||
* @param st <tt>OpusProjectionDecoder*</tt>: Projection 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_projection_decode( |
||||
OpusProjectionDecoder *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 projection Opus packet.
|
||||
* @param st <tt>OpusProjectionDecoder*</tt>: Projection 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_int32*</tt>: Output signal, with interleaved |
||||
* samples representing (or slightly exceeding) 24-bit values. |
||||
* 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_projection_decode24( |
||||
OpusProjectionDecoder *st, |
||||
const unsigned char *data, |
||||
opus_int32 len, |
||||
opus_int32 *pcm, |
||||
int frame_size, |
||||
int decode_fec |
||||
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4); |
||||
|
||||
/** Decode a projection Opus packet with floating point output.
|
||||
* @param st <tt>OpusProjectionDecoder*</tt>: Projection 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_projection_decode_float( |
||||
OpusProjectionDecoder *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 projection Opus decoder.
|
||||
* |
||||
* Generally the request and subsequent arguments are generated by a |
||||
* convenience macro. |
||||
* @param st <tt>OpusProjectionDecoder*</tt>: Projection 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, @ref opus_multistream_ctls, or |
||||
* @ref opus_projection_ctls. |
||||
* @see opus_genericctls |
||||
* @see opus_decoderctls |
||||
* @see opus_multistream_ctls |
||||
* @see opus_projection_ctls |
||||
*/ |
||||
OPUS_EXPORT int opus_projection_decoder_ctl(OpusProjectionDecoder *st, int request, ...) OPUS_ARG_NONNULL(1); |
||||
|
||||
|
||||
/** Frees an <code>OpusProjectionDecoder</code> allocated by
|
||||
* opus_projection_decoder_create(). |
||||
* @param st <tt>OpusProjectionDecoder</tt>: Projection decoder state to be freed. |
||||
*/ |
||||
OPUS_EXPORT void opus_projection_decoder_destroy(OpusProjectionDecoder *st); |
||||
|
||||
|
||||
/**@}*/ |
||||
|
||||
/**@}*/ |
||||
|
||||
#ifdef __cplusplus |
||||
} |
||||
#endif |
||||
|
||||
#endif /* OPUS_PROJECTION_H */ |
||||
@ -0,0 +1,166 @@
|
||||
/* (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 |
||||
|
||||
#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 |
||||
|
||||
/* Use the real stdint.h if it's there (taken from Paul Hsieh's pstdint.h) */ |
||||
#if (defined(__STDC__) && __STDC__ && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || (defined(__GNUC__) && (defined(_STDINT_H) || defined(_STDINT_H_)) || defined (HAVE_STDINT_H)) |
||||
#include <stdint.h> |
||||
# undef opus_int64 |
||||
# undef opus_int8 |
||||
# undef opus_uint64 |
||||
# undef opus_uint8 |
||||
typedef int8_t opus_int8; |
||||
typedef uint8_t opus_uint8; |
||||
typedef int16_t opus_int16; |
||||
typedef uint16_t opus_uint16; |
||||
typedef int32_t opus_int32; |
||||
typedef uint32_t opus_uint32; |
||||
typedef int64_t opus_int64; |
||||
typedef uint64_t opus_uint64; |
||||
#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 |
||||
|
||||
#endif /* OPUS_TYPES_H */ |
||||
@ -0,0 +1,8 @@
|
||||
#ifndef OPUS_CONFIG_H |
||||
#define OPUS_CONFIG_H |
||||
|
||||
#define OPUS_BUILD 1 |
||||
#define VAR_ARRAYS 1 |
||||
#define USE_ALLOCA 1 |
||||
|
||||
#endif |
||||
@ -0,0 +1,267 @@
|
||||
/***********************************************************************
|
||||
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 16 |
||||
|
||||
/* Helper function for A2NLSF(..) */ |
||||
/* Transforms polynomials from cos(n*f) to cos(f)^n */ |
||||
static OPUS_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 OPUS_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 ); |
||||
|
||||
if ( opus_likely( 8 == dd ) ) |
||||
{ |
||||
y32 = silk_SMLAWW( p[ 7 ], y32, x_Q16 ); |
||||
y32 = silk_SMLAWW( p[ 6 ], y32, x_Q16 ); |
||||
y32 = silk_SMLAWW( p[ 5 ], y32, x_Q16 ); |
||||
y32 = silk_SMLAWW( p[ 4 ], y32, x_Q16 ); |
||||
y32 = silk_SMLAWW( p[ 3 ], y32, x_Q16 ); |
||||
y32 = silk_SMLAWW( p[ 2 ], y32, x_Q16 ); |
||||
y32 = silk_SMLAWW( p[ 1 ], y32, x_Q16 ); |
||||
y32 = silk_SMLAWW( p[ 0 ], y32, x_Q16 ); |
||||
} |
||||
else |
||||
{ |
||||
for( n = dd - 1; n >= 0; n-- ) { |
||||
y32 = silk_SMLAWW( p[ n ], y32, x_Q16 ); /* Q16 */ |
||||
} |
||||
} |
||||
return y32; |
||||
} |
||||
|
||||
static OPUS_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_ADD16( NLSF[ k-1 ], NLSF[ 0 ] ); |
||||
} |
||||
return; |
||||
} |
||||
|
||||
/* Error: Apply progressively more bandwidth expansion and run again */ |
||||
silk_bwexpander_32( a_Q16, d, 65536 - silk_LSHIFT( 1, i ) ); |
||||
|
||||
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,150 @@
|
||||
/***********************************************************************
|
||||
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 ENABLE_DEEP_PLC |
||||
#include "lpcnet_private.h" |
||||
#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 */ |
||||
opus_int channels /* I Number of channels */ |
||||
); |
||||
|
||||
/*************************/ |
||||
/* Init or reset encoder */ |
||||
/*************************/ |
||||
opus_int silk_InitEncoder( /* O Returns error code */ |
||||
void *encState, /* I/O State */ |
||||
int channels, /* I Number of channels */ |
||||
int arch, /* I Run-time architecture */ |
||||
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_res *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 */ |
||||
int activity /* I Decision of Opus voice activity detector */ |
||||
); |
||||
|
||||
/****************************************/ |
||||
/* Decoder functions */ |
||||
/****************************************/ |
||||
|
||||
|
||||
/***********************************************/ |
||||
/* Load OSCE models from external data pointer */ |
||||
/***********************************************/ |
||||
opus_int silk_LoadOSCEModels( |
||||
void *decState, /* O I/O State */ |
||||
const unsigned char *data, /* I pointer to binary blob */ |
||||
int len /* I length of binary blob data */ |
||||
); |
||||
|
||||
/***********************************************/ |
||||
/* 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 and Reset decoder */ |
||||
/*************************/ |
||||
opus_int silk_ResetDecoder( /* O Returns error code */ |
||||
void *decState /* I/O State */ |
||||
); |
||||
|
||||
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_res *samplesOut, /* O Decoded output speech vector */ |
||||
opus_int32 *nSamplesOut, /* O Number of samples decoded */ |
||||
#ifdef ENABLE_DEEP_PLC |
||||
LPCNetPLCState *lpcnet, |
||||
#endif |
||||
int arch /* I Run-time architecture */ |
||||
); |
||||
|
||||
#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 |
||||
|
||||
|
||||
#endif |
||||
@ -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. |
||||
***********************************************************************/ |
||||
|
||||
#ifdef HAVE_CONFIG_H |
||||
#include "config.h" |
||||
#endif |
||||
|
||||
#include "main.h" |
||||
#include "stack_alloc.h" |
||||
|
||||
/* Generates excitation for CNG LPC synthesis */ |
||||
static OPUS_INLINE void silk_CNG_exc( |
||||
opus_int32 exc_Q14[], /* O CNG excitation signal Q10 */ |
||||
opus_int32 exc_buf_Q14[], /* I Random samples buffer Q10 */ |
||||
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 ); |
||||
exc_Q14[ i ] = exc_buf_Q14[ idx ]; |
||||
} |
||||
*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 LPC_pred_Q10, max_Gain_Q16, gain_Q16, gain_Q10; |
||||
opus_int16 A_Q12[ MAX_LPC_ORDER ]; |
||||
silk_CNG_struct *psCNG = &psDec->sCNG; |
||||
SAVE_STACK; |
||||
|
||||
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 ); |
||||
/* If the smoothed gain is 3 dB greater than this subframe's gain, use this subframe's gain to adapt faster. */ |
||||
if( silk_SMULWW( psCNG->CNG_smth_Gain_Q16, CNG_GAIN_SMTH_THRESHOLD_Q16 ) > psDecCtrl->Gains_Q16[ i ] ) { |
||||
psCNG->CNG_smth_Gain_Q16 = psDecCtrl->Gains_Q16[ i ]; |
||||
} |
||||
} |
||||
} |
||||
|
||||
/* Add CNG when packet is lost or during DTX */ |
||||
if( psDec->lossCnt ) { |
||||
VARDECL( opus_int32, CNG_sig_Q14 ); |
||||
ALLOC( CNG_sig_Q14, length + MAX_LPC_ORDER, opus_int32 ); |
||||
|
||||
/* Generate CNG excitation */ |
||||
gain_Q16 = silk_SMULWW( psDec->sPLC.randScale_Q14, psDec->sPLC.prevGain_Q16[1] ); |
||||
if( gain_Q16 >= (1 << 21) || psCNG->CNG_smth_Gain_Q16 > (1 << 23) ) { |
||||
gain_Q16 = silk_SMULTT( gain_Q16, gain_Q16 ); |
||||
gain_Q16 = silk_SUB_LSHIFT32(silk_SMULTT( psCNG->CNG_smth_Gain_Q16, psCNG->CNG_smth_Gain_Q16 ), gain_Q16, 5 ); |
||||
gain_Q16 = silk_LSHIFT32( silk_SQRT_APPROX( gain_Q16 ), 16 ); |
||||
} else { |
||||
gain_Q16 = silk_SMULWW( gain_Q16, gain_Q16 ); |
||||
gain_Q16 = silk_SUB_LSHIFT32(silk_SMULWW( psCNG->CNG_smth_Gain_Q16, psCNG->CNG_smth_Gain_Q16 ), gain_Q16, 5 ); |
||||
gain_Q16 = silk_LSHIFT32( silk_SQRT_APPROX( gain_Q16 ), 8 ); |
||||
} |
||||
gain_Q10 = silk_RSHIFT( gain_Q16, 6 ); |
||||
|
||||
silk_CNG_exc( CNG_sig_Q14 + MAX_LPC_ORDER, psCNG->CNG_exc_buf_Q14, length, &psCNG->rand_seed ); |
||||
|
||||
/* Convert CNG NLSF to filter representation */ |
||||
silk_NLSF2A( A_Q12, psCNG->CNG_smth_NLSF_Q15, psDec->LPC_order, psDec->arch ); |
||||
|
||||
/* Generate CNG signal, by synthesis filtering */ |
||||
silk_memcpy( CNG_sig_Q14, psCNG->CNG_synth_state, MAX_LPC_ORDER * sizeof( opus_int32 ) ); |
||||
celt_assert( psDec->LPC_order == 10 || psDec->LPC_order == 16 ); |
||||
for( i = 0; i < length; i++ ) { |
||||
/* 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, CNG_sig_Q14[ MAX_LPC_ORDER + i - 1 ], A_Q12[ 0 ] ); |
||||
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 2 ], A_Q12[ 1 ] ); |
||||
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 3 ], A_Q12[ 2 ] ); |
||||
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 4 ], A_Q12[ 3 ] ); |
||||
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 5 ], A_Q12[ 4 ] ); |
||||
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 6 ], A_Q12[ 5 ] ); |
||||
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 7 ], A_Q12[ 6 ] ); |
||||
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 8 ], A_Q12[ 7 ] ); |
||||
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 9 ], A_Q12[ 8 ] ); |
||||
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 10 ], A_Q12[ 9 ] ); |
||||
if( psDec->LPC_order == 16 ) { |
||||
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 11 ], A_Q12[ 10 ] ); |
||||
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 12 ], A_Q12[ 11 ] ); |
||||
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 13 ], A_Q12[ 12 ] ); |
||||
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 14 ], A_Q12[ 13 ] ); |
||||
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 15 ], A_Q12[ 14 ] ); |
||||
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 16 ], A_Q12[ 15 ] ); |
||||
} |
||||
|
||||
/* Update states */ |
||||
CNG_sig_Q14[ MAX_LPC_ORDER + i ] = silk_ADD_SAT32( CNG_sig_Q14[ MAX_LPC_ORDER + i ], silk_LSHIFT_SAT32( LPC_pred_Q10, 4 ) ); |
||||
|
||||
/* Scale with Gain and add to input signal */ |
||||
frame[ i ] = (opus_int16)silk_ADD_SAT16( frame[ i ], silk_SAT16( silk_RSHIFT_ROUND( silk_SMULWW( CNG_sig_Q14[ MAX_LPC_ORDER + i ], gain_Q10 ), 8 ) ) ); |
||||
|
||||
} |
||||
silk_memcpy( psCNG->CNG_synth_state, &CNG_sig_Q14[ length ], MAX_LPC_ORDER * sizeof( opus_int32 ) ); |
||||
} else { |
||||
silk_memset( psCNG->CNG_synth_state, 0, psDec->LPC_order * sizeof( opus_int32 ) ); |
||||
} |
||||
RESTORE_STACK; |
||||
} |
||||
@ -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,180 @@
|
||||
/***********************************************************************
|
||||
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 OPUS_INLINE signal processing functions. |
||||
*/ |
||||
|
||||
#ifndef SILK_FIX_INLINES_H |
||||
#define SILK_FIX_INLINES_H |
||||
|
||||
|
||||
/* count leading zeros of opus_int64 */ |
||||
static OPUS_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 OPUS_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 OPUS_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 OPUS_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 OPUS_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; |
||||
} |
||||
} |
||||
} |
||||
|
||||
#endif /* SILK_FIX_INLINES_H */ |
||||
@ -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 "SigProc_FIX.h" |
||||
#include "celt_lpc.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 */ |
||||
/*******************************************/ |
||||
|
||||
/* OPT: Using celt_fir() for this function should be faster, but it may cause
|
||||
integer overflows in intermediate values (not final results), which the |
||||
current implementation silences by casting to unsigned. Enabling |
||||
this should be safe in pretty much all cases, even though it is not technically |
||||
C89-compliant. */ |
||||
#define USE_CELT_FIR 0 |
||||
|
||||
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 */ |
||||
int arch /* I Run-time architecture */ |
||||
) |
||||
{ |
||||
opus_int j; |
||||
#if defined(FIXED_POINT) && USE_CELT_FIR |
||||
opus_int16 num[SILK_MAX_ORDER_LPC]; |
||||
#else |
||||
int ix; |
||||
opus_int32 out32_Q12, out32; |
||||
const opus_int16 *in_ptr; |
||||
#endif |
||||
|
||||
celt_assert( d >= 6 ); |
||||
celt_assert( (d & 1) == 0 ); |
||||
celt_assert( d <= len ); |
||||
|
||||
#if defined(FIXED_POINT) && USE_CELT_FIR |
||||
celt_assert( d <= SILK_MAX_ORDER_LPC ); |
||||
for ( j = 0; j < d; j++ ) { |
||||
num[ j ] = -B[ j ]; |
||||
} |
||||
celt_fir( in + d, num, out + d, len - d, d, arch ); |
||||
for ( j = 0; j < d; j++ ) { |
||||
out[ j ] = 0; |
||||
} |
||||
#else |
||||
(void)arch; |
||||
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 ) ); |
||||
#endif |
||||
} |
||||
@ -0,0 +1,82 @@
|
||||
/***********************************************************************
|
||||
Copyright (c) 2013, Koen Vos. 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" |
||||
|
||||
/* Convert int32 coefficients to int16 coefs and make sure there's no wrap-around.
|
||||
This logic is reused in _celt_lpc(). Any bug fixes should also be applied there. */ |
||||
void silk_LPC_fit( |
||||
opus_int16 *a_QOUT, /* O Output signal */ |
||||
opus_int32 *a_QIN, /* I/O Input signal */ |
||||
const opus_int QOUT, /* I Input Q domain */ |
||||
const opus_int QIN, /* I Input Q domain */ |
||||
const opus_int d /* I Filter order */ |
||||
) |
||||
{ |
||||
opus_int i, k, idx = 0; |
||||
opus_int32 maxabs, absval, chirp_Q16; |
||||
|
||||
/* 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( a_QIN[k] ); |
||||
if( absval > maxabs ) { |
||||
maxabs = absval; |
||||
idx = k; |
||||
} |
||||
} |
||||
maxabs = silk_RSHIFT_ROUND( maxabs, QIN - QOUT ); |
||||
|
||||
if( maxabs > silk_int16_MAX ) { |
||||
/* Reduce magnitude of prediction coefficients */ |
||||
maxabs = silk_min( maxabs, 163838 ); /* ( silk_int32_MAX >> 14 ) + silk_int16_MAX = 163838 */ |
||||
chirp_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( a_QIN, d, chirp_Q16 ); |
||||
} else { |
||||
break; |
||||
} |
||||
} |
||||
|
||||
if( i == 10 ) { |
||||
/* Reached the last iteration, clip the coefficients */ |
||||
for( k = 0; k < d; k++ ) { |
||||
a_QOUT[ k ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( a_QIN[ k ], QIN - QOUT ) ); |
||||
a_QIN[ k ] = silk_LSHIFT( (opus_int32)a_QOUT[ k ], QIN - QOUT ); |
||||
} |
||||
} else { |
||||
for( k = 0; k < d; k++ ) { |
||||
a_QOUT[ k ] = (opus_int16)silk_RSHIFT_ROUND( a_QIN[ k ], QIN - QOUT ); |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,141 @@
|
||||
/***********************************************************************
|
||||
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" |
||||
#include "define.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_c( /* O Returns inverse prediction gain in energy domain, Q30 */ |
||||
opus_int32 A_QA[ 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, tmp1, tmp2; |
||||
|
||||
invGain_Q30 = SILK_FIX_CONST( 1, 30 ); |
||||
for( k = order - 1; k > 0; k-- ) { |
||||
/* Check for stability */ |
||||
if( ( A_QA[ k ] > A_LIMIT ) || ( A_QA[ k ] < -A_LIMIT ) ) { |
||||
return 0; |
||||
} |
||||
|
||||
/* Set RC equal to negated AR coef */ |
||||
rc_Q31 = -silk_LSHIFT( A_QA[ k ], 31 - QA ); |
||||
|
||||
/* rc_mult1_Q30 range: [ 1 : 2^30 ] */ |
||||
rc_mult1_Q30 = silk_SUB32( SILK_FIX_CONST( 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 ) ); |
||||
|
||||
/* 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 ) ); |
||||
if( invGain_Q30 < SILK_FIX_CONST( 1.0f / MAX_PREDICTION_POWER_GAIN, 30 ) ) { |
||||
return 0; |
||||
} |
||||
|
||||
/* 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 AR coefficient */ |
||||
for( n = 0; n < (k + 1) >> 1; n++ ) { |
||||
opus_int64 tmp64; |
||||
tmp1 = A_QA[ n ]; |
||||
tmp2 = A_QA[ k - n - 1 ]; |
||||
tmp64 = silk_RSHIFT_ROUND64( silk_SMULL( silk_SUB_SAT32(tmp1, |
||||
MUL32_FRAC_Q( tmp2, rc_Q31, 31 ) ), rc_mult2 ), mult2Q); |
||||
if( tmp64 > silk_int32_MAX || tmp64 < silk_int32_MIN ) { |
||||
return 0; |
||||
} |
||||
A_QA[ n ] = ( opus_int32 )tmp64; |
||||
tmp64 = silk_RSHIFT_ROUND64( silk_SMULL( silk_SUB_SAT32(tmp2, |
||||
MUL32_FRAC_Q( tmp1, rc_Q31, 31 ) ), rc_mult2), mult2Q); |
||||
if( tmp64 > silk_int32_MAX || tmp64 < silk_int32_MIN ) { |
||||
return 0; |
||||
} |
||||
A_QA[ k - n - 1 ] = ( opus_int32 )tmp64; |
||||
} |
||||
} |
||||
|
||||
/* Check for stability */ |
||||
if( ( A_QA[ k ] > A_LIMIT ) || ( A_QA[ k ] < -A_LIMIT ) ) { |
||||
return 0; |
||||
} |
||||
|
||||
/* Set RC equal to negated AR coef */ |
||||
rc_Q31 = -silk_LSHIFT( A_QA[ 0 ], 31 - QA ); |
||||
|
||||
/* Range: [ 1 : 2^30 ] */ |
||||
rc_mult1_Q30 = silk_SUB32( SILK_FIX_CONST( 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 ) ); |
||||
if( invGain_Q30 < SILK_FIX_CONST( 1.0f / MAX_PREDICTION_POWER_GAIN, 30 ) ) { |
||||
return 0; |
||||
} |
||||
|
||||
return invGain_Q30; |
||||
} |
||||
|
||||
/* For input in Q12 domain */ |
||||
opus_int32 silk_LPC_inverse_pred_gain_c( /* 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[ SILK_MAX_ORDER_LPC ]; |
||||
opus_int32 DC_resp = 0; |
||||
|
||||
/* Increase Q domain of the AR coefficients */ |
||||
for( k = 0; k < order; k++ ) { |
||||
DC_resp += (opus_int32)A_Q12[ k ]; |
||||
Atmp_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_c( Atmp_QA, order ); |
||||
} |
||||
@ -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 OPUS_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_stride1( frame, B_Q28, A_Q28, psLP->In_LP_State, frame, frame_length); |
||||
} |
||||
} |
||||
@ -0,0 +1,709 @@
|
||||
/***********************************************************************
|
||||
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 |
||||
|
||||
#ifdef silk_MACRO_COUNT |
||||
#include <stdio.h> |
||||
#define varDefine opus_int64 ops_count = 0; |
||||
|
||||
extern opus_int64 ops_count; |
||||
|
||||
static OPUS_INLINE opus_int64 silk_SaveCount(){ |
||||
return(ops_count); |
||||
} |
||||
|
||||
static OPUS_INLINE opus_int64 silk_SaveResetCount(){ |
||||
opus_int64 ret; |
||||
|
||||
ret = ops_count; |
||||
ops_count = 0; |
||||
return(ret); |
||||
} |
||||
|
||||
static OPUS_INLINE silk_PrintCount(){ |
||||
printf("ops_count = %d \n ", (opus_int32)ops_count); |
||||
} |
||||
|
||||
#undef silk_MUL |
||||
static OPUS_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 OPUS_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 OPUS_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 OPUS_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 OPUS_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 OPUS_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 OPUS_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 OPUS_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 OPUS_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 OPUS_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 OPUS_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 OPUS_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 OPUS_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 OPUS_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 OPUS_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 OPUS_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 OPUS_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 OPUS_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 OPUS_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 OPUS_INLINE opus_int32 silk_DIV32(opus_int32 a32, opus_int32 b32){ |
||||
ops_count += 64; |
||||
return a32 / b32; |
||||
} |
||||
|
||||
#undef silk_DIV32_16 |
||||
static OPUS_INLINE opus_int32 silk_DIV32_16(opus_int32 a32, opus_int32 b32){ |
||||
ops_count += 32; |
||||
return a32 / b32; |
||||
} |
||||
|
||||
#undef silk_SAT8 |
||||
static OPUS_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 OPUS_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 OPUS_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 OPUS_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 OPUS_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 OPUS_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 OPUS_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_LSHIFT8 |
||||
static OPUS_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 OPUS_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 OPUS_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 OPUS_INLINE opus_int64 silk_LSHIFT64(opus_int64 a, opus_int shift){ |
||||
ops_count += 1; |
||||
return a << shift; |
||||
} |
||||
|
||||
#undef silk_LSHIFT_ovflw |
||||
static OPUS_INLINE opus_int32 silk_LSHIFT_ovflw(opus_int32 a, opus_int32 shift){ |
||||
ops_count += 1; |
||||
return a << shift; |
||||
} |
||||
|
||||
#undef silk_LSHIFT_uint |
||||
static OPUS_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 OPUS_INLINE opus_int8 silk_RSHIFT8(opus_int8 a, opus_int32 shift){ |
||||
ops_count += 1; |
||||
return a >> shift; |
||||
} |
||||
#undef silk_RSHIFT16 |
||||
static OPUS_INLINE opus_int16 silk_RSHIFT16(opus_int16 a, opus_int32 shift){ |
||||
ops_count += 1; |
||||
return a >> shift; |
||||
} |
||||
#undef silk_RSHIFT32 |
||||
static OPUS_INLINE opus_int32 silk_RSHIFT32(opus_int32 a, opus_int32 shift){ |
||||
ops_count += 1; |
||||
return a >> shift; |
||||
} |
||||
#undef silk_RSHIFT64 |
||||
static OPUS_INLINE opus_int64 silk_RSHIFT64(opus_int64 a, opus_int64 shift){ |
||||
ops_count += 1; |
||||
return a >> shift; |
||||
} |
||||
|
||||
#undef silk_RSHIFT_uint |
||||
static OPUS_INLINE opus_uint32 silk_RSHIFT_uint(opus_uint32 a, opus_int32 shift){ |
||||
ops_count += 1; |
||||
return a >> shift; |
||||
} |
||||
|
||||
#undef silk_ADD_LSHIFT |
||||
static OPUS_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 OPUS_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 OPUS_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 OPUS_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 OPUS_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 OPUS_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 OPUS_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 OPUS_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 OPUS_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 OPUS_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 OPUS_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 OPUS_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 OPUS_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 OPUS_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 OPUS_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 OPUS_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 OPUS_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 OPUS_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 OPUS_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 OPUS_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 OPUS_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 OPUS_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 OPUS_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 OPUS_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 OPUS_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 OPUS_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 OPUS_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 OPUS_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 OPUS_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 OPUS_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 OPUS_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 OPUS_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 OPUS_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 OPUS_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 OPUS_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 OPUS_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 OPUS_INLINE opus_int32 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,945 @@
|
||||
/***********************************************************************
|
||||
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 OPUS_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 OPUS_INLINE opus_int32 silk_ADD32_(opus_int32 a, opus_int32 b, char *file, int line){ |
||||
opus_int32 ret; |
||||
|
||||
ret = (opus_int32)((opus_uint32)a + (opus_uint32)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 OPUS_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 OPUS_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 OPUS_INLINE opus_int32 silk_SUB32_(opus_int32 a, opus_int32 b, char *file, int line){ |
||||
opus_int64 ret; |
||||
|
||||
ret = a - (opus_int64)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 OPUS_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 OPUS_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 OPUS_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 OPUS_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 OPUS_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 OPUS_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 OPUS_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 OPUS_INLINE opus_int32 silk_MUL_(opus_int32 a32, opus_int32 b32, char *file, int line){ |
||||
opus_int32 ret; |
||||
opus_int64 ret64; |
||||
ret = (opus_int32)((opus_uint32)a32 * (opus_uint32)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 OPUS_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 OPUS_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 OPUS_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 OPUS_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 OPUS_INLINE opus_int32 silk_SMLAWB_(opus_int32 a32, opus_int32 b32, opus_int32 c32, char *file, int line){ |
||||
opus_int32 ret; |
||||
ret = silk_ADD32_ovflw( a32, silk_SMULWB( b32, c32 ) ); |
||||
if ( ret != 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 OPUS_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 OPUS_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 OPUS_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 OPUS_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 OPUS_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 OPUS_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 OPUS_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_SMULWW(%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 OPUS_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; |
||||
} |
||||
|
||||
/* 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 OPUS_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 OPUS_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 */ |
||||
|
||||
#undef silk_LSHIFT8 |
||||
#define silk_LSHIFT8(a,b) silk_LSHIFT8_((a), (b), __FILE__, __LINE__) |
||||
static OPUS_INLINE opus_int8 silk_LSHIFT8_(opus_int8 a, opus_int32 shift, char *file, int line){ |
||||
opus_int8 ret; |
||||
int fail = 0; |
||||
ret = (opus_int8)((opus_uint8)a << shift); |
||||
fail |= shift < 0; |
||||
fail |= shift >= 8; |
||||
fail |= (opus_int64)ret != (opus_int64)(((opus_uint64)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 OPUS_INLINE opus_int16 silk_LSHIFT16_(opus_int16 a, opus_int32 shift, char *file, int line){ |
||||
opus_int16 ret; |
||||
int fail = 0; |
||||
ret = (opus_int16)((opus_uint16)a << shift); |
||||
fail |= shift < 0; |
||||
fail |= shift >= 16; |
||||
fail |= (opus_int64)ret != (opus_int64)(((opus_uint64)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 OPUS_INLINE opus_int32 silk_LSHIFT32_(opus_int32 a, opus_int32 shift, char *file, int line){ |
||||
opus_int32 ret; |
||||
int fail = 0; |
||||
ret = (opus_int32)((opus_uint32)a << shift); |
||||
fail |= shift < 0; |
||||
fail |= shift >= 32; |
||||
fail |= (opus_int64)ret != (opus_int64)(((opus_uint64)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 OPUS_INLINE opus_int64 silk_LSHIFT64_(opus_int64 a, opus_int shift, char *file, int line){ |
||||
opus_int64 ret; |
||||
int fail = 0; |
||||
ret = (opus_int64)((opus_uint64)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 OPUS_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 OPUS_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 OPUS_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 OPUS_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 OPUS_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 OPUS_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 OPUS_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 OPUS_INLINE int silk_ADD_LSHIFT_(int a, int b, int shift, char *file, int line){ |
||||
opus_int16 ret; |
||||
ret = a + (opus_int16)((opus_uint16)b << shift); |
||||
if ( (shift < 0) || (shift>15) || ((opus_int64)ret != (opus_int64)a + (opus_int64)(((opus_uint64)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 OPUS_INLINE opus_int32 silk_ADD_LSHIFT32_(opus_int32 a, opus_int32 b, opus_int32 shift, char *file, int line){ |
||||
opus_int32 ret; |
||||
ret = silk_ADD32_ovflw(a, (opus_int32)((opus_uint32)b << shift)); |
||||
if ( (shift < 0) || (shift>31) || ((opus_int64)ret != (opus_int64)a + (opus_int64)(((opus_uint64)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 OPUS_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 OPUS_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 OPUS_INLINE opus_int32 silk_ADD_RSHIFT32_(opus_int32 a, opus_int32 b, opus_int32 shift, char *file, int line){ |
||||
opus_int32 ret; |
||||
ret = silk_ADD32_ovflw(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 OPUS_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 OPUS_INLINE opus_int32 silk_SUB_LSHIFT32_(opus_int32 a, opus_int32 b, opus_int32 shift, char *file, int line){ |
||||
opus_int32 ret; |
||||
ret = silk_SUB32_ovflw(a, (opus_int32)((opus_uint32)b << shift)); |
||||
if ( (shift < 0) || (shift>31) || ((opus_int64)ret != (opus_int64)a - (opus_int64)(((opus_uint64)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 OPUS_INLINE opus_int32 silk_SUB_RSHIFT32_(opus_int32 a, opus_int32 b, opus_int32 shift, char *file, int line){ |
||||
opus_int32 ret; |
||||
ret = silk_SUB32_ovflw(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 OPUS_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 macro 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 OPUS_INLINE opus_int64 silk_RSHIFT_ROUND64_(opus_int64 a, opus_int32 shift, char *file, int line){ |
||||
opus_int64 ret; |
||||
/* the macro 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 OPUS_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 OPUS_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 OPUS_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 OPUS_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 OPUS_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 OPUS_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,140 @@
|
||||
/***********************************************************************
|
||||
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 OPUS_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) */ |
||||
int arch /* I Run-time architecture */ |
||||
) |
||||
{ |
||||
/* 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 ]; |
||||
|
||||
silk_assert( LSF_COS_TAB_SZ_FIX == 128 ); |
||||
celt_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 */ |
||||
} |
||||
|
||||
/* Convert int32 coefficients to Q12 int16 coefs */ |
||||
silk_LPC_fit( a_Q12, a32_QA1, 12, QA + 1, d ); |
||||
|
||||
for( i = 0; silk_LPC_inverse_pred_gain( a_Q12, d, arch ) == 0 && i < MAX_LPC_STABILIZE_ITERATIONS; i++ ) { |
||||
/* 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 */ |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,76 @@
|
||||
/***********************************************************************
|
||||
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_Q24[], /* 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_int16 pWght_Q9[], /* I Codebook weights [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, diffw_Q24, sum_error_Q24, pred_Q24; |
||||
const opus_int16 *w_Q9_ptr; |
||||
const opus_uint8 *cb_Q8_ptr; |
||||
|
||||
celt_assert( ( LPC_order & 1 ) == 0 ); |
||||
|
||||
/* Loop over codebook */ |
||||
cb_Q8_ptr = pCB_Q8; |
||||
w_Q9_ptr = pWght_Q9; |
||||
for( i = 0; i < K; i++ ) { |
||||
sum_error_Q24 = 0; |
||||
pred_Q24 = 0; |
||||
for( m = LPC_order-2; m >= 0; m -= 2 ) { |
||||
/* Compute weighted absolute predictive quantization error for index m + 1 */ |
||||
diff_Q15 = silk_SUB_LSHIFT32( in_Q15[ m + 1 ], (opus_int32)cb_Q8_ptr[ m + 1 ], 7 ); /* range: [ -32767 : 32767 ]*/ |
||||
diffw_Q24 = silk_SMULBB( diff_Q15, w_Q9_ptr[ m + 1 ] ); |
||||
sum_error_Q24 = silk_ADD32( sum_error_Q24, silk_abs( silk_SUB_RSHIFT32( diffw_Q24, pred_Q24, 1 ) ) ); |
||||
pred_Q24 = diffw_Q24; |
||||
|
||||
/* Compute weighted absolute predictive quantization error for index m */ |
||||
diff_Q15 = silk_SUB_LSHIFT32( in_Q15[ m ], (opus_int32)cb_Q8_ptr[ m ], 7 ); /* range: [ -32767 : 32767 ]*/ |
||||
diffw_Q24 = silk_SMULBB( diff_Q15, w_Q9_ptr[ m ] ); |
||||
sum_error_Q24 = silk_ADD32( sum_error_Q24, silk_abs( silk_SUB_RSHIFT32( diffw_Q24, pred_Q24, 1 ) ) ); |
||||
pred_Q24 = diffw_Q24; |
||||
|
||||
silk_assert( sum_error_Q24 >= 0 ); |
||||
} |
||||
err_Q24[ i ] = sum_error_Q24; |
||||
cb_Q8_ptr += LPC_order; |
||||
w_Q9_ptr += LPC_order; |
||||
} |
||||
} |
||||
@ -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; |
||||
|
||||
celt_assert( D > 0 ); |
||||
celt_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,93 @@
|
||||
/***********************************************************************
|
||||
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 OPUS_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_int32 NLSF_Q15_tmp; |
||||
const opus_uint8 *pCB_element; |
||||
const opus_int16 *pCB_Wght_Q9; |
||||
|
||||
/* 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 ); |
||||
|
||||
/* Apply inverse square-rooted weights to first stage and add to output */ |
||||
pCB_element = &psNLSF_CB->CB1_NLSF_Q8[ NLSFIndices[ 0 ] * psNLSF_CB->order ]; |
||||
pCB_Wght_Q9 = &psNLSF_CB->CB1_Wght_Q9[ NLSFIndices[ 0 ] * psNLSF_CB->order ]; |
||||
for( i = 0; i < psNLSF_CB->order; i++ ) { |
||||
NLSF_Q15_tmp = silk_ADD_LSHIFT32( silk_DIV32_16( silk_LSHIFT( (opus_int32)res_Q10[ i ], 14 ), pCB_Wght_Q9[ i ] ), (opus_int16)pCB_element[ i ], 7 ); |
||||
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,215 @@
|
||||
/***********************************************************************
|
||||
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, rate0_Q5, rate1_Q5; |
||||
opus_int16 out0_Q10, out1_Q10; |
||||
opus_int32 RD_tmp_Q25, min_Q25, min_max_Q25, max_min_Q25; |
||||
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; |
||||
|
||||
opus_int out0_Q10_table[2 * NLSF_QUANT_MAX_AMPLITUDE_EXT]; |
||||
opus_int out1_Q10_table[2 * NLSF_QUANT_MAX_AMPLITUDE_EXT]; |
||||
|
||||
for (i = -NLSF_QUANT_MAX_AMPLITUDE_EXT; i <= NLSF_QUANT_MAX_AMPLITUDE_EXT-1; i++) |
||||
{ |
||||
out0_Q10 = silk_LSHIFT( i, 10 ); |
||||
out1_Q10 = silk_ADD16( out0_Q10, 1024 ); |
||||
if( i > 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( i == 0 ) { |
||||
out1_Q10 = silk_SUB16( out1_Q10, SILK_FIX_CONST( NLSF_QUANT_LEVEL_ADJ, 10 ) ); |
||||
} else if( i == -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_table[ i + NLSF_QUANT_MAX_AMPLITUDE_EXT ] = silk_RSHIFT( silk_SMULBB( out0_Q10, quant_step_size_Q16 ), 16 ); |
||||
out1_Q10_table[ i + NLSF_QUANT_MAX_AMPLITUDE_EXT ] = silk_RSHIFT( silk_SMULBB( out1_Q10, quant_step_size_Q16 ), 16 ); |
||||
} |
||||
|
||||
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 >= 0; i-- ) { |
||||
rates_Q5 = &ec_rates_Q5[ ec_ix[ i ] ]; |
||||
in_Q10 = x_Q10[ i ]; |
||||
for( j = 0; j < nStates; j++ ) { |
||||
pred_Q10 = silk_RSHIFT( silk_SMULBB( (opus_int16)pred_coef_Q8[ i ], prev_out_Q10[ j ] ), 8 ); |
||||
res_Q10 = silk_SUB16( in_Q10, pred_Q10 ); |
||||
ind_tmp = silk_RSHIFT( silk_SMULBB( inv_quant_step_size_Q6, res_Q10 ), 16 ); |
||||
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 = out0_Q10_table[ ind_tmp + NLSF_QUANT_MAX_AMPLITUDE_EXT ]; |
||||
out1_Q10 = out1_Q10_table[ ind_tmp + NLSF_QUANT_MAX_AMPLITUDE_EXT ]; |
||||
|
||||
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/2 ) { |
||||
/* 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 { |
||||
/* 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 ); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/* 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,124 @@
|
||||
/***********************************************************************
|
||||
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" |
||||
|
||||
/***********************/ |
||||
/* 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 (Un)quantized NLSF vector [ LPC_ORDER ] */ |
||||
const silk_NLSF_CB_struct *psNLSF_CB, /* I Codebook object */ |
||||
const opus_int16 *pW_Q2, /* 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, ret; |
||||
VARDECL( opus_int32, err_Q24 ); |
||||
VARDECL( opus_int32, RD_Q25 ); |
||||
VARDECL( opus_int, tempIndices1 ); |
||||
VARDECL( opus_int8, tempIndices2 ); |
||||
opus_int16 res_Q10[ MAX_LPC_ORDER ]; |
||||
opus_int16 NLSF_tmp_Q15[ 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; |
||||
const opus_int16 *pCB_Wght_Q9; |
||||
SAVE_STACK; |
||||
|
||||
celt_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 */ |
||||
ALLOC( err_Q24, psNLSF_CB->nVectors, opus_int32 ); |
||||
silk_NLSF_VQ( err_Q24, pNLSF_Q15, psNLSF_CB->CB1_NLSF_Q8, psNLSF_CB->CB1_Wght_Q9, psNLSF_CB->nVectors, psNLSF_CB->order ); |
||||
|
||||
/* Sort the quantization errors */ |
||||
ALLOC( tempIndices1, nSurvivors, opus_int ); |
||||
silk_insertion_sort_increasing( err_Q24, tempIndices1, psNLSF_CB->nVectors, nSurvivors ); |
||||
|
||||
ALLOC( RD_Q25, nSurvivors, opus_int32 ); |
||||
ALLOC( tempIndices2, nSurvivors * MAX_LPC_ORDER, opus_int8 ); |
||||
|
||||
/* 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 ]; |
||||
pCB_Wght_Q9 = &psNLSF_CB->CB1_Wght_Q9[ ind1 * psNLSF_CB->order ]; |
||||
for( i = 0; i < psNLSF_CB->order; i++ ) { |
||||
NLSF_tmp_Q15[ i ] = silk_LSHIFT16( (opus_int16)pCB_element[ i ], 7 ); |
||||
W_tmp_Q9 = pCB_Wght_Q9[ i ]; |
||||
res_Q10[ i ] = (opus_int16)silk_RSHIFT( silk_SMULBB( pNLSF_Q15[ i ] - NLSF_tmp_Q15[ i ], W_tmp_Q9 ), 14 ); |
||||
W_adj_Q5[ i ] = silk_DIV32_varQ( (opus_int32)pW_Q2[ i ], silk_SMULBB( W_tmp_Q9, W_tmp_Q9 ), 21 ); |
||||
} |
||||
|
||||
/* 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 ); |
||||
|
||||
ret = RD_Q25[ 0 ]; |
||||
RESTORE_STACK; |
||||
return ret; |
||||
} |
||||
@ -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], silk_ADD_SAT16( 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,54 @@
|
||||
/***********************************************************************
|
||||
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,437 @@
|
||||
/***********************************************************************
|
||||
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 "NSQ.h" |
||||
|
||||
|
||||
static OPUS_INLINE void silk_nsq_scale_states( |
||||
const silk_encoder_state *psEncC, /* I Encoder State */ |
||||
silk_nsq_state *NSQ, /* I/O NSQ state */ |
||||
const opus_int16 x16[], /* I input */ |
||||
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 */ |
||||
); |
||||
|
||||
#if !defined(OPUS_X86_MAY_HAVE_SSE4_1) |
||||
static OPUS_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 */ |
||||
int arch /* I Architecture */ |
||||
); |
||||
#endif |
||||
|
||||
void silk_NSQ_c |
||||
( |
||||
const silk_encoder_state *psEncC, /* I Encoder State */ |
||||
silk_nsq_state *NSQ, /* I/O NSQ state */ |
||||
SideInfoIndices *psIndices, /* I/O Quantization Indices */ |
||||
const opus_int16 x16[], /* I Input */ |
||||
opus_int8 pulses[], /* O Quantized pulse signal */ |
||||
const opus_int16 *PredCoef_Q12, /* I Short term prediction coefs */ |
||||
const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */ |
||||
const opus_int16 AR_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; |
||||
VARDECL( opus_int32, sLTP_Q15 ); |
||||
VARDECL( opus_int16, sLTP ); |
||||
opus_int32 HarmShapeFIRPacked_Q14; |
||||
opus_int offset_Q10; |
||||
VARDECL( opus_int32, x_sc_Q10 ); |
||||
SAVE_STACK; |
||||
|
||||
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; |
||||
} |
||||
|
||||
ALLOC( sLTP_Q15, psEncC->ltp_mem_length + psEncC->frame_length, opus_int32 ); |
||||
ALLOC( sLTP, psEncC->ltp_mem_length + psEncC->frame_length, opus_int16 ); |
||||
ALLOC( x_sc_Q10, psEncC->subfr_length, opus_int32 ); |
||||
/* 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 = &AR_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; |
||||
celt_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, psEncC->arch ); |
||||
|
||||
NSQ->rewhite_flag = 1; |
||||
NSQ->sLTP_buf_idx = psEncC->ltp_mem_length; |
||||
} |
||||
} |
||||
|
||||
silk_nsq_scale_states( psEncC, NSQ, x16, 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, psEncC->arch ); |
||||
|
||||
x16 += 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 */ |
||||
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 ) ); |
||||
RESTORE_STACK; |
||||
} |
||||
|
||||
/******************************/ |
||||
/* silk_noise_shape_quantizer */ |
||||
/******************************/ |
||||
|
||||
#if !defined(OPUS_X86_MAY_HAVE_SSE4_1) |
||||
static OPUS_INLINE |
||||
#endif |
||||
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 */ |
||||
int arch /* I Architecture */ |
||||
) |
||||
{ |
||||
opus_int i; |
||||
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; |
||||
#ifdef silk_short_prediction_create_arch_coef |
||||
opus_int32 a_Q12_arch[MAX_LPC_ORDER]; |
||||
#endif |
||||
|
||||
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 ]; |
||||
|
||||
#ifdef silk_short_prediction_create_arch_coef |
||||
silk_short_prediction_create_arch_coef(a_Q12_arch, a_Q12, predictLPCOrder); |
||||
#endif |
||||
|
||||
for( i = 0; i < length; i++ ) { |
||||
/* Generate dither */ |
||||
NSQ->rand_seed = silk_RAND( NSQ->rand_seed ); |
||||
|
||||
/* Short-term prediction */ |
||||
LPC_pred_Q10 = silk_noise_shape_quantizer_short_prediction(psLPC_Q14, a_Q12, a_Q12_arch, predictLPCOrder, arch); |
||||
|
||||
/* 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 */ |
||||
celt_assert( ( shapingLPCOrder & 1 ) == 0 ); /* check that order is even */ |
||||
n_AR_Q12 = silk_NSQ_noise_shape_feedback_loop(&NSQ->sDiff_shp_Q14, NSQ->sAR2_Q14, AR_shp_Q13, shapingLPCOrder, arch); |
||||
|
||||
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 ); |
||||
|
||||
celt_assert( lag > 0 || signalType != TYPE_VOICED ); |
||||
|
||||
/* Combine prediction and noise shaping signals */ |
||||
tmp1 = silk_SUB32_ovflw( silk_LSHIFT32( LPC_pred_Q10, 2 ), n_AR_Q12 ); /* Q12 */ |
||||
tmp1 = silk_SUB32_ovflw( tmp1, n_LF_Q12 ); /* Q12 */ |
||||
if( lag > 0 ) { |
||||
/* Symmetric, packed FIR coefficients */ |
||||
n_LTP_Q13 = silk_SMULWB( silk_ADD_SAT32( 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_ADD32_ovflw( tmp2, silk_LSHIFT32( 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 (Lambda_Q10 > 2048) { |
||||
/* For aggressive RDO, the bias becomes more than one pulse. */ |
||||
int rdo_offset = Lambda_Q10/2 - 512; |
||||
if (q1_Q10 > rdo_offset) { |
||||
q1_Q0 = silk_RSHIFT( q1_Q10 - rdo_offset, 10 ); |
||||
} else if (q1_Q10 < -rdo_offset) { |
||||
q1_Q0 = silk_RSHIFT( q1_Q10 + rdo_offset, 10 ); |
||||
} else if (q1_Q10 < 0) { |
||||
q1_Q0 = -1; |
||||
} else { |
||||
q1_Q0 = 0; |
||||
} |
||||
} |
||||
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_ADD32_ovflw( LPC_exc_Q14, silk_LSHIFT32( 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; |
||||
NSQ->sDiff_shp_Q14 = silk_SUB32_ovflw( xq_Q14, silk_LSHIFT32( x_sc_Q10[ i ], 4 ) ); |
||||
sLF_AR_shp_Q14 = silk_SUB32_ovflw( NSQ->sDiff_shp_Q14, silk_LSHIFT32( n_AR_Q12, 2 ) ); |
||||
NSQ->sLF_AR_shp_Q14 = sLF_AR_shp_Q14; |
||||
|
||||
NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx ] = silk_SUB32_ovflw(sLF_AR_shp_Q14, silk_LSHIFT32(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 OPUS_INLINE void silk_nsq_scale_states( |
||||
const silk_encoder_state *psEncC, /* I Encoder State */ |
||||
silk_nsq_state *NSQ, /* I/O NSQ state */ |
||||
const opus_int16 x16[], /* I input */ |
||||
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_Q26; |
||||
|
||||
lag = pitchL[ subfr ]; |
||||
inv_gain_Q31 = silk_INVERSE32_varQ( silk_max( Gains_Q16[ subfr ], 1 ), 47 ); |
||||
silk_assert( inv_gain_Q31 != 0 ); |
||||
|
||||
/* Scale input */ |
||||
inv_gain_Q26 = silk_RSHIFT_ROUND( inv_gain_Q31, 5 ); |
||||
for( i = 0; i < psEncC->subfr_length; i++ ) { |
||||
x_sc_Q10[ i ] = silk_SMULWW( x16[ i ], inv_gain_Q26 ); |
||||
} |
||||
|
||||
/* 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( Gains_Q16[ subfr ] != NSQ->prev_gain_Q16 ) { |
||||
gain_adj_Q16 = silk_DIV32_varQ( NSQ->prev_gain_Q16, Gains_Q16[ subfr ], 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 ); |
||||
NSQ->sDiff_shp_Q14 = silk_SMULWW( gain_adj_Q16, NSQ->sDiff_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 ] ); |
||||
} |
||||
|
||||
/* Save inverse gain */ |
||||
NSQ->prev_gain_Q16 = Gains_Q16[ subfr ]; |
||||
} |
||||
} |
||||
@ -0,0 +1,105 @@
|
||||
/***********************************************************************
|
||||
Copyright (c) 2014 Vidyo. |
||||
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_NSQ_H |
||||
#define SILK_NSQ_H |
||||
|
||||
#include "SigProc_FIX.h" |
||||
|
||||
#undef silk_short_prediction_create_arch_coef |
||||
|
||||
static OPUS_INLINE opus_int32 silk_noise_shape_quantizer_short_prediction_c(const opus_int32 *buf32, const opus_int16 *coef16, opus_int order) |
||||
{ |
||||
opus_int32 out; |
||||
silk_assert( order == 10 || order == 16 ); |
||||
|
||||
/* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */ |
||||
out = silk_RSHIFT( order, 1 ); |
||||
out = silk_SMLAWB( out, buf32[ 0 ], coef16[ 0 ] ); |
||||
out = silk_SMLAWB( out, buf32[ -1 ], coef16[ 1 ] ); |
||||
out = silk_SMLAWB( out, buf32[ -2 ], coef16[ 2 ] ); |
||||
out = silk_SMLAWB( out, buf32[ -3 ], coef16[ 3 ] ); |
||||
out = silk_SMLAWB( out, buf32[ -4 ], coef16[ 4 ] ); |
||||
out = silk_SMLAWB( out, buf32[ -5 ], coef16[ 5 ] ); |
||||
out = silk_SMLAWB( out, buf32[ -6 ], coef16[ 6 ] ); |
||||
out = silk_SMLAWB( out, buf32[ -7 ], coef16[ 7 ] ); |
||||
out = silk_SMLAWB( out, buf32[ -8 ], coef16[ 8 ] ); |
||||
out = silk_SMLAWB( out, buf32[ -9 ], coef16[ 9 ] ); |
||||
|
||||
if( order == 16 ) |
||||
{ |
||||
out = silk_SMLAWB( out, buf32[ -10 ], coef16[ 10 ] ); |
||||
out = silk_SMLAWB( out, buf32[ -11 ], coef16[ 11 ] ); |
||||
out = silk_SMLAWB( out, buf32[ -12 ], coef16[ 12 ] ); |
||||
out = silk_SMLAWB( out, buf32[ -13 ], coef16[ 13 ] ); |
||||
out = silk_SMLAWB( out, buf32[ -14 ], coef16[ 14 ] ); |
||||
out = silk_SMLAWB( out, buf32[ -15 ], coef16[ 15 ] ); |
||||
} |
||||
return out; |
||||
} |
||||
|
||||
#define silk_noise_shape_quantizer_short_prediction(in, coef, coefRev, order, arch) ((void)arch,silk_noise_shape_quantizer_short_prediction_c(in, coef, order)) |
||||
|
||||
static OPUS_INLINE opus_int32 silk_NSQ_noise_shape_feedback_loop_c(const opus_int32 *data0, opus_int32 *data1, const opus_int16 *coef, opus_int order) |
||||
{ |
||||
opus_int32 out; |
||||
opus_int32 tmp1, tmp2; |
||||
opus_int j; |
||||
|
||||
tmp2 = data0[0]; |
||||
tmp1 = data1[0]; |
||||
data1[0] = tmp2; |
||||
|
||||
out = silk_RSHIFT(order, 1); |
||||
out = silk_SMLAWB(out, tmp2, coef[0]); |
||||
|
||||
for (j = 2; j < order; j += 2) { |
||||
tmp2 = data1[j - 1]; |
||||
data1[j - 1] = tmp1; |
||||
out = silk_SMLAWB(out, tmp1, coef[j - 1]); |
||||
tmp1 = data1[j + 0]; |
||||
data1[j + 0] = tmp2; |
||||
out = silk_SMLAWB(out, tmp2, coef[j]); |
||||
} |
||||
data1[order - 1] = tmp1; |
||||
out = silk_SMLAWB(out, tmp1, coef[order - 1]); |
||||
/* Q11 -> Q12 */ |
||||
out = silk_LSHIFT32( out, 1 ); |
||||
return out; |
||||
} |
||||
|
||||
#define silk_NSQ_noise_shape_feedback_loop(data0, data1, coef, order, arch) ((void)arch,silk_NSQ_noise_shape_feedback_loop_c(data0, data1, coef, order)) |
||||
|
||||
#if defined(OPUS_ARM_MAY_HAVE_NEON_INTR) |
||||
#include "arm/NSQ_neon.h" |
||||
#endif |
||||
|
||||
#if defined(__mips) |
||||
#include "mips/NSQ_mips.h" |
||||
#endif |
||||
|
||||
#endif /* SILK_NSQ_H */ |
||||
@ -0,0 +1,730 @@
|
||||
/***********************************************************************
|
||||
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 "NSQ.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 Diff_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 Diff_Q14; |
||||
opus_int32 sLTP_shp_Q14; |
||||
opus_int32 LPC_exc_Q14; |
||||
} NSQ_sample_struct; |
||||
|
||||
typedef NSQ_sample_struct NSQ_sample_pair[ 2 ]; |
||||
|
||||
static OPUS_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_int16 x16[], /* I Input */ |
||||
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 OPUS_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/O Index to newest samples in buffers */ |
||||
opus_int decisionDelay, /* I */ |
||||
int arch /* I */ |
||||
); |
||||
|
||||
void silk_NSQ_del_dec_c( |
||||
const silk_encoder_state *psEncC, /* I Encoder State */ |
||||
silk_nsq_state *NSQ, /* I/O NSQ state */ |
||||
SideInfoIndices *psIndices, /* I/O Quantization Indices */ |
||||
const opus_int16 x16[], /* I Input */ |
||||
opus_int8 pulses[], /* O Quantized pulse signal */ |
||||
const opus_int16 *PredCoef_Q12, /* I Short term prediction coefs */ |
||||
const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */ |
||||
const opus_int16 AR_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; |
||||
VARDECL( opus_int32, sLTP_Q15 ); |
||||
VARDECL( opus_int16, sLTP ); |
||||
opus_int32 HarmShapeFIRPacked_Q14; |
||||
opus_int offset_Q10; |
||||
opus_int32 RDmin_Q10, Gain_Q10; |
||||
VARDECL( opus_int32, x_sc_Q10 ); |
||||
VARDECL( opus_int32, delayedGain_Q10 ); |
||||
VARDECL( NSQ_del_dec_struct, psDelDec ); |
||||
NSQ_del_dec_struct *psDD; |
||||
SAVE_STACK; |
||||
|
||||
/* 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 */ |
||||
ALLOC( psDelDec, psEncC->nStatesDelayedDecision, NSQ_del_dec_struct ); |
||||
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->Diff_Q14 = NSQ->sDiff_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; |
||||
} |
||||
|
||||
ALLOC( sLTP_Q15, psEncC->ltp_mem_length + psEncC->frame_length, opus_int32 ); |
||||
ALLOC( sLTP, psEncC->ltp_mem_length + psEncC->frame_length, opus_int16 ); |
||||
ALLOC( x_sc_Q10, psEncC->subfr_length, opus_int32 ); |
||||
ALLOC( delayedGain_Q10, DECISION_DELAY, opus_int32 ); |
||||
/* 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 = &AR_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; |
||||
if( last_smple_idx < 0 ) last_smple_idx += DECISION_DELAY; |
||||
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; |
||||
celt_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, psEncC->arch ); |
||||
|
||||
NSQ->sLTP_buf_idx = psEncC->ltp_mem_length; |
||||
NSQ->rewhite_flag = 1; |
||||
} |
||||
} |
||||
|
||||
silk_nsq_del_dec_scale_states( psEncC, NSQ, psDelDec, x16, 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, psEncC->arch ); |
||||
|
||||
x16 += 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; |
||||
if( last_smple_idx < 0 ) last_smple_idx += DECISION_DELAY; |
||||
|
||||
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->sDiff_shp_Q14 = psDD->Diff_Q14; |
||||
NSQ->lagPrev = pitchL[ psEncC->nb_subfr - 1 ]; |
||||
|
||||
/* Save quantized speech signal */ |
||||
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 ) ); |
||||
RESTORE_STACK; |
||||
} |
||||
|
||||
/******************************************/ |
||||
/* Noise shape quantizer for one subframe */ |
||||
/******************************************/ |
||||
#ifndef OVERRIDE_silk_noise_shape_quantizer_del_dec |
||||
static OPUS_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/O Index to newest samples in buffers */ |
||||
opus_int decisionDelay, /* I */ |
||||
int arch /* 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; |
||||
#ifdef silk_short_prediction_create_arch_coef |
||||
opus_int32 a_Q12_arch[MAX_LPC_ORDER]; |
||||
#endif |
||||
|
||||
VARDECL( NSQ_sample_pair, psSampleState ); |
||||
NSQ_del_dec_struct *psDD; |
||||
NSQ_sample_struct *psSS; |
||||
SAVE_STACK; |
||||
|
||||
celt_assert( nStatesDelayedDecision > 0 ); |
||||
ALLOC( psSampleState, nStatesDelayedDecision, NSQ_sample_pair ); |
||||
|
||||
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 ); |
||||
|
||||
#ifdef silk_short_prediction_create_arch_coef |
||||
silk_short_prediction_create_arch_coef(a_Q12_arch, a_Q12, predictLPCOrder); |
||||
#endif |
||||
|
||||
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_ADD_SAT32( 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 */ |
||||
LPC_pred_Q14 = silk_noise_shape_quantizer_short_prediction(psLPC_Q14, a_Q12, a_Q12_arch, predictLPCOrder, arch); |
||||
LPC_pred_Q14 = silk_LSHIFT( LPC_pred_Q14, 4 ); /* Q10 -> Q14 */ |
||||
|
||||
/* Noise shape feedback */ |
||||
celt_assert( ( shapingLPCOrder & 1 ) == 0 ); /* check that order is even */ |
||||
/* Output of lowpass section */ |
||||
tmp2 = silk_SMLAWB( psDD->Diff_Q14, psDD->sAR2_Q14[ 0 ], warping_Q16 ); |
||||
/* Output of allpass section */ |
||||
tmp1 = silk_SMLAWB( psDD->sAR2_Q14[ 0 ], silk_SUB32_ovflw(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 ], silk_SUB32_ovflw(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 ], silk_SUB32_ovflw(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_ADD_SAT32( n_AR_Q14, n_LF_Q14 ); /* Q14 */ |
||||
tmp2 = silk_ADD32_ovflw( n_LTP_Q14, LPC_pred_Q14 ); /* Q13 */ |
||||
tmp1 = silk_SUB_SAT32( 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 (Lambda_Q10 > 2048) { |
||||
/* For aggressive RDO, the bias becomes more than one pulse. */ |
||||
int rdo_offset = Lambda_Q10/2 - 512; |
||||
if (q1_Q10 > rdo_offset) { |
||||
q1_Q0 = silk_RSHIFT( q1_Q10 - rdo_offset, 10 ); |
||||
} else if (q1_Q10 < -rdo_offset) { |
||||
q1_Q0 = silk_RSHIFT( q1_Q10 + rdo_offset, 10 ); |
||||
} else if (q1_Q10 < 0) { |
||||
q1_Q0 = -1; |
||||
} else { |
||||
q1_Q0 = 0; |
||||
} |
||||
} |
||||
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_ovflw( LPC_exc_Q14, LPC_pred_Q14 ); |
||||
|
||||
/* Update states */ |
||||
psSS[ 0 ].Diff_Q14 = silk_SUB32_ovflw( xq_Q14, silk_LSHIFT32( x_Q10[ i ], 4 ) ); |
||||
sLF_AR_shp_Q14 = silk_SUB32_ovflw( psSS[ 0 ].Diff_Q14, n_AR_Q14 ); |
||||
psSS[ 0 ].sLTP_shp_Q14 = silk_SUB_SAT32( 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_ovflw( LPC_exc_Q14, LPC_pred_Q14 ); |
||||
|
||||
/* Update states */ |
||||
psSS[ 1 ].Diff_Q14 = silk_SUB32_ovflw( xq_Q14, silk_LSHIFT32( x_Q10[ i ], 4 ) ); |
||||
sLF_AR_shp_Q14 = silk_SUB32_ovflw( psSS[ 1 ].Diff_Q14, n_AR_Q14 ); |
||||
psSS[ 1 ].sLTP_shp_Q14 = silk_SUB_SAT32( 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; |
||||
if( *smpl_buf_idx < 0 ) *smpl_buf_idx += DECISION_DELAY; |
||||
last_smple_idx = ( *smpl_buf_idx + decisionDelay ) % DECISION_DELAY; |
||||
|
||||
/* 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->Diff_Q14 = psSS->Diff_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 ) ); |
||||
} |
||||
RESTORE_STACK; |
||||
} |
||||
#endif /* OVERRIDE_silk_noise_shape_quantizer_del_dec */ |
||||
|
||||
static OPUS_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_int16 x16[], /* I Input */ |
||||
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_Q26; |
||||
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 ); |
||||
|
||||
/* Scale input */ |
||||
inv_gain_Q26 = silk_RSHIFT_ROUND( inv_gain_Q31, 5 ); |
||||
for( i = 0; i < psEncC->subfr_length; i++ ) { |
||||
x_sc_Q10[ i ] = silk_SMULWW( x16[ i ], inv_gain_Q26 ); |
||||
} |
||||
|
||||
/* 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( Gains_Q16[ subfr ] != NSQ->prev_gain_Q16 ) { |
||||
gain_adj_Q16 = silk_DIV32_varQ( NSQ->prev_gain_Q16, Gains_Q16[ subfr ], 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 ); |
||||
psDD->Diff_Q14 = silk_SMULWW( gain_adj_Q16, psDD->Diff_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 ] ); |
||||
} |
||||
} |
||||
|
||||
/* Save inverse gain */ |
||||
NSQ->prev_gain_Q16 = Gains_Q16[ subfr ]; |
||||
} |
||||
} |
||||
@ -0,0 +1,493 @@
|
||||
/***********************************************************************
|
||||
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" |
||||
|
||||
#ifdef ENABLE_DEEP_PLC |
||||
#include "lpcnet.h" |
||||
#endif |
||||
|
||||
#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 OPUS_INLINE void silk_PLC_update( |
||||
silk_decoder_state *psDec, /* I/O Decoder state */ |
||||
silk_decoder_control *psDecCtrl /* I/O Decoder control */ |
||||
); |
||||
|
||||
static OPUS_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 */ |
||||
#ifdef ENABLE_DEEP_PLC |
||||
LPCNetPLCState *lpcnet, |
||||
#endif |
||||
int arch /* I Run-time architecture */ |
||||
); |
||||
|
||||
|
||||
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 */ |
||||
#ifdef ENABLE_DEEP_PLC |
||||
LPCNetPLCState *lpcnet, |
||||
#endif |
||||
int arch /* I Run-time architecture */ |
||||
) |
||||
{ |
||||
/* 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, |
||||
#ifdef ENABLE_DEEP_PLC |
||||
lpcnet, |
||||
#endif |
||||
arch ); |
||||
|
||||
psDec->lossCnt++; |
||||
} else { |
||||
/****************************/ |
||||
/* Update state */ |
||||
/****************************/ |
||||
silk_PLC_update( psDec, psDecCtrl ); |
||||
#ifdef ENABLE_DEEP_PLC |
||||
if ( lpcnet != NULL && psDec->sPLC.fs_kHz == 16 ) { |
||||
int k; |
||||
for( k = 0; k < psDec->nb_subfr; k += 2 ) { |
||||
lpcnet_plc_update( lpcnet, frame + k * psDec->subfr_length ); |
||||
} |
||||
} |
||||
#endif |
||||
} |
||||
} |
||||
|
||||
/**************************************************/ |
||||
/* Update state of PLC */ |
||||
/**************************************************/ |
||||
static OPUS_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 coefficients */ |
||||
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 OPUS_INLINE void silk_PLC_energy(opus_int32 *energy1, opus_int *shift1, opus_int32 *energy2, opus_int *shift2, |
||||
const opus_int32 *exc_Q14, const opus_int32 *prevGain_Q10, int subfr_length, int nb_subfr) |
||||
{ |
||||
int i, k; |
||||
VARDECL( opus_int16, exc_buf ); |
||||
opus_int16 *exc_buf_ptr; |
||||
SAVE_STACK; |
||||
ALLOC( exc_buf, 2*subfr_length, opus_int16 ); |
||||
/* Find random noise component */ |
||||
/* Scale previous excitation signal */ |
||||
exc_buf_ptr = exc_buf; |
||||
for( k = 0; k < 2; k++ ) { |
||||
for( i = 0; i < subfr_length; i++ ) { |
||||
exc_buf_ptr[ i ] = (opus_int16)silk_SAT16( silk_RSHIFT( |
||||
silk_SMULWW( exc_Q14[ i + ( k + nb_subfr - 2 ) * subfr_length ], prevGain_Q10[ k ] ), 8 ) ); |
||||
} |
||||
exc_buf_ptr += 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, subfr_length ); |
||||
silk_sum_sqr_shift( energy2, shift2, &exc_buf[ subfr_length ], subfr_length ); |
||||
RESTORE_STACK; |
||||
} |
||||
|
||||
static OPUS_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 */ |
||||
#ifdef ENABLE_DEEP_PLC |
||||
LPCNetPLCState *lpcnet, |
||||
#endif |
||||
int arch /* I Run-time architecture */ |
||||
) |
||||
{ |
||||
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; |
||||
opus_int32 *sLPC_Q14_ptr; |
||||
opus_int16 A_Q12[ MAX_LPC_ORDER ]; |
||||
#ifdef SMALL_FOOTPRINT |
||||
opus_int16 *sLTP; |
||||
#else |
||||
VARDECL( opus_int16, sLTP ); |
||||
#endif |
||||
VARDECL( opus_int32, sLTP_Q14 ); |
||||
silk_PLC_struct *psPLC = &psDec->sPLC; |
||||
opus_int32 prevGain_Q10[2]; |
||||
SAVE_STACK; |
||||
|
||||
ALLOC( sLTP_Q14, psDec->ltp_mem_length + psDec->frame_length, opus_int32 ); |
||||
#ifdef SMALL_FOOTPRINT |
||||
/* Ugly hack that breaks aliasing rules to save stack: put sLTP at the very end of sLTP_Q14. */ |
||||
sLTP = ((opus_int16*)&sLTP_Q14[psDec->ltp_mem_length + psDec->frame_length])-psDec->ltp_mem_length; |
||||
#else |
||||
ALLOC( sLTP, psDec->ltp_mem_length, opus_int16 ); |
||||
#endif |
||||
|
||||
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 ) ); |
||||
} |
||||
|
||||
silk_PLC_energy(&energy1, &shift1, &energy2, &shift2, psDec->exc_Q14, prevGain_Q10, psDec->subfr_length, psDec->nb_subfr); |
||||
|
||||
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 coefficients 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, arch ); |
||||
|
||||
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; |
||||
celt_assert( idx > 0 ); |
||||
silk_LPC_analysis_filter( &sLTP[ idx ], &psDec->outBuf[ idx ], A_Q12, psDec->ltp_mem_length - idx, psDec->LPC_order, arch ); |
||||
/* 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 ) ); |
||||
|
||||
celt_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_SAT32( sLPC_Q14_ptr[ MAX_LPC_ORDER + i ], |
||||
silk_LSHIFT_SAT32( 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 ) ) ); |
||||
} |
||||
#ifdef ENABLE_DEEP_PLC |
||||
if ( lpcnet != NULL && lpcnet->loaded && psDec->sPLC.fs_kHz == 16 ) { |
||||
int run_deep_plc = psDec->sPLC.enable_deep_plc || lpcnet->fec_fill_pos != 0; |
||||
if( run_deep_plc ) { |
||||
for( k = 0; k < psDec->nb_subfr; k += 2 ) { |
||||
lpcnet_plc_conceal( lpcnet, frame + k * psDec->subfr_length ); |
||||
} |
||||
/* We *should* be able to copy only from psDec->frame_length-MAX_LPC_ORDER, i.e. the last MAX_LPC_ORDER samples. */ |
||||
for( i = 0; i < psDec->frame_length; i++ ) { |
||||
sLPC_Q14_ptr[ MAX_LPC_ORDER + i ] = (int)floor(.5 + frame[ i ] * (float)(1 << 24) / prevGain_Q10[ 1 ] ); |
||||
} |
||||
} else { |
||||
for( k = 0; k < psDec->nb_subfr; k += 2 ) { |
||||
lpcnet_plc_update( lpcnet, frame + k * psDec->subfr_length ); |
||||
} |
||||
} |
||||
} |
||||
#endif |
||||
|
||||
/* 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 ); |
||||
#ifdef ENABLE_DEEP_PLC |
||||
if ( psDec->sPLC.fs_kHz != 16 ) |
||||
#endif |
||||
{ |
||||
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,64 @@
|
||||
/***********************************************************************
|
||||
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 */ |
||||
#ifdef ENABLE_DEEP_PLC |
||||
LPCNetPLCState *lpcnet, |
||||
#endif |
||||
int arch /* I Run-time architecture */ |
||||
); |
||||
|
||||
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,641 @@
|
||||
/***********************************************************************
|
||||
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 |
||||
|
||||
|
||||
/*#define silk_MACRO_COUNT */ /* Used to enable WMOPS counting */ |
||||
|
||||
#define SILK_MAX_ORDER_LPC 24 /* 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" |
||||
#include "cpu_support.h" |
||||
|
||||
#if defined(OPUS_X86_MAY_HAVE_SSE4_1) |
||||
#include "x86/SigProc_FIX_sse.h" |
||||
#endif |
||||
|
||||
#if (defined(OPUS_ARM_ASM) || defined(OPUS_ARM_MAY_HAVE_NEON_INTR)) |
||||
#include "arm/biquad_alt_arm.h" |
||||
#include "arm/LPC_inv_pred_gain_arm.h" |
||||
#endif |
||||
|
||||
/********************************************************************/ |
||||
/* 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_stride1( |
||||
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) */ |
||||
); |
||||
|
||||
void silk_biquad_alt_stride2_c( |
||||
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 [4] */ |
||||
opus_int16 *out, /* O output signal */ |
||||
const opus_int32 len /* I signal length (must be even) */ |
||||
); |
||||
|
||||
/* 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 */ |
||||
int arch /* I Run-time architecture */ |
||||
); |
||||
|
||||
/* 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_c( /* 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 */ |
||||
); |
||||
|
||||
/* 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 */ |
||||
); |
||||
|
||||
#if !defined(OVERRIDE_silk_biquad_alt_stride2) |
||||
#define silk_biquad_alt_stride2(in, B_Q28, A_Q28, S, out, len, arch) ((void)(arch), silk_biquad_alt_stride2_c(in, B_Q28, A_Q28, S, out, len)) |
||||
#endif |
||||
|
||||
#if !defined(OVERRIDE_silk_LPC_inverse_pred_gain) |
||||
#define silk_LPC_inverse_pred_gain(A_Q12, order, arch) ((void)(arch), silk_LPC_inverse_pred_gain_c(A_Q12, order)) |
||||
#endif |
||||
|
||||
/********************************************************************/ |
||||
/* 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 */ |
||||
); |
||||
|
||||
/* 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 */ |
||||
int arch /* I Run-time architecture */ |
||||
); |
||||
|
||||
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_Q13, /* 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 */ |
||||
int arch /* I Run-time architecture */ |
||||
); |
||||
|
||||
/* 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) */ |
||||
int arch /* I Run-time architecture */ |
||||
); |
||||
|
||||
/* Convert int32 coefficients to int16 coefs and make sure there's no wrap-around */ |
||||
void silk_LPC_fit( |
||||
opus_int16 *a_QOUT, /* O Output signal */ |
||||
opus_int32 *a_QIN, /* I/O Input signal */ |
||||
const opus_int QOUT, /* I Input Q domain */ |
||||
const opus_int QIN, /* I Input Q domain */ |
||||
const opus_int d /* I Filter order */ |
||||
); |
||||
|
||||
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_c( |
||||
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 */ |
||||
int arch /* I Run-time architecture */ |
||||
); |
||||
|
||||
/* 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 */ |
||||
int arch /* I Run-time architecture */ |
||||
); |
||||
|
||||
|
||||
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_c( |
||||
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 OPUS_INLINE ASM! */ |
||||
static OPUS_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) ((((opus_uint32)(a)+(opus_uint32)(b)) & 0x80000000) ? silk_int32_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 OPUS_INLINE opus_int silk_min_int(opus_int a, opus_int b) |
||||
{ |
||||
return (((a) < (b)) ? (a) : (b)); |
||||
} |
||||
static OPUS_INLINE opus_int16 silk_min_16(opus_int16 a, opus_int16 b) |
||||
{ |
||||
return (((a) < (b)) ? (a) : (b)); |
||||
} |
||||
static OPUS_INLINE opus_int32 silk_min_32(opus_int32 a, opus_int32 b) |
||||
{ |
||||
return (((a) < (b)) ? (a) : (b)); |
||||
} |
||||
static OPUS_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 OPUS_INLINE opus_int silk_max_int(opus_int a, opus_int b) |
||||
{ |
||||
return (((a) > (b)) ? (a) : (b)); |
||||
} |
||||
static OPUS_INLINE opus_int16 silk_max_16(opus_int16 a, opus_int16 b) |
||||
{ |
||||
return (((a) > (b)) ? (a) : (b)); |
||||
} |
||||
static OPUS_INLINE opus_int32 silk_max_32(opus_int32 a, opus_int32 b) |
||||
{ |
||||
return (((a) > (b)) ? (a) : (b)); |
||||
} |
||||
static OPUS_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 RAND_MULTIPLIER 196314165 |
||||
#define RAND_INCREMENT 907633515 |
||||
#define silk_RAND(seed) (silk_MLA_ovflw((RAND_INCREMENT), (seed), (RAND_MULTIPLIER))) |
||||
|
||||
/* Add some multiplication functions that can be easily mapped to ARM/MIPS32. */ |
||||
|
||||
/* silk_SMMUL: Signed top word multiply.
|
||||
ARMv6 2 instruction cycles. |
||||
ARMv3M+ 3 instruction cycles. use SMULL and ignore LSB registers.(except xM) |
||||
MIPS32 2 instructions mul+mfhi |
||||
MIPS32r6 1 instruction muh */ |
||||
/*#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) |
||||
|
||||
#if !defined(OVERRIDE_silk_burg_modified) |
||||
#define silk_burg_modified(res_nrg, res_nrg_Q, A_Q16, x, minInvGain_Q30, subfr_length, nb_subfr, D, arch) \ |
||||
((void)(arch), silk_burg_modified_c(res_nrg, res_nrg_Q, A_Q16, x, minInvGain_Q30, subfr_length, nb_subfr, D, arch)) |
||||
#endif |
||||
|
||||
#if !defined(OVERRIDE_silk_inner_prod16) |
||||
#define silk_inner_prod16(inVec1, inVec2, len, arch) \ |
||||
((void)(arch),silk_inner_prod16_c(inVec1, inVec2, len)) |
||||
#endif |
||||
|
||||
#include "Inlines.h" |
||||
#include "MacroCount.h" |
||||
#include "MacroDebug.h" |
||||
|
||||
#ifdef OPUS_ARM_INLINE_ASM |
||||
#include "arm/SigProc_FIX_armv4.h" |
||||
#endif |
||||
|
||||
#ifdef OPUS_ARM_INLINE_EDSP |
||||
#include "arm/SigProc_FIX_armv5e.h" |
||||
#endif |
||||
|
||||
#if defined(FIXED_POINT) && defined(__mips_dsp) && __mips == 32 |
||||
#include "mips/sigproc_fix_mipsr1.h" |
||||
#endif |
||||
|
||||
#ifdef OPUS_XTENSA_LX7 |
||||
#include "xtensa/SigProc_FIX_lx7.h" |
||||
#endif |
||||
|
||||
|
||||
#endif /* SILK_SIGPROC_FIX_H */ |
||||
@ -0,0 +1,360 @@
|
||||
/***********************************************************************
|
||||
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" |
||||
|
||||
/* Silk VAD noise level estimation */ |
||||
# if !defined(OPUS_X86_MAY_HAVE_SSE4_1) |
||||
static OPUS_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 */ |
||||
); |
||||
#endif |
||||
|
||||
/**********************************/ |
||||
/* 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_c( /* 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_framelength1, decimated_framelength2; |
||||
opus_int decimated_framelength; |
||||
opus_int dec_subframe_length, dec_subframe_offset, SNR_Q7, i, b, s; |
||||
opus_int32 sumSquared, smooth_coef_Q16; |
||||
opus_int16 HPstateTmp; |
||||
VARDECL( opus_int16, X ); |
||||
opus_int32 Xnrg[ VAD_N_BANDS ]; |
||||
opus_int32 NrgToNoiseRatio_Q8[ VAD_N_BANDS ]; |
||||
opus_int32 speech_nrg, x_tmp; |
||||
opus_int X_offset[ VAD_N_BANDS ]; |
||||
opus_int ret = 0; |
||||
silk_VAD_state *psSilk_VAD = &psEncC->sVAD; |
||||
SAVE_STACK; |
||||
|
||||
/* Safety checks */ |
||||
silk_assert( VAD_N_BANDS == 4 ); |
||||
celt_assert( MAX_FRAME_LENGTH >= psEncC->frame_length ); |
||||
celt_assert( psEncC->frame_length <= 512 ); |
||||
celt_assert( psEncC->frame_length == 8 * silk_RSHIFT( psEncC->frame_length, 3 ) ); |
||||
|
||||
/***********************/ |
||||
/* Filter and Decimate */ |
||||
/***********************/ |
||||
decimated_framelength1 = silk_RSHIFT( psEncC->frame_length, 1 ); |
||||
decimated_framelength2 = silk_RSHIFT( psEncC->frame_length, 2 ); |
||||
decimated_framelength = silk_RSHIFT( psEncC->frame_length, 3 ); |
||||
/* Decimate into 4 bands:
|
||||
0 L 3L L 3L 5L |
||||
- -- - -- -- |
||||
8 8 2 4 4 |
||||
|
||||
[0-1 kHz| temp. |1-2 kHz| 2-4 kHz | 4-8 kHz | |
||||
|
||||
They're arranged to allow the minimal ( frame_length / 4 ) extra |
||||
scratch space during the downsampling process */ |
||||
X_offset[ 0 ] = 0; |
||||
X_offset[ 1 ] = decimated_framelength + decimated_framelength2; |
||||
X_offset[ 2 ] = X_offset[ 1 ] + decimated_framelength; |
||||
X_offset[ 3 ] = X_offset[ 2 ] + decimated_framelength2; |
||||
ALLOC( X, X_offset[ 3 ] + decimated_framelength1, opus_int16 ); |
||||
|
||||
/* 0-8 kHz to 0-4 kHz and 4-8 kHz */ |
||||
silk_ana_filt_bank_1( pIn, &psSilk_VAD->AnaState[ 0 ], |
||||
X, &X[ X_offset[ 3 ] ], psEncC->frame_length ); |
||||
|
||||
/* 0-4 kHz to 0-2 kHz and 2-4 kHz */ |
||||
silk_ana_filt_bank_1( X, &psSilk_VAD->AnaState1[ 0 ], |
||||
X, &X[ X_offset[ 2 ] ], decimated_framelength1 ); |
||||
|
||||
/* 0-2 kHz to 0-1 kHz and 1-2 kHz */ |
||||
silk_ana_filt_bank_1( X, &psSilk_VAD->AnaState2[ 0 ], |
||||
X, &X[ X_offset[ 1 ] ], decimated_framelength2 ); |
||||
|
||||
/*********************************************/ |
||||
/* HP filter on lowest band (differentiator) */ |
||||
/*********************************************/ |
||||
X[ decimated_framelength - 1 ] = silk_RSHIFT( X[ decimated_framelength - 1 ], 1 ); |
||||
HPstateTmp = X[ decimated_framelength - 1 ]; |
||||
for( i = decimated_framelength - 1; i > 0; i-- ) { |
||||
X[ i - 1 ] = silk_RSHIFT( X[ i - 1 ], 1 ); |
||||
X[ i ] -= X[ i - 1 ]; |
||||
} |
||||
X[ 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[ X_offset[ 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 ); |
||||
} |
||||
|
||||
if( psEncC->frame_length == 20 * psEncC->fs_kHz ) { |
||||
speech_nrg = silk_RSHIFT32( speech_nrg, 1 ); |
||||
} |
||||
/* Power scaling */ |
||||
if( speech_nrg <= 0 ) { |
||||
SA_Q15 = silk_RSHIFT( SA_Q15, 1 ); |
||||
} else if( speech_nrg < 16384 ) { |
||||
speech_nrg = silk_LSHIFT32( speech_nrg, 16 ); |
||||
|
||||
/* 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 ) ); |
||||
} |
||||
|
||||
RESTORE_STACK; |
||||
return( ret ); |
||||
} |
||||
|
||||
/**************************/ |
||||
/* Noise level estimation */ |
||||
/**************************/ |
||||
# if !defined(OPUS_X86_MAY_HAVE_SSE4_1) |
||||
static OPUS_INLINE |
||||
#endif |
||||
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 ); |
||||
/* Increment frame counter */ |
||||
psSilk_VAD->counter++; |
||||
} 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; |
||||
} |
||||
} |
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue