1
0
Fork 0
forked from len0rd/rockbox

Sync opus codec to upstream git

Change-Id: I0cfcc0005c4ad7bfbb1aaf454188ce70fb043dc1
This commit is contained in:
William Wilgus 2019-01-04 02:01:18 -06:00 committed by Solomon Peachy
parent 75d9393796
commit 14c6bb798d
286 changed files with 48931 additions and 1278 deletions

View file

@ -1,5 +1,5 @@
Libraries: Opus (snapshot) / Opus-tools (snapshot) / libogg 1.3 Libraries: Opus (snapshot) / Opus-tools (snapshot) / libogg 1.3
Imported: September 15th, 2012 Imported: January 1st, 2019
Steps taken to adapt original opus/opus-tool/ogg source files to rockbox Steps taken to adapt original opus/opus-tool/ogg source files to rockbox
(useful when for example syncing a new snapshot) (useful when for example syncing a new snapshot)
@ -10,13 +10,21 @@ Opus:
* copied .c/.h files from opus/celt to lib/rbcodec/codecs/libopus/celt * copied .c/.h files from opus/celt to lib/rbcodec/codecs/libopus/celt
* copied .c/.h files from opus/silk to lib/rbcodec/codecs/libopus/silk * copied .c/.h files from opus/silk to lib/rbcodec/codecs/libopus/silk
Celt:
* changed #if FIXED_POINT to #ifdef FIXED_POINT in bands.c
* changed #elif OPUS_ARM_INLINE_EDSP to #elif defined (OPUS_ARM_INLINE_EDSP)
* add #define ABS(a)(((a) < 0) ? - (a) :(a)) to mathops.h
Opus-tools: Opus-tools:
* copied src/opus_header.h and src/opus_header.c to lib/rbcodec/codecs/libopus * copied src/opus_header.h and src/opus_header.c to lib/rbcodec/codecs/libopus
* changed #include <ogg/ogg.h> to #include "ogg/ogg.h" in opus_header.c * changed #include <ogg/ogg.h> to #include "ogg/ogg.h" in opus_header.h
Ogg: Ogg:
* copied libogg/src/framing.c to lib/rbcodec/codecs/libopus/ogg * copied libogg/src/framing.c to lib/rbcodec/codecs/libopus/ogg
* copied libogg/include/ogg.h to lib/rbcodec/codecs/libopus/ogg * copied libogg/include/ogg.h to lib/rbcodec/codecs/libopus/ogg
* copied libogg/include/crctable.h to lib/rbcodec/codecs/libopus/ogg
* changed #include "ogg/ogg.h" to #include "ogg.h" in framing.c * changed #include "ogg/ogg.h" to #include "ogg.h" in framing.c
* added os_config.h to lib/rbcodec/codecs/libopus/ogg * -- added os_config.h to lib/rbcodec/codecs/libopus/ogg
* added our own os_types.h
* changed #include <ogg/os_types.h> to #include "os_types.h" in ogg.h
* changed #include <ogg/os_types.h> to #include "os_types.h" in crctable.h

View file

@ -32,8 +32,10 @@ silk/decode_pulses.c
silk/decoder_set_fs.c silk/decoder_set_fs.c
silk/gain_quant.c silk/gain_quant.c
silk/init_decoder.c silk/init_decoder.c
silk/lin2log.c
silk/log2lin.c silk/log2lin.c
silk/LPC_analysis_filter.c silk/LPC_analysis_filter.c
silk/LPC_fit.c
silk/LPC_inv_pred_gain.c silk/LPC_inv_pred_gain.c
silk/NLSF2A.c silk/NLSF2A.c
silk/NLSF_decode.c silk/NLSF_decode.c

View file

@ -0,0 +1,945 @@
/* 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 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 HAVE_CONFIG_H
#include "config.h"
#endif
#define ANALYSIS_C
#include <stdio.h>
#include "mathops.h"
#include "kiss_fft.h"
#include "celt.h"
#include "modes.h"
#include "arch.h"
#include "quant_bands.h"
#include "analysis.h"
#include "mlp.h"
#include "stack_alloc.h"
#include "float_cast.h"
#ifndef M_PI
#define M_PI 3.141592653
#endif
#ifndef DISABLE_FLOAT_API
#define TRANSITION_PENALTY 10
static const float dct_table[128] = {
0.250000f, 0.250000f, 0.250000f, 0.250000f, 0.250000f, 0.250000f, 0.250000f, 0.250000f,
0.250000f, 0.250000f, 0.250000f, 0.250000f, 0.250000f, 0.250000f, 0.250000f, 0.250000f,
0.351851f, 0.338330f, 0.311806f, 0.273300f, 0.224292f, 0.166664f, 0.102631f, 0.034654f,
-0.034654f,-0.102631f,-0.166664f,-0.224292f,-0.273300f,-0.311806f,-0.338330f,-0.351851f,
0.346760f, 0.293969f, 0.196424f, 0.068975f,-0.068975f,-0.196424f,-0.293969f,-0.346760f,
-0.346760f,-0.293969f,-0.196424f,-0.068975f, 0.068975f, 0.196424f, 0.293969f, 0.346760f,
0.338330f, 0.224292f, 0.034654f,-0.166664f,-0.311806f,-0.351851f,-0.273300f,-0.102631f,
0.102631f, 0.273300f, 0.351851f, 0.311806f, 0.166664f,-0.034654f,-0.224292f,-0.338330f,
0.326641f, 0.135299f,-0.135299f,-0.326641f,-0.326641f,-0.135299f, 0.135299f, 0.326641f,
0.326641f, 0.135299f,-0.135299f,-0.326641f,-0.326641f,-0.135299f, 0.135299f, 0.326641f,
0.311806f, 0.034654f,-0.273300f,-0.338330f,-0.102631f, 0.224292f, 0.351851f, 0.166664f,
-0.166664f,-0.351851f,-0.224292f, 0.102631f, 0.338330f, 0.273300f,-0.034654f,-0.311806f,
0.293969f,-0.068975f,-0.346760f,-0.196424f, 0.196424f, 0.346760f, 0.068975f,-0.293969f,
-0.293969f, 0.068975f, 0.346760f, 0.196424f,-0.196424f,-0.346760f,-0.068975f, 0.293969f,
0.273300f,-0.166664f,-0.338330f, 0.034654f, 0.351851f, 0.102631f,-0.311806f,-0.224292f,
0.224292f, 0.311806f,-0.102631f,-0.351851f,-0.034654f, 0.338330f, 0.166664f,-0.273300f,
};
static const float analysis_window[240] = {
0.000043f, 0.000171f, 0.000385f, 0.000685f, 0.001071f, 0.001541f, 0.002098f, 0.002739f,
0.003466f, 0.004278f, 0.005174f, 0.006156f, 0.007222f, 0.008373f, 0.009607f, 0.010926f,
0.012329f, 0.013815f, 0.015385f, 0.017037f, 0.018772f, 0.020590f, 0.022490f, 0.024472f,
0.026535f, 0.028679f, 0.030904f, 0.033210f, 0.035595f, 0.038060f, 0.040604f, 0.043227f,
0.045928f, 0.048707f, 0.051564f, 0.054497f, 0.057506f, 0.060591f, 0.063752f, 0.066987f,
0.070297f, 0.073680f, 0.077136f, 0.080665f, 0.084265f, 0.087937f, 0.091679f, 0.095492f,
0.099373f, 0.103323f, 0.107342f, 0.111427f, 0.115579f, 0.119797f, 0.124080f, 0.128428f,
0.132839f, 0.137313f, 0.141849f, 0.146447f, 0.151105f, 0.155823f, 0.160600f, 0.165435f,
0.170327f, 0.175276f, 0.180280f, 0.185340f, 0.190453f, 0.195619f, 0.200838f, 0.206107f,
0.211427f, 0.216797f, 0.222215f, 0.227680f, 0.233193f, 0.238751f, 0.244353f, 0.250000f,
0.255689f, 0.261421f, 0.267193f, 0.273005f, 0.278856f, 0.284744f, 0.290670f, 0.296632f,
0.302628f, 0.308658f, 0.314721f, 0.320816f, 0.326941f, 0.333097f, 0.339280f, 0.345492f,
0.351729f, 0.357992f, 0.364280f, 0.370590f, 0.376923f, 0.383277f, 0.389651f, 0.396044f,
0.402455f, 0.408882f, 0.415325f, 0.421783f, 0.428254f, 0.434737f, 0.441231f, 0.447736f,
0.454249f, 0.460770f, 0.467298f, 0.473832f, 0.480370f, 0.486912f, 0.493455f, 0.500000f,
0.506545f, 0.513088f, 0.519630f, 0.526168f, 0.532702f, 0.539230f, 0.545751f, 0.552264f,
0.558769f, 0.565263f, 0.571746f, 0.578217f, 0.584675f, 0.591118f, 0.597545f, 0.603956f,
0.610349f, 0.616723f, 0.623077f, 0.629410f, 0.635720f, 0.642008f, 0.648271f, 0.654508f,
0.660720f, 0.666903f, 0.673059f, 0.679184f, 0.685279f, 0.691342f, 0.697372f, 0.703368f,
0.709330f, 0.715256f, 0.721144f, 0.726995f, 0.732807f, 0.738579f, 0.744311f, 0.750000f,
0.755647f, 0.761249f, 0.766807f, 0.772320f, 0.777785f, 0.783203f, 0.788573f, 0.793893f,
0.799162f, 0.804381f, 0.809547f, 0.814660f, 0.819720f, 0.824724f, 0.829673f, 0.834565f,
0.839400f, 0.844177f, 0.848895f, 0.853553f, 0.858151f, 0.862687f, 0.867161f, 0.871572f,
0.875920f, 0.880203f, 0.884421f, 0.888573f, 0.892658f, 0.896677f, 0.900627f, 0.904508f,
0.908321f, 0.912063f, 0.915735f, 0.919335f, 0.922864f, 0.926320f, 0.929703f, 0.933013f,
0.936248f, 0.939409f, 0.942494f, 0.945503f, 0.948436f, 0.951293f, 0.954072f, 0.956773f,
0.959396f, 0.961940f, 0.964405f, 0.966790f, 0.969096f, 0.971321f, 0.973465f, 0.975528f,
0.977510f, 0.979410f, 0.981228f, 0.982963f, 0.984615f, 0.986185f, 0.987671f, 0.989074f,
0.990393f, 0.991627f, 0.992778f, 0.993844f, 0.994826f, 0.995722f, 0.996534f, 0.997261f,
0.997902f, 0.998459f, 0.998929f, 0.999315f, 0.999615f, 0.999829f, 0.999957f, 1.000000f,
};
static const int tbands[NB_TBANDS+1] = {
4, 8, 12, 16, 20, 24, 28, 32, 40, 48, 56, 64, 80, 96, 112, 136, 160, 192, 240
};
#define NB_TONAL_SKIP_BANDS 9
static opus_val32 silk_resampler_down2_hp(
opus_val32 *S, /* I/O State vector [ 2 ] */
opus_val32 *out, /* O Output signal [ floor(len/2) ] */
const opus_val32 *in, /* I Input signal [ len ] */
int inLen /* I Number of input samples */
)
{
int k, len2 = inLen/2;
opus_val32 in32, out32, out32_hp, Y, X;
opus_val64 hp_ener = 0;
/* Internal variables and state are in Q10 format */
for( k = 0; k < len2; k++ ) {
/* Convert to Q10 */
in32 = in[ 2 * k ];
/* All-pass section for even input sample */
Y = SUB32( in32, S[ 0 ] );
X = MULT16_32_Q15(QCONST16(0.6074371f, 15), Y);
out32 = ADD32( S[ 0 ], X );
S[ 0 ] = ADD32( in32, X );
out32_hp = out32;
/* Convert to Q10 */
in32 = in[ 2 * k + 1 ];
/* All-pass section for odd input sample, and add to output of previous section */
Y = SUB32( in32, S[ 1 ] );
X = MULT16_32_Q15(QCONST16(0.15063f, 15), Y);
out32 = ADD32( out32, S[ 1 ] );
out32 = ADD32( out32, X );
S[ 1 ] = ADD32( in32, X );
Y = SUB32( -in32, S[ 2 ] );
X = MULT16_32_Q15(QCONST16(0.15063f, 15), Y);
out32_hp = ADD32( out32_hp, S[ 2 ] );
out32_hp = ADD32( out32_hp, X );
S[ 2 ] = ADD32( -in32, X );
hp_ener += out32_hp*(opus_val64)out32_hp;
/* Add, convert back to int16 and store to output */
out[ k ] = HALF32(out32);
}
#ifdef FIXED_POINT
/* len2 can be up to 480, so we shift by 8 more to make it fit. */
hp_ener = hp_ener >> (2*SIG_SHIFT + 8);
#endif
return (opus_val32)hp_ener;
}
static opus_val32 downmix_and_resample(downmix_func downmix, const void *_x, opus_val32 *y, opus_val32 S[3], int subframe, int offset, int c1, int c2, int C, int Fs)
{
VARDECL(opus_val32, tmp);
opus_val32 scale;
int j;
opus_val32 ret = 0;
SAVE_STACK;
if (subframe==0) return 0;
if (Fs == 48000)
{
subframe *= 2;
offset *= 2;
} else if (Fs == 16000) {
subframe = subframe*2/3;
offset = offset*2/3;
}
ALLOC(tmp, subframe, opus_val32);
downmix(_x, tmp, subframe, offset, c1, c2, C);
#ifdef FIXED_POINT
scale = (1<<SIG_SHIFT);
#else
scale = 1.f/32768;
#endif
if (c2==-2)
scale /= C;
else if (c2>-1)
scale /= 2;
for (j=0;j<subframe;j++)
tmp[j] *= scale;
if (Fs == 48000)
{
ret = silk_resampler_down2_hp(S, y, tmp, subframe);
} else if (Fs == 24000) {
OPUS_COPY(y, tmp, subframe);
} else if (Fs == 16000) {
VARDECL(opus_val32, tmp3x);
ALLOC(tmp3x, 3*subframe, opus_val32);
/* Don't do this at home! This resampler is horrible and it's only (barely)
usable for the purpose of the analysis because we don't care about all
the aliasing between 8 kHz and 12 kHz. */
for (j=0;j<subframe;j++)
{
tmp3x[3*j] = tmp[j];
tmp3x[3*j+1] = tmp[j];
tmp3x[3*j+2] = tmp[j];
}
silk_resampler_down2_hp(S, y, tmp3x, 3*subframe);
}
RESTORE_STACK;
return ret;
}
void tonality_analysis_init(TonalityAnalysisState *tonal, opus_int32 Fs)
{
/* Initialize reusable fields. */
tonal->arch = opus_select_arch();
tonal->Fs = Fs;
/* Clear remaining fields. */
tonality_analysis_reset(tonal);
}
void tonality_analysis_reset(TonalityAnalysisState *tonal)
{
/* Clear non-reusable fields. */
char *start = (char*)&tonal->TONALITY_ANALYSIS_RESET_START;
OPUS_CLEAR(start, sizeof(TonalityAnalysisState) - (start - (char*)tonal));
}
void tonality_get_info(TonalityAnalysisState *tonal, AnalysisInfo *info_out, int len)
{
int pos;
int curr_lookahead;
float tonality_max;
float tonality_avg;
int tonality_count;
int i;
int pos0;
float prob_avg;
float prob_count;
float prob_min, prob_max;
float vad_prob;
int mpos, vpos;
int bandwidth_span;
pos = tonal->read_pos;
curr_lookahead = tonal->write_pos-tonal->read_pos;
if (curr_lookahead<0)
curr_lookahead += DETECT_SIZE;
/* On long frames, look at the second analysis window rather than the first. */
if (len > tonal->Fs/50 && pos != tonal->write_pos)
{
pos++;
if (pos==DETECT_SIZE)
pos=0;
}
if (pos == tonal->write_pos)
pos--;
if (pos<0)
pos = DETECT_SIZE-1;
pos0 = pos;
OPUS_COPY(info_out, &tonal->info[pos], 1);
tonality_max = tonality_avg = info_out->tonality;
tonality_count = 1;
/* Look at the neighbouring frames and pick largest bandwidth found (to be safe). */
bandwidth_span = 6;
/* If possible, look ahead for a tone to compensate for the delay in the tone detector. */
for (i=0;i<3;i++)
{
pos++;
if (pos==DETECT_SIZE)
pos = 0;
if (pos == tonal->write_pos)
break;
tonality_max = MAX32(tonality_max, tonal->info[pos].tonality);
tonality_avg += tonal->info[pos].tonality;
tonality_count++;
info_out->bandwidth = IMAX(info_out->bandwidth, tonal->info[pos].bandwidth);
bandwidth_span--;
}
pos = pos0;
/* Look back in time to see if any has a wider bandwidth than the current frame. */
for (i=0;i<bandwidth_span;i++)
{
pos--;
if (pos < 0)
pos = DETECT_SIZE-1;
if (pos == tonal->write_pos)
break;
info_out->bandwidth = IMAX(info_out->bandwidth, tonal->info[pos].bandwidth);
}
info_out->tonality = MAX32(tonality_avg/tonality_count, tonality_max-.2f);
mpos = vpos = pos0;
/* If we have enough look-ahead, compensate for the ~5-frame delay in the music prob and
~1 frame delay in the VAD prob. */
if (curr_lookahead > 15)
{
mpos += 5;
if (mpos>=DETECT_SIZE)
mpos -= DETECT_SIZE;
vpos += 1;
if (vpos>=DETECT_SIZE)
vpos -= DETECT_SIZE;
}
/* The following calculations attempt to minimize a "badness function"
for the transition. When switching from speech to music, the badness
of switching at frame k is
b_k = S*v_k + \sum_{i=0}^{k-1} v_i*(p_i - T)
where
v_i is the activity probability (VAD) at frame i,
p_i is the music probability at frame i
T is the probability threshold for switching
S is the penalty for switching during active audio rather than silence
the current frame has index i=0
Rather than apply badness to directly decide when to switch, what we compute
instead is the threshold for which the optimal switching point is now. When
considering whether to switch now (frame 0) or at frame k, we have:
S*v_0 = S*v_k + \sum_{i=0}^{k-1} v_i*(p_i - T)
which gives us:
T = ( \sum_{i=0}^{k-1} v_i*p_i + S*(v_k-v_0) ) / ( \sum_{i=0}^{k-1} v_i )
We take the min threshold across all positive values of k (up to the maximum
amount of lookahead we have) to give us the threshold for which the current
frame is the optimal switch point.
The last step is that we need to consider whether we want to switch at all.
For that we use the average of the music probability over the entire window.
If the threshold is higher than that average we're not going to
switch, so we compute a min with the average as well. The result of all these
min operations is music_prob_min, which gives the threshold for switching to music
if we're currently encoding for speech.
We do the exact opposite to compute music_prob_max which is used for switching
from music to speech.
*/
prob_min = 1.f;
prob_max = 0.f;
vad_prob = tonal->info[vpos].activity_probability;
prob_count = MAX16(.1f, vad_prob);
prob_avg = MAX16(.1f, vad_prob)*tonal->info[mpos].music_prob;
while (1)
{
float pos_vad;
mpos++;
if (mpos==DETECT_SIZE)
mpos = 0;
if (mpos == tonal->write_pos)
break;
vpos++;
if (vpos==DETECT_SIZE)
vpos = 0;
if (vpos == tonal->write_pos)
break;
pos_vad = tonal->info[vpos].activity_probability;
prob_min = MIN16((prob_avg - TRANSITION_PENALTY*(vad_prob - pos_vad))/prob_count, prob_min);
prob_max = MAX16((prob_avg + TRANSITION_PENALTY*(vad_prob - pos_vad))/prob_count, prob_max);
prob_count += MAX16(.1f, pos_vad);
prob_avg += MAX16(.1f, pos_vad)*tonal->info[mpos].music_prob;
}
info_out->music_prob = prob_avg/prob_count;
prob_min = MIN16(prob_avg/prob_count, prob_min);
prob_max = MAX16(prob_avg/prob_count, prob_max);
prob_min = MAX16(prob_min, 0.f);
prob_max = MIN16(prob_max, 1.f);
/* If we don't have enough look-ahead, do our best to make a decent decision. */
if (curr_lookahead < 10)
{
float pmin, pmax;
pmin = prob_min;
pmax = prob_max;
pos = pos0;
/* Look for min/max in the past. */
for (i=0;i<IMIN(tonal->count-1, 15);i++)
{
pos--;
if (pos < 0)
pos = DETECT_SIZE-1;
pmin = MIN16(pmin, tonal->info[pos].music_prob);
pmax = MAX16(pmax, tonal->info[pos].music_prob);
}
/* Bias against switching on active audio. */
pmin = MAX16(0.f, pmin - .1f*vad_prob);
pmax = MIN16(1.f, pmax + .1f*vad_prob);
prob_min += (1.f-.1f*curr_lookahead)*(pmin - prob_min);
prob_max += (1.f-.1f*curr_lookahead)*(pmax - prob_max);
}
info_out->music_prob_min = prob_min;
info_out->music_prob_max = prob_max;
/* printf("%f %f %f %f %f\n", prob_min, prob_max, prob_avg/prob_count, vad_prob, info_out->music_prob); */
tonal->read_subframe += len/(tonal->Fs/400);
while (tonal->read_subframe>=8)
{
tonal->read_subframe -= 8;
tonal->read_pos++;
}
if (tonal->read_pos>=DETECT_SIZE)
tonal->read_pos-=DETECT_SIZE;
}
static const float std_feature_bias[9] = {
5.684947f, 3.475288f, 1.770634f, 1.599784f, 3.773215f,
2.163313f, 1.260756f, 1.116868f, 1.918795f
};
#define LEAKAGE_OFFSET 2.5f
#define LEAKAGE_SLOPE 2.f
#ifdef FIXED_POINT
/* For fixed-point, the input is +/-2^15 shifted up by SIG_SHIFT, so we need to
compensate for that in the energy. */
#define SCALE_COMPENS (1.f/((opus_int32)1<<(15+SIG_SHIFT)))
#define SCALE_ENER(e) ((SCALE_COMPENS*SCALE_COMPENS)*(e))
#else
#define SCALE_ENER(e) (e)
#endif
static void tonality_analysis(TonalityAnalysisState *tonal, const CELTMode *celt_mode, const void *x, int len, int offset, int c1, int c2, int C, int lsb_depth, downmix_func downmix)
{
int i, b;
const kiss_fft_state *kfft;
VARDECL(kiss_fft_cpx, in);
VARDECL(kiss_fft_cpx, out);
int N = 480, N2=240;
float * OPUS_RESTRICT A = tonal->angle;
float * OPUS_RESTRICT dA = tonal->d_angle;
float * OPUS_RESTRICT d2A = tonal->d2_angle;
VARDECL(float, tonality);
VARDECL(float, noisiness);
float band_tonality[NB_TBANDS];
float logE[NB_TBANDS];
float BFCC[8];
float features[25];
float frame_tonality;
float max_frame_tonality;
/*float tw_sum=0;*/
float frame_noisiness;
const float pi4 = (float)(M_PI*M_PI*M_PI*M_PI);
float slope=0;
float frame_stationarity;
float relativeE;
float frame_probs[2];
float alpha, alphaE, alphaE2;
float frame_loudness;
float bandwidth_mask;
int is_masked[NB_TBANDS+1];
int bandwidth=0;
float maxE = 0;
float noise_floor;
int remaining;
AnalysisInfo *info;
float hp_ener;
float tonality2[240];
float midE[8];
float spec_variability=0;
float band_log2[NB_TBANDS+1];
float leakage_from[NB_TBANDS+1];
float leakage_to[NB_TBANDS+1];
float layer_out[MAX_NEURONS];
float below_max_pitch;
float above_max_pitch;
SAVE_STACK;
alpha = 1.f/IMIN(10, 1+tonal->count);
alphaE = 1.f/IMIN(25, 1+tonal->count);
/* Noise floor related decay for bandwidth detection: -2.2 dB/second */
alphaE2 = 1.f/IMIN(100, 1+tonal->count);
if (tonal->count <= 1) alphaE2 = 1;
if (tonal->Fs == 48000)
{
/* len and offset are now at 24 kHz. */
len/= 2;
offset /= 2;
} else if (tonal->Fs == 16000) {
len = 3*len/2;
offset = 3*offset/2;
}
kfft = celt_mode->mdct.kfft[0];
if (tonal->count==0)
tonal->mem_fill = 240;
tonal->hp_ener_accum += (float)downmix_and_resample(downmix, x,
&tonal->inmem[tonal->mem_fill], tonal->downmix_state,
IMIN(len, ANALYSIS_BUF_SIZE-tonal->mem_fill), offset, c1, c2, C, tonal->Fs);
if (tonal->mem_fill+len < ANALYSIS_BUF_SIZE)
{
tonal->mem_fill += len;
/* Don't have enough to update the analysis */
RESTORE_STACK;
return;
}
hp_ener = tonal->hp_ener_accum;
info = &tonal->info[tonal->write_pos++];
if (tonal->write_pos>=DETECT_SIZE)
tonal->write_pos-=DETECT_SIZE;
ALLOC(in, 480, kiss_fft_cpx);
ALLOC(out, 480, kiss_fft_cpx);
ALLOC(tonality, 240, float);
ALLOC(noisiness, 240, float);
for (i=0;i<N2;i++)
{
float w = analysis_window[i];
in[i].r = (kiss_fft_scalar)(w*tonal->inmem[i]);
in[i].i = (kiss_fft_scalar)(w*tonal->inmem[N2+i]);
in[N-i-1].r = (kiss_fft_scalar)(w*tonal->inmem[N-i-1]);
in[N-i-1].i = (kiss_fft_scalar)(w*tonal->inmem[N+N2-i-1]);
}
OPUS_MOVE(tonal->inmem, tonal->inmem+ANALYSIS_BUF_SIZE-240, 240);
remaining = len - (ANALYSIS_BUF_SIZE-tonal->mem_fill);
tonal->hp_ener_accum = (float)downmix_and_resample(downmix, x,
&tonal->inmem[240], tonal->downmix_state, remaining,
offset+ANALYSIS_BUF_SIZE-tonal->mem_fill, c1, c2, C, tonal->Fs);
tonal->mem_fill = 240 + remaining;
opus_fft(kfft, in, out, tonal->arch);
#ifndef FIXED_POINT
/* If there's any NaN on the input, the entire output will be NaN, so we only need to check one value. */
if (celt_isnan(out[0].r))
{
info->valid = 0;
RESTORE_STACK;
return;
}
#endif
for (i=1;i<N2;i++)
{
float X1r, X2r, X1i, X2i;
float angle, d_angle, d2_angle;
float angle2, d_angle2, d2_angle2;
float mod1, mod2, avg_mod;
X1r = (float)out[i].r+out[N-i].r;
X1i = (float)out[i].i-out[N-i].i;
X2r = (float)out[i].i+out[N-i].i;
X2i = (float)out[N-i].r-out[i].r;
angle = (float)(.5f/M_PI)*fast_atan2f(X1i, X1r);
d_angle = angle - A[i];
d2_angle = d_angle - dA[i];
angle2 = (float)(.5f/M_PI)*fast_atan2f(X2i, X2r);
d_angle2 = angle2 - angle;
d2_angle2 = d_angle2 - d_angle;
mod1 = d2_angle - (float)float2int(d2_angle);
noisiness[i] = ABS16(mod1);
mod1 *= mod1;
mod1 *= mod1;
mod2 = d2_angle2 - (float)float2int(d2_angle2);
noisiness[i] += ABS16(mod2);
mod2 *= mod2;
mod2 *= mod2;
avg_mod = .25f*(d2A[i]+mod1+2*mod2);
/* This introduces an extra delay of 2 frames in the detection. */
tonality[i] = 1.f/(1.f+40.f*16.f*pi4*avg_mod)-.015f;
/* No delay on this detection, but it's less reliable. */
tonality2[i] = 1.f/(1.f+40.f*16.f*pi4*mod2)-.015f;
A[i] = angle2;
dA[i] = d_angle2;
d2A[i] = mod2;
}
for (i=2;i<N2-1;i++)
{
float tt = MIN32(tonality2[i], MAX32(tonality2[i-1], tonality2[i+1]));
tonality[i] = .9f*MAX32(tonality[i], tt-.1f);
}
frame_tonality = 0;
max_frame_tonality = 0;
/*tw_sum = 0;*/
info->activity = 0;
frame_noisiness = 0;
frame_stationarity = 0;
if (!tonal->count)
{
for (b=0;b<NB_TBANDS;b++)
{
tonal->lowE[b] = 1e10;
tonal->highE[b] = -1e10;
}
}
relativeE = 0;
frame_loudness = 0;
/* The energy of the very first band is special because of DC. */
{
float E = 0;
float X1r, X2r;
X1r = 2*(float)out[0].r;
X2r = 2*(float)out[0].i;
E = X1r*X1r + X2r*X2r;
for (i=1;i<4;i++)
{
float binE = out[i].r*(float)out[i].r + out[N-i].r*(float)out[N-i].r
+ out[i].i*(float)out[i].i + out[N-i].i*(float)out[N-i].i;
E += binE;
}
E = SCALE_ENER(E);
band_log2[0] = .5f*1.442695f*(float)log(E+1e-10f);
}
for (b=0;b<NB_TBANDS;b++)
{
float E=0, tE=0, nE=0;
float L1, L2;
float stationarity;
for (i=tbands[b];i<tbands[b+1];i++)
{
float binE = out[i].r*(float)out[i].r + out[N-i].r*(float)out[N-i].r
+ out[i].i*(float)out[i].i + out[N-i].i*(float)out[N-i].i;
binE = SCALE_ENER(binE);
E += binE;
tE += binE*MAX32(0, tonality[i]);
nE += binE*2.f*(.5f-noisiness[i]);
}
#ifndef FIXED_POINT
/* Check for extreme band energies that could cause NaNs later. */
if (!(E<1e9f) || celt_isnan(E))
{
info->valid = 0;
RESTORE_STACK;
return;
}
#endif
tonal->E[tonal->E_count][b] = E;
frame_noisiness += nE/(1e-15f+E);
frame_loudness += (float)sqrt(E+1e-10f);
logE[b] = (float)log(E+1e-10f);
band_log2[b+1] = .5f*1.442695f*(float)log(E+1e-10f);
tonal->logE[tonal->E_count][b] = logE[b];
if (tonal->count==0)
tonal->highE[b] = tonal->lowE[b] = logE[b];
if (tonal->highE[b] > tonal->lowE[b] + 7.5)
{
if (tonal->highE[b] - logE[b] > logE[b] - tonal->lowE[b])
tonal->highE[b] -= .01f;
else
tonal->lowE[b] += .01f;
}
if (logE[b] > tonal->highE[b])
{
tonal->highE[b] = logE[b];
tonal->lowE[b] = MAX32(tonal->highE[b]-15, tonal->lowE[b]);
} else if (logE[b] < tonal->lowE[b])
{
tonal->lowE[b] = logE[b];
tonal->highE[b] = MIN32(tonal->lowE[b]+15, tonal->highE[b]);
}
relativeE += (logE[b]-tonal->lowE[b])/(1e-15f + (tonal->highE[b]-tonal->lowE[b]));
L1=L2=0;
for (i=0;i<NB_FRAMES;i++)
{
L1 += (float)sqrt(tonal->E[i][b]);
L2 += tonal->E[i][b];
}
stationarity = MIN16(0.99f,L1/(float)sqrt(1e-15+NB_FRAMES*L2));
stationarity *= stationarity;
stationarity *= stationarity;
frame_stationarity += stationarity;
/*band_tonality[b] = tE/(1e-15+E)*/;
band_tonality[b] = MAX16(tE/(1e-15f+E), stationarity*tonal->prev_band_tonality[b]);
#if 0
if (b>=NB_TONAL_SKIP_BANDS)
{
frame_tonality += tweight[b]*band_tonality[b];
tw_sum += tweight[b];
}
#else
frame_tonality += band_tonality[b];
if (b>=NB_TBANDS-NB_TONAL_SKIP_BANDS)
frame_tonality -= band_tonality[b-NB_TBANDS+NB_TONAL_SKIP_BANDS];
#endif
max_frame_tonality = MAX16(max_frame_tonality, (1.f+.03f*(b-NB_TBANDS))*frame_tonality);
slope += band_tonality[b]*(b-8);
/*printf("%f %f ", band_tonality[b], stationarity);*/
tonal->prev_band_tonality[b] = band_tonality[b];
}
leakage_from[0] = band_log2[0];
leakage_to[0] = band_log2[0] - LEAKAGE_OFFSET;
for (b=1;b<NB_TBANDS+1;b++)
{
float leak_slope = LEAKAGE_SLOPE*(tbands[b]-tbands[b-1])/4;
leakage_from[b] = MIN16(leakage_from[b-1]+leak_slope, band_log2[b]);
leakage_to[b] = MAX16(leakage_to[b-1]-leak_slope, band_log2[b]-LEAKAGE_OFFSET);
}
for (b=NB_TBANDS-2;b>=0;b--)
{
float leak_slope = LEAKAGE_SLOPE*(tbands[b+1]-tbands[b])/4;
leakage_from[b] = MIN16(leakage_from[b+1]+leak_slope, leakage_from[b]);
leakage_to[b] = MAX16(leakage_to[b+1]-leak_slope, leakage_to[b]);
}
celt_assert(NB_TBANDS+1 <= LEAK_BANDS);
for (b=0;b<NB_TBANDS+1;b++)
{
/* leak_boost[] is made up of two terms. The first, based on leakage_to[],
represents the boost needed to overcome the amount of analysis leakage
cause in a weaker band b by louder neighbouring bands.
The second, based on leakage_from[], applies to a loud band b for
which the quantization noise causes synthesis leakage to the weaker
neighbouring bands. */
float boost = MAX16(0, leakage_to[b] - band_log2[b]) +
MAX16(0, band_log2[b] - (leakage_from[b]+LEAKAGE_OFFSET));
info->leak_boost[b] = IMIN(255, (int)floor(.5 + 64.f*boost));
}
for (;b<LEAK_BANDS;b++) info->leak_boost[b] = 0;
for (i=0;i<NB_FRAMES;i++)
{
int j;
float mindist = 1e15f;
for (j=0;j<NB_FRAMES;j++)
{
int k;
float dist=0;
for (k=0;k<NB_TBANDS;k++)
{
float tmp;
tmp = tonal->logE[i][k] - tonal->logE[j][k];
dist += tmp*tmp;
}
if (j!=i)
mindist = MIN32(mindist, dist);
}
spec_variability += mindist;
}
spec_variability = (float)sqrt(spec_variability/NB_FRAMES/NB_TBANDS);
bandwidth_mask = 0;
bandwidth = 0;
maxE = 0;
noise_floor = 5.7e-4f/(1<<(IMAX(0,lsb_depth-8)));
noise_floor *= noise_floor;
below_max_pitch=0;
above_max_pitch=0;
for (b=0;b<NB_TBANDS;b++)
{
float E=0;
float Em;
int band_start, band_end;
/* Keep a margin of 300 Hz for aliasing */
band_start = tbands[b];
band_end = tbands[b+1];
for (i=band_start;i<band_end;i++)
{
float binE = out[i].r*(float)out[i].r + out[N-i].r*(float)out[N-i].r
+ out[i].i*(float)out[i].i + out[N-i].i*(float)out[N-i].i;
E += binE;
}
E = SCALE_ENER(E);
maxE = MAX32(maxE, E);
if (band_start < 64)
{
below_max_pitch += E;
} else {
above_max_pitch += E;
}
tonal->meanE[b] = MAX32((1-alphaE2)*tonal->meanE[b], E);
Em = MAX32(E, tonal->meanE[b]);
/* Consider the band "active" only if all these conditions are met:
1) less than 90 dB below the peak band (maximal masking possible considering
both the ATH and the loudness-dependent slope of the spreading function)
2) above the PCM quantization noise floor
We use b+1 because the first CELT band isn't included in tbands[]
*/
if (E*1e9f > maxE && (Em > 3*noise_floor*(band_end-band_start) || E > noise_floor*(band_end-band_start)))
bandwidth = b+1;
/* Check if the band is masked (see below). */
is_masked[b] = E < (tonal->prev_bandwidth >= b+1 ? .01f : .05f)*bandwidth_mask;
/* Use a simple follower with 13 dB/Bark slope for spreading function. */
bandwidth_mask = MAX32(.05f*bandwidth_mask, E);
}
/* Special case for the last two bands, for which we don't have spectrum but only
the energy above 12 kHz. The difficulty here is that the high-pass we use
leaks some LF energy, so we need to increase the threshold without accidentally cutting
off the band. */
if (tonal->Fs == 48000) {
float noise_ratio;
float Em;
float E = hp_ener*(1.f/(60*60));
noise_ratio = tonal->prev_bandwidth==20 ? 10.f : 30.f;
#ifdef FIXED_POINT
/* silk_resampler_down2_hp() shifted right by an extra 8 bits. */
E *= 256.f*(1.f/Q15ONE)*(1.f/Q15ONE);
#endif
above_max_pitch += E;
tonal->meanE[b] = MAX32((1-alphaE2)*tonal->meanE[b], E);
Em = MAX32(E, tonal->meanE[b]);
if (Em > 3*noise_ratio*noise_floor*160 || E > noise_ratio*noise_floor*160)
bandwidth = 20;
/* Check if the band is masked (see below). */
is_masked[b] = E < (tonal->prev_bandwidth == 20 ? .01f : .05f)*bandwidth_mask;
}
if (above_max_pitch > below_max_pitch)
info->max_pitch_ratio = below_max_pitch/above_max_pitch;
else
info->max_pitch_ratio = 1;
/* In some cases, resampling aliasing can create a small amount of energy in the first band
being cut. So if the last band is masked, we don't include it. */
if (bandwidth == 20 && is_masked[NB_TBANDS])
bandwidth-=2;
else if (bandwidth > 0 && bandwidth <= NB_TBANDS && is_masked[bandwidth-1])
bandwidth--;
if (tonal->count<=2)
bandwidth = 20;
frame_loudness = 20*(float)log10(frame_loudness);
tonal->Etracker = MAX32(tonal->Etracker-.003f, frame_loudness);
tonal->lowECount *= (1-alphaE);
if (frame_loudness < tonal->Etracker-30)
tonal->lowECount += alphaE;
for (i=0;i<8;i++)
{
float sum=0;
for (b=0;b<16;b++)
sum += dct_table[i*16+b]*logE[b];
BFCC[i] = sum;
}
for (i=0;i<8;i++)
{
float sum=0;
for (b=0;b<16;b++)
sum += dct_table[i*16+b]*.5f*(tonal->highE[b]+tonal->lowE[b]);
midE[i] = sum;
}
frame_stationarity /= NB_TBANDS;
relativeE /= NB_TBANDS;
if (tonal->count<10)
relativeE = .5f;
frame_noisiness /= NB_TBANDS;
#if 1
info->activity = frame_noisiness + (1-frame_noisiness)*relativeE;
#else
info->activity = .5*(1+frame_noisiness-frame_stationarity);
#endif
frame_tonality = (max_frame_tonality/(NB_TBANDS-NB_TONAL_SKIP_BANDS));
frame_tonality = MAX16(frame_tonality, tonal->prev_tonality*.8f);
tonal->prev_tonality = frame_tonality;
slope /= 8*8;
info->tonality_slope = slope;
tonal->E_count = (tonal->E_count+1)%NB_FRAMES;
tonal->count = IMIN(tonal->count+1, ANALYSIS_COUNT_MAX);
info->tonality = frame_tonality;
for (i=0;i<4;i++)
features[i] = -0.12299f*(BFCC[i]+tonal->mem[i+24]) + 0.49195f*(tonal->mem[i]+tonal->mem[i+16]) + 0.69693f*tonal->mem[i+8] - 1.4349f*tonal->cmean[i];
for (i=0;i<4;i++)
tonal->cmean[i] = (1-alpha)*tonal->cmean[i] + alpha*BFCC[i];
for (i=0;i<4;i++)
features[4+i] = 0.63246f*(BFCC[i]-tonal->mem[i+24]) + 0.31623f*(tonal->mem[i]-tonal->mem[i+16]);
for (i=0;i<3;i++)
features[8+i] = 0.53452f*(BFCC[i]+tonal->mem[i+24]) - 0.26726f*(tonal->mem[i]+tonal->mem[i+16]) -0.53452f*tonal->mem[i+8];
if (tonal->count > 5)
{
for (i=0;i<9;i++)
tonal->std[i] = (1-alpha)*tonal->std[i] + alpha*features[i]*features[i];
}
for (i=0;i<4;i++)
features[i] = BFCC[i]-midE[i];
for (i=0;i<8;i++)
{
tonal->mem[i+24] = tonal->mem[i+16];
tonal->mem[i+16] = tonal->mem[i+8];
tonal->mem[i+8] = tonal->mem[i];
tonal->mem[i] = BFCC[i];
}
for (i=0;i<9;i++)
features[11+i] = (float)sqrt(tonal->std[i]) - std_feature_bias[i];
features[18] = spec_variability - 0.78f;
features[20] = info->tonality - 0.154723f;
features[21] = info->activity - 0.724643f;
features[22] = frame_stationarity - 0.743717f;
features[23] = info->tonality_slope + 0.069216f;
features[24] = tonal->lowECount - 0.067930f;
compute_dense(&layer0, layer_out, features);
compute_gru(&layer1, tonal->rnn_state, layer_out);
compute_dense(&layer2, frame_probs, tonal->rnn_state);
/* Probability of speech or music vs noise */
info->activity_probability = frame_probs[1];
info->music_prob = frame_probs[0];
/*printf("%f %f %f\n", frame_probs[0], frame_probs[1], info->music_prob);*/
#ifdef MLP_TRAINING
for (i=0;i<25;i++)
printf("%f ", features[i]);
printf("\n");
#endif
info->bandwidth = bandwidth;
tonal->prev_bandwidth = bandwidth;
/*printf("%d %d\n", info->bandwidth, info->opus_bandwidth);*/
info->noisiness = frame_noisiness;
info->valid = 1;
RESTORE_STACK;
}
void run_analysis(TonalityAnalysisState *analysis, const CELTMode *celt_mode, const void *analysis_pcm,
int analysis_frame_size, int frame_size, int c1, int c2, int C, opus_int32 Fs,
int lsb_depth, downmix_func downmix, AnalysisInfo *analysis_info)
{
int offset;
int pcm_len;
analysis_frame_size -= analysis_frame_size&1;
if (analysis_pcm != NULL)
{
/* Avoid overflow/wrap-around of the analysis buffer */
analysis_frame_size = IMIN((DETECT_SIZE-5)*Fs/50, analysis_frame_size);
pcm_len = analysis_frame_size - analysis->analysis_offset;
offset = analysis->analysis_offset;
while (pcm_len>0) {
tonality_analysis(analysis, celt_mode, analysis_pcm, IMIN(Fs/50, pcm_len), offset, c1, c2, C, lsb_depth, downmix);
offset += Fs/50;
pcm_len -= Fs/50;
}
analysis->analysis_offset = analysis_frame_size;
analysis->analysis_offset -= frame_size;
}
analysis_info->valid = 0;
tonality_get_info(analysis, analysis_info, frame_size);
}
#endif /* DISABLE_FLOAT_API */

View file

@ -0,0 +1,102 @@
/* 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 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.
*/
#ifndef ANALYSIS_H
#define ANALYSIS_H
#include "celt.h"
#include "opus_private.h"
#include "mlp.h"
#define NB_FRAMES 8
#define NB_TBANDS 18
#define ANALYSIS_BUF_SIZE 720 /* 30 ms at 24 kHz */
/* At that point we can stop counting frames because it no longer matters. */
#define ANALYSIS_COUNT_MAX 10000
#define DETECT_SIZE 100
/* Uncomment this to print the MLP features on stdout. */
/*#define MLP_TRAINING*/
typedef struct {
int arch;
int application;
opus_int32 Fs;
#define TONALITY_ANALYSIS_RESET_START angle
float angle[240];
float d_angle[240];
float d2_angle[240];
opus_val32 inmem[ANALYSIS_BUF_SIZE];
int mem_fill; /* number of usable samples in the buffer */
float prev_band_tonality[NB_TBANDS];
float prev_tonality;
int prev_bandwidth;
float E[NB_FRAMES][NB_TBANDS];
float logE[NB_FRAMES][NB_TBANDS];
float lowE[NB_TBANDS];
float highE[NB_TBANDS];
float meanE[NB_TBANDS+1];
float mem[32];
float cmean[8];
float std[9];
float Etracker;
float lowECount;
int E_count;
int count;
int analysis_offset;
int write_pos;
int read_pos;
int read_subframe;
float hp_ener_accum;
float rnn_state[MAX_NEURONS];
opus_val32 downmix_state[3];
AnalysisInfo info[DETECT_SIZE];
} TonalityAnalysisState;
/** Initialize a TonalityAnalysisState struct.
*
* This performs some possibly slow initialization steps which should
* not be repeated every analysis step. No allocated memory is retained
* by the state struct, so no cleanup call is required.
*/
void tonality_analysis_init(TonalityAnalysisState *analysis, opus_int32 Fs);
/** Reset a TonalityAnalysisState stuct.
*
* Call this when there's a discontinuity in the data.
*/
void tonality_analysis_reset(TonalityAnalysisState *analysis);
void tonality_get_info(TonalityAnalysisState *tonal, AnalysisInfo *info_out, int len);
void run_analysis(TonalityAnalysisState *analysis, const CELTMode *celt_mode, const void *analysis_pcm,
int analysis_frame_size, int frame_size, int c1, int c2, int C, opus_int32 Fs,
int lsb_depth, downmix_func downmix, AnalysisInfo *analysis_info);
#endif

View file

@ -58,12 +58,12 @@
# define S_MUL(a,b) MULT16_32_Q15(b, a) # define S_MUL(a,b) MULT16_32_Q15(b, a)
# define C_MUL(m,a,b) \ # define C_MUL(m,a,b) \
do{ (m).r = SUB32(S_MUL((a).r,(b).r) , S_MUL((a).i,(b).i)); \ do{ (m).r = SUB32_ovflw(S_MUL((a).r,(b).r) , S_MUL((a).i,(b).i)); \
(m).i = ADD32(S_MUL((a).r,(b).i) , S_MUL((a).i,(b).r)); }while(0) (m).i = ADD32_ovflw(S_MUL((a).r,(b).i) , S_MUL((a).i,(b).r)); }while(0)
# define C_MULC(m,a,b) \ # define C_MULC(m,a,b) \
do{ (m).r = ADD32(S_MUL((a).r,(b).r) , S_MUL((a).i,(b).i)); \ do{ (m).r = ADD32_ovflw(S_MUL((a).r,(b).r) , S_MUL((a).i,(b).i)); \
(m).i = SUB32(S_MUL((a).i,(b).r) , S_MUL((a).r,(b).i)); }while(0) (m).i = SUB32_ovflw(S_MUL((a).i,(b).r) , S_MUL((a).r,(b).i)); }while(0)
# define C_MULBYSCALAR( c, s ) \ # define C_MULBYSCALAR( c, s ) \
do{ (c).r = S_MUL( (c).r , s ) ;\ do{ (c).r = S_MUL( (c).r , s ) ;\
@ -77,17 +77,17 @@
DIVSCALAR( (c).i , div); }while (0) DIVSCALAR( (c).i , div); }while (0)
#define C_ADD( res, a,b)\ #define C_ADD( res, a,b)\
do {(res).r=ADD32((a).r,(b).r); (res).i=ADD32((a).i,(b).i); \ do {(res).r=ADD32_ovflw((a).r,(b).r); (res).i=ADD32_ovflw((a).i,(b).i); \
}while(0) }while(0)
#define C_SUB( res, a,b)\ #define C_SUB( res, a,b)\
do {(res).r=SUB32((a).r,(b).r); (res).i=SUB32((a).i,(b).i); \ do {(res).r=SUB32_ovflw((a).r,(b).r); (res).i=SUB32_ovflw((a).i,(b).i); \
}while(0) }while(0)
#define C_ADDTO( res , a)\ #define C_ADDTO( res , a)\
do {(res).r = ADD32((res).r, (a).r); (res).i = ADD32((res).i,(a).i);\ do {(res).r = ADD32_ovflw((res).r, (a).r); (res).i = ADD32_ovflw((res).i,(a).i);\
}while(0) }while(0)
#define C_SUBFROM( res , a)\ #define C_SUBFROM( res , a)\
do {(res).r = ADD32((res).r,(a).r); (res).i = SUB32((res).i,(a).i); \ do {(res).r = ADD32_ovflw((res).r,(a).r); (res).i = SUB32_ovflw((res).i,(a).i); \
}while(0) }while(0)
#if defined(OPUS_ARM_INLINE_ASM) #if defined(OPUS_ARM_INLINE_ASM)
@ -97,9 +97,8 @@
#if defined(OPUS_ARM_INLINE_EDSP) #if defined(OPUS_ARM_INLINE_EDSP)
#include "arm/kiss_fft_armv5e.h" #include "arm/kiss_fft_armv5e.h"
#endif #endif
#if defined(MIPSr1_ASM)
#if defined(OPUS_CF_INLINE_ASM) #include "mips/kiss_fft_mipsr1.h"
#include "cf/kiss_fft_cf.h"
#endif #endif
#else /* not FIXED_POINT*/ #else /* not FIXED_POINT*/

View file

@ -46,30 +46,54 @@
# endif # endif
# 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_SIG_SCALE 32768.f
#define celt_fatal(str) _celt_fatal(str, __FILE__, __LINE__); #define CELT_FATAL(str) celt_fatal(str, __FILE__, __LINE__);
#ifdef ENABLE_ASSERTIONS
#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 <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#ifdef __GNUC__ #ifdef __GNUC__
__attribute__((noreturn)) __attribute__((noreturn))
#endif #endif
static OPUS_INLINE void _celt_fatal(const char *str, const char *file, int line) 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); fprintf (stderr, "Fatal (internal) error in %s, line %d: %s\n", file, line, str);
abort(); abort();
} }
#define celt_assert(cond) {if (!(cond)) {celt_fatal("assertion failed: " #cond);}} #endif
#define celt_assert2(cond, message) {if (!(cond)) {celt_fatal("assertion failed: " #cond "\n" message);}}
#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 #else
#define celt_assert(cond) #define celt_assert(cond)
#define celt_assert2(cond, message) #define celt_assert2(cond, message)
#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)
#endif #endif
#define IMUL32(a,b) ((a)*(b)) #define IMUL32(a,b) ((a)*(b))
#define ABS(x) ((x) < 0 ? (-(x)) : (x))
#define MIN16(a,b) ((a) < (b) ? (a) : (b)) /**< Minimum 16-bit value. */ #define MIN16(a,b) ((a) < (b) ? (a) : (b)) /**< Minimum 16-bit value. */
#define MAX16(a,b) ((a) > (b) ? (a) : (b)) /**< Maximum 16-bit value. */ #define MAX16(a,b) ((a) > (b) ? (a) : (b)) /**< Maximum 16-bit value. */
#define MIN32(a,b) ((a) < (b) ? (a) : (b)) /**< Minimum 32-bit value. */ #define MIN32(a,b) ((a) < (b) ? (a) : (b)) /**< Minimum 32-bit value. */
@ -79,20 +103,35 @@ static OPUS_INLINE void _celt_fatal(const char *str, const char *file, int line)
#define UADD32(a,b) ((a)+(b)) #define UADD32(a,b) ((a)+(b))
#define USUB32(a,b) ((a)-(b)) #define USUB32(a,b) ((a)-(b))
/* 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)
#define OPUS_FAST_INT64 1
#else
#define OPUS_FAST_INT64 0
#endif
#define PRINT_MIPS(file) #define PRINT_MIPS(file)
#ifdef FIXED_POINT #ifdef FIXED_POINT
typedef opus_int16 opus_val16; typedef opus_int16 opus_val16;
typedef opus_int32 opus_val32; typedef opus_int32 opus_val32;
typedef opus_int64 opus_val64;
typedef opus_val32 celt_sig; typedef opus_val32 celt_sig;
typedef opus_val16 celt_norm; typedef opus_val16 celt_norm;
typedef opus_val32 celt_ener; typedef opus_val32 celt_ener;
#define celt_isnan(x) 0
#define Q15ONE 32767 #define Q15ONE 32767
#define SIG_SHIFT 12 #define SIG_SHIFT 12
/* Safe saturation value for 32-bit signals. Should be less than
2^31*(1-0.85) to avoid blowing up on DC at deemphasis.*/
#define SIG_SAT (300000000)
#define NORM_SCALING 16384 #define NORM_SCALING 16384
@ -119,7 +158,9 @@ static OPUS_INLINE opus_int16 SAT16(opus_int32 x) {
#include "fixed_generic.h" #include "fixed_generic.h"
#ifdef OPUS_ARM_INLINE_EDSP #ifdef OPUS_ARM_PRESUME_AARCH64_NEON_INTR
#include "arm/fixed_arm64.h"
#elif defined (OPUS_ARM_INLINE_EDSP)
#include "arm/fixed_armv5e.h" #include "arm/fixed_armv5e.h"
#elif defined (OPUS_ARM_INLINE_ASM) #elif defined (OPUS_ARM_INLINE_ASM)
#include "arm/fixed_armv4.h" #include "arm/fixed_armv4.h"
@ -129,8 +170,6 @@ static OPUS_INLINE opus_int16 SAT16(opus_int32 x) {
#include "fixed_c5x.h" #include "fixed_c5x.h"
#elif defined (TI_C6X_ASM) #elif defined (TI_C6X_ASM)
#include "fixed_c6x.h" #include "fixed_c6x.h"
#elif defined (OPUS_CF_INLINE_ASM)
#include "cf/fixed_cf.h"
#endif #endif
#endif #endif
@ -139,6 +178,7 @@ static OPUS_INLINE opus_int16 SAT16(opus_int32 x) {
typedef float opus_val16; typedef float opus_val16;
typedef float opus_val32; typedef float opus_val32;
typedef float opus_val64;
typedef float celt_sig; typedef float celt_sig;
typedef float celt_norm; typedef float celt_norm;
@ -178,6 +218,7 @@ static OPUS_INLINE int celt_isnan(float x)
#define NEG16(x) (-(x)) #define NEG16(x) (-(x))
#define NEG32(x) (-(x)) #define NEG32(x) (-(x))
#define NEG32_ovflw(x) (-(x))
#define EXTRACT16(x) (x) #define EXTRACT16(x) (x)
#define EXTEND32(x) (x) #define EXTEND32(x) (x)
#define SHR16(a,shift) (a) #define SHR16(a,shift) (a)
@ -194,6 +235,7 @@ static OPUS_INLINE int celt_isnan(float x)
#define SATURATE16(x) (x) #define SATURATE16(x) (x)
#define ROUND16(a,shift) (a) #define ROUND16(a,shift) (a)
#define SROUND16(a,shift) (a)
#define HALF16(x) (.5f*(x)) #define HALF16(x) (.5f*(x))
#define HALF32(x) (.5f*(x)) #define HALF32(x) (.5f*(x))
@ -201,6 +243,8 @@ static OPUS_INLINE int celt_isnan(float x)
#define SUB16(a,b) ((a)-(b)) #define SUB16(a,b) ((a)-(b))
#define ADD32(a,b) ((a)+(b)) #define ADD32(a,b) ((a)+(b))
#define SUB32(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 MULT16_16_16(a,b) ((a)*(b)) #define MULT16_16_16(a,b) ((a)*(b))
#define MULT16_16(a,b) ((opus_val32)(a)*(opus_val32)(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 MAC16_16(c,a,b) ((c)+(opus_val32)(a)*(opus_val32)(b))
@ -235,9 +279,9 @@ static OPUS_INLINE int celt_isnan(float x)
#ifndef GLOBAL_STACK_SIZE #ifndef GLOBAL_STACK_SIZE
#ifdef FIXED_POINT #ifdef FIXED_POINT
#define GLOBAL_STACK_SIZE 100000 #define GLOBAL_STACK_SIZE 120000
#else #else
#define GLOBAL_STACK_SIZE 100000 #define GLOBAL_STACK_SIZE 120000
#endif #endif
#endif #endif

View file

@ -0,0 +1,353 @@
#!/usr/bin/perl
# Copyright (C) 2002-2013 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.
my $bigend; # little/big endian
my $nxstack;
my $apple = 0;
my $symprefix = "";
$nxstack = 0;
eval 'exec /usr/local/bin/perl -S $0 ${1+"$@"}'
if $running_under_some_shell;
while ($ARGV[0] =~ /^-/) {
$_ = shift;
last if /^--$/;
if (/^-n$/) {
$nflag++;
next;
}
if (/^--apple$/) {
$apple = 1;
$symprefix = "_";
next;
}
die "I don't recognize this switch: $_\\n";
}
$printit++ unless $nflag;
$\ = "\n"; # automatically add newline on print
$n=0;
$thumb = 0; # ARM mode by default, not Thumb.
@proc_stack = ();
printf (" .syntax unified\n");
LINE:
while (<>) {
# For ADRLs we need to add a new line after the substituted one.
$addPadding = 0;
# First, we do not dare to touch *anything* inside double quotes, do we?
# Second, if you want a dollar character in the string,
# insert two of them -- that's how ARM C and assembler treat strings.
s/^([A-Za-z_]\w*)[ \t]+DCB[ \t]*\"/$1: .ascii \"/ && do { s/\$\$/\$/g; next };
s/\bDCB\b[ \t]*\"/.ascii \"/ && do { s/\$\$/\$/g; next };
s/^(\S+)\s+RN\s+(\S+)/$1 .req r$2/ && do { s/\$\$/\$/g; next };
# If there's nothing on a line but a comment, don't try to apply any further
# substitutions (this is a cheap hack to avoid mucking up the license header)
s/^([ \t]*);/$1@/ && do { s/\$\$/\$/g; next };
# If substituted -- leave immediately !
s/@/,:/;
s/;/@/;
while ( /@.*'/ ) {
s/(@.*)'/$1/g;
}
s/\{FALSE\}/0/g;
s/\{TRUE\}/1/g;
s/\{(\w\w\w\w+)\}/$1/g;
s/\bINCLUDE[ \t]*([^ \t\n]+)/.include \"$1\"/;
s/\bGET[ \t]*([^ \t\n]+)/.include \"${ my $x=$1; $x =~ s|\.s|-gnu.S|; \$x }\"/;
s/\bIMPORT\b/.extern/;
s/\bEXPORT\b\s*/.global $symprefix/;
s/^(\s+)\[/$1IF/;
s/^(\s+)\|/$1ELSE/;
s/^(\s+)\]/$1ENDIF/;
s/IF *:DEF:/ .ifdef/;
s/IF *:LNOT: *:DEF:/ .ifndef/;
s/ELSE/ .else/;
s/ENDIF/ .endif/;
if( /\bIF\b/ ) {
s/\bIF\b/ .if/;
s/=/==/;
}
if ( $n == 2) {
s/\$/\\/g;
}
if ($n == 1) {
s/\$//g;
s/label//g;
$n = 2;
}
if ( /MACRO/ ) {
s/MACRO *\n/.macro/;
$n=1;
}
if ( /\bMEND\b/ ) {
s/\bMEND\b/.endm/;
$n=0;
}
# ".rdata" doesn't work in 'as' version 2.13.2, as it is ".rodata" there.
#
if ( /\bAREA\b/ ) {
my $align;
$align = "2";
if ( /ALIGN=(\d+)/ ) {
$align = $1;
}
if ( /CODE/ ) {
$nxstack = 1;
}
s/^(.+)CODE(.+)READONLY(.*)/ .text/;
s/^(.+)DATA(.+)READONLY(.*)/ .section .rdata/;
s/^(.+)\|\|\.data\|\|(.+)/ .data/;
s/^(.+)\|\|\.bss\|\|(.+)/ .bss/;
s/$/; .p2align $align/;
# Enable NEON instructions but don't produce a binary that requires
# ARMv7. RVCT does not have equivalent directives, so we just do this
# for all CODE areas.
if ( /.text/ ) {
# Separating .arch, .fpu, etc., by semicolons does not work (gas
# thinks the semicolon is part of the arch name, even when there's
# whitespace separating them). Sadly this means our line numbers
# won't match the original source file (we could use the .line
# directive, which is documented to be obsolete, but then gdb will
# show the wrong line in the translated source file).
s/$/; .arch armv7-a\n .fpu neon\n .object_arch armv4t/ unless ($apple);
}
}
s/\|\|\.constdata\$(\d+)\|\|/.L_CONST$1/; # ||.constdata$3||
s/\|\|\.bss\$(\d+)\|\|/.L_BSS$1/; # ||.bss$2||
s/\|\|\.data\$(\d+)\|\|/.L_DATA$1/; # ||.data$2||
s/\|\|([a-zA-Z0-9_]+)\@([a-zA-Z0-9_]+)\|\|/@ $&/;
s/^(\s+)\%(\s)/ .space $1/;
s/\|(.+)\.(\d+)\|/\.$1_$2/; # |L80.123| -> .L80_123
s/\bCODE32\b/.code 32/ && do {$thumb = 0};
s/\bCODE16\b/.code 16/ && do {$thumb = 1};
if (/\bPROC\b/)
{
my $prefix;
my $proc;
/^([A-Za-z_\.]\w+)\b/;
$proc = $1;
$prefix = "";
if ($proc)
{
$prefix = $prefix.sprintf("\t.type\t%s, %%function", $proc) unless ($apple);
# Make sure we $prefix isn't empty here (for the $apple case).
# We handle mangling the label here, make sure it doesn't match
# the label handling below (if $prefix would be empty).
$prefix = $prefix."; ";
push(@proc_stack, $proc);
s/^[A-Za-z_\.]\w+/$symprefix$&:/;
}
$prefix = $prefix."\t.thumb_func; " if ($thumb);
s/\bPROC\b/@ $&/;
$_ = $prefix.$_;
}
s/^(\s*)(S|Q|SH|U|UQ|UH)ASX\b/$1$2ADDSUBX/;
s/^(\s*)(S|Q|SH|U|UQ|UH)SAX\b/$1$2SUBADDX/;
if (/\bENDP\b/)
{
my $proc;
s/\bENDP\b/@ $&/;
$proc = pop(@proc_stack);
$_ = "\t.size $proc, .-$proc".$_ if ($proc && !$apple);
}
s/\bSUBT\b/@ $&/;
s/\bDATA\b/@ $&/; # DATA directive is deprecated -- Asm guide, p.7-25
s/\bKEEP\b/@ $&/;
s/\bEXPORTAS\b/@ $&/;
s/\|\|(.)+\bEQU\b/@ $&/;
s/\|\|([\w\$]+)\|\|/$1/;
s/\bENTRY\b/@ $&/;
s/\bASSERT\b/@ $&/;
s/\bGBLL\b/@ $&/;
s/\bGBLA\b/@ $&/;
s/^\W+OPT\b/@ $&/;
s/:OR:/|/g;
s/:SHL:/<</g;
s/:SHR:/>>/g;
s/:AND:/&/g;
s/:LAND:/&&/g;
s/CPSR/cpsr/;
s/SPSR/spsr/;
s/ALIGN$/.balign 4/;
s/ALIGN\s+([0-9x]+)$/.balign $1/;
s/psr_cxsf/psr_all/;
s/LTORG/.ltorg/;
s/^([A-Za-z_]\w*)[ \t]+EQU/ .set $1,/;
s/^([A-Za-z_]\w*)[ \t]+SETL/ .set $1,/;
s/^([A-Za-z_]\w*)[ \t]+SETA/ .set $1,/;
s/^([A-Za-z_]\w*)[ \t]+\*/ .set $1,/;
# {PC} + 0xdeadfeed --> . + 0xdeadfeed
s/\{PC\} \+/ \. +/;
# Single hex constant on the line !
#
# >>> NOTE <<<
# Double-precision floats in gcc are always mixed-endian, which means
# bytes in two words are little-endian, but words are big-endian.
# So, 0x0000deadfeed0000 would be stored as 0x0000dead at low address
# and 0xfeed0000 at high address.
#
s/\bDCFD\b[ \t]+0x([a-fA-F0-9]{8})([a-fA-F0-9]{8})/.long 0x$1, 0x$2/;
# Only decimal constants on the line, no hex !
s/\bDCFD\b[ \t]+([0-9\.\-]+)/.double $1/;
# Single hex constant on the line !
# s/\bDCFS\b[ \t]+0x([a-f0-9]{8})([a-f0-9]{8})/.long 0x$1, 0x$2/;
# Only decimal constants on the line, no hex !
# s/\bDCFS\b[ \t]+([0-9\.\-]+)/.double $1/;
s/\bDCFS[ \t]+0x/.word 0x/;
s/\bDCFS\b/.float/;
s/^([A-Za-z_]\w*)[ \t]+DCD/$1 .word/;
s/\bDCD\b/.word/;
s/^([A-Za-z_]\w*)[ \t]+DCW/$1 .short/;
s/\bDCW\b/.short/;
s/^([A-Za-z_]\w*)[ \t]+DCB/$1 .byte/;
s/\bDCB\b/.byte/;
s/^([A-Za-z_]\w*)[ \t]+\%/.comm $1,/;
s/^[A-Za-z_\.]\w+/$&:/;
s/^(\d+)/$1:/;
s/\%(\d+)/$1b_or_f/;
s/\%[Bb](\d+)/$1b/;
s/\%[Ff](\d+)/$1f/;
s/\%[Ff][Tt](\d+)/$1f/;
s/&([\dA-Fa-f]+)/0x$1/;
if ( /\b2_[01]+\b/ ) {
s/\b2_([01]+)\b/conv$1&&&&/g;
while ( /[01][01][01][01]&&&&/ ) {
s/0000&&&&/&&&&0/g;
s/0001&&&&/&&&&1/g;
s/0010&&&&/&&&&2/g;
s/0011&&&&/&&&&3/g;
s/0100&&&&/&&&&4/g;
s/0101&&&&/&&&&5/g;
s/0110&&&&/&&&&6/g;
s/0111&&&&/&&&&7/g;
s/1000&&&&/&&&&8/g;
s/1001&&&&/&&&&9/g;
s/1010&&&&/&&&&A/g;
s/1011&&&&/&&&&B/g;
s/1100&&&&/&&&&C/g;
s/1101&&&&/&&&&D/g;
s/1110&&&&/&&&&E/g;
s/1111&&&&/&&&&F/g;
}
s/000&&&&/&&&&0/g;
s/001&&&&/&&&&1/g;
s/010&&&&/&&&&2/g;
s/011&&&&/&&&&3/g;
s/100&&&&/&&&&4/g;
s/101&&&&/&&&&5/g;
s/110&&&&/&&&&6/g;
s/111&&&&/&&&&7/g;
s/00&&&&/&&&&0/g;
s/01&&&&/&&&&1/g;
s/10&&&&/&&&&2/g;
s/11&&&&/&&&&3/g;
s/0&&&&/&&&&0/g;
s/1&&&&/&&&&1/g;
s/conv&&&&/0x/g;
}
if ( /commandline/)
{
if( /-bigend/)
{
$bigend=1;
}
}
if ( /\bDCDU\b/ )
{
my $cmd=$_;
my $value;
my $prefix;
my $w1;
my $w2;
my $w3;
my $w4;
s/\s+DCDU\b/@ $&/;
$cmd =~ /\bDCDU\b\s+0x(\d+)/;
$value = $1;
$value =~ /(\w\w)(\w\w)(\w\w)(\w\w)/;
$w1 = $1;
$w2 = $2;
$w3 = $3;
$w4 = $4;
if( $bigend ne "")
{
# big endian
$prefix = "\t.byte\t0x".$w1.";".
"\t.byte\t0x".$w2.";".
"\t.byte\t0x".$w3.";".
"\t.byte\t0x".$w4."; ";
}
else
{
# little endian
$prefix = "\t.byte\t0x".$w4.";".
"\t.byte\t0x".$w3.";".
"\t.byte\t0x".$w2.";".
"\t.byte\t0x".$w1."; ";
}
$_=$prefix.$_;
}
if ( /\badrl\b/i )
{
s/\badrl\s+(\w+)\s*,\s*(\w+)/ldr $1,=$2/i;
$addPadding = 1;
}
s/\bEND\b/@ END/;
} continue {
printf ("%s", $_) if $printit;
if ($addPadding != 0)
{
printf (" mov r0,r0\n");
$addPadding = 0;
}
}
#If we had a code section, mark that this object doesn't need an executable
# stack.
if ($nxstack && !$apple) {
printf (" .section\t.note.GNU-stack,\"\",\%\%progbits\n");
}

View file

@ -0,0 +1,160 @@
/* 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.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "pitch.h"
#include "kiss_fft.h"
#include "mdct.h"
#if defined(OPUS_HAVE_RTCD)
# if defined(OPUS_ARM_MAY_HAVE_NEON_INTR) && !defined(OPUS_ARM_PRESUME_NEON_INTR)
opus_val32 (*const CELT_INNER_PROD_IMPL[OPUS_ARCHMASK+1])(const opus_val16 *x, const opus_val16 *y, int N) = {
celt_inner_prod_c, /* ARMv4 */
celt_inner_prod_c, /* EDSP */
celt_inner_prod_c, /* Media */
celt_inner_prod_neon /* NEON */
};
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, /* ARMv4 */
dual_inner_prod_c, /* EDSP */
dual_inner_prod_c, /* Media */
dual_inner_prod_neon /* NEON */
};
# endif
# if defined(FIXED_POINT)
# if ((defined(OPUS_ARM_MAY_HAVE_NEON) && !defined(OPUS_ARM_PRESUME_NEON)) || \
(defined(OPUS_ARM_MAY_HAVE_MEDIA) && !defined(OPUS_ARM_PRESUME_MEDIA)) || \
(defined(OPUS_ARM_MAY_HAVE_EDSP) && !defined(OPUS_ARM_PRESUME_EDSP)))
opus_val32 (*const CELT_PITCH_XCORR_IMPL[OPUS_ARCHMASK+1])(const opus_val16 *,
const opus_val16 *, opus_val32 *, int, int, int) = {
celt_pitch_xcorr_c, /* ARMv4 */
MAY_HAVE_EDSP(celt_pitch_xcorr), /* EDSP */
MAY_HAVE_MEDIA(celt_pitch_xcorr), /* Media */
MAY_HAVE_NEON(celt_pitch_xcorr) /* NEON */
};
# endif
# else /* !FIXED_POINT */
# if defined(OPUS_ARM_MAY_HAVE_NEON_INTR) && !defined(OPUS_ARM_PRESUME_NEON_INTR)
void (*const CELT_PITCH_XCORR_IMPL[OPUS_ARCHMASK+1])(const opus_val16 *,
const opus_val16 *, opus_val32 *, int, int, int) = {
celt_pitch_xcorr_c, /* ARMv4 */
celt_pitch_xcorr_c, /* EDSP */
celt_pitch_xcorr_c, /* Media */
celt_pitch_xcorr_float_neon /* Neon */
};
# endif
# endif /* FIXED_POINT */
#if defined(FIXED_POINT) && defined(OPUS_HAVE_RTCD) && \
defined(OPUS_ARM_MAY_HAVE_NEON_INTR) && !defined(OPUS_ARM_PRESUME_NEON_INTR)
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, /* ARMv4 */
xcorr_kernel_c, /* EDSP */
xcorr_kernel_c, /* Media */
xcorr_kernel_neon_fixed, /* Neon */
};
#endif
# if defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
# if defined(HAVE_ARM_NE10)
# if defined(CUSTOM_MODES)
int (*const OPUS_FFT_ALLOC_ARCH_IMPL[OPUS_ARCHMASK+1])(kiss_fft_state *st) = {
opus_fft_alloc_arch_c, /* ARMv4 */
opus_fft_alloc_arch_c, /* EDSP */
opus_fft_alloc_arch_c, /* Media */
opus_fft_alloc_arm_neon /* Neon with NE10 library support */
};
void (*const OPUS_FFT_FREE_ARCH_IMPL[OPUS_ARCHMASK+1])(kiss_fft_state *st) = {
opus_fft_free_arch_c, /* ARMv4 */
opus_fft_free_arch_c, /* EDSP */
opus_fft_free_arch_c, /* Media */
opus_fft_free_arm_neon /* Neon with NE10 */
};
# endif /* CUSTOM_MODES */
void (*const OPUS_FFT[OPUS_ARCHMASK+1])(const kiss_fft_state *cfg,
const kiss_fft_cpx *fin,
kiss_fft_cpx *fout) = {
opus_fft_c, /* ARMv4 */
opus_fft_c, /* EDSP */
opus_fft_c, /* Media */
opus_fft_neon /* Neon with NE10 */
};
void (*const OPUS_IFFT[OPUS_ARCHMASK+1])(const kiss_fft_state *cfg,
const kiss_fft_cpx *fin,
kiss_fft_cpx *fout) = {
opus_ifft_c, /* ARMv4 */
opus_ifft_c, /* EDSP */
opus_ifft_c, /* Media */
opus_ifft_neon /* Neon with NE10 */
};
void (*const CLT_MDCT_FORWARD_IMPL[OPUS_ARCHMASK+1])(const mdct_lookup *l,
kiss_fft_scalar *in,
kiss_fft_scalar * OPUS_RESTRICT out,
const opus_val16 *window,
int overlap, int shift,
int stride, int arch) = {
clt_mdct_forward_c, /* ARMv4 */
clt_mdct_forward_c, /* EDSP */
clt_mdct_forward_c, /* Media */
clt_mdct_forward_neon /* Neon with NE10 */
};
void (*const CLT_MDCT_BACKWARD_IMPL[OPUS_ARCHMASK+1])(const mdct_lookup *l,
kiss_fft_scalar *in,
kiss_fft_scalar * OPUS_RESTRICT out,
const opus_val16 *window,
int overlap, int shift,
int stride, int arch) = {
clt_mdct_backward_c, /* ARMv4 */
clt_mdct_backward_c, /* EDSP */
clt_mdct_backward_c, /* Media */
clt_mdct_backward_neon /* Neon with NE10 */
};
# endif /* HAVE_ARM_NE10 */
# endif /* OPUS_ARM_MAY_HAVE_NEON_INTR */
#endif /* OPUS_HAVE_RTCD */

View file

@ -0,0 +1,185 @@
/* 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.
*/
/* Original code from libtheora modified to suit to Opus */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifdef OPUS_HAVE_RTCD
#include "armcpu.h"
#include "cpu_support.h"
#include "os_support.h"
#include "opus_types.h"
#include "arch.h"
#define OPUS_CPU_ARM_V4_FLAG (1<<OPUS_ARCH_ARM_V4)
#define OPUS_CPU_ARM_EDSP_FLAG (1<<OPUS_ARCH_ARM_EDSP)
#define OPUS_CPU_ARM_MEDIA_FLAG (1<<OPUS_ARCH_ARM_MEDIA)
#define OPUS_CPU_ARM_NEON_FLAG (1<<OPUS_ARCH_ARM_NEON)
#if defined(_MSC_VER)
/*For GetExceptionCode() and EXCEPTION_ILLEGAL_INSTRUCTION.*/
# define WIN32_LEAN_AND_MEAN
# define WIN32_EXTRA_LEAN
# include <windows.h>
static OPUS_INLINE opus_uint32 opus_cpu_capabilities(void){
opus_uint32 flags;
flags=0;
/* MSVC has no OPUS_INLINE __asm support for ARM, but it does let you __emit
* instructions via their assembled hex code.
* All of these instructions should be essentially nops. */
# if defined(OPUS_ARM_MAY_HAVE_EDSP) || defined(OPUS_ARM_MAY_HAVE_MEDIA) \
|| defined(OPUS_ARM_MAY_HAVE_NEON) || defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
__try{
/*PLD [r13]*/
__emit(0xF5DDF000);
flags|=OPUS_CPU_ARM_EDSP_FLAG;
}
__except(GetExceptionCode()==EXCEPTION_ILLEGAL_INSTRUCTION){
/*Ignore exception.*/
}
# if defined(OPUS_ARM_MAY_HAVE_MEDIA) \
|| defined(OPUS_ARM_MAY_HAVE_NEON) || defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
__try{
/*SHADD8 r3,r3,r3*/
__emit(0xE6333F93);
flags|=OPUS_CPU_ARM_MEDIA_FLAG;
}
__except(GetExceptionCode()==EXCEPTION_ILLEGAL_INSTRUCTION){
/*Ignore exception.*/
}
# if defined(OPUS_ARM_MAY_HAVE_NEON) || defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
__try{
/*VORR q0,q0,q0*/
__emit(0xF2200150);
flags|=OPUS_CPU_ARM_NEON_FLAG;
}
__except(GetExceptionCode()==EXCEPTION_ILLEGAL_INSTRUCTION){
/*Ignore exception.*/
}
# endif
# endif
# endif
return flags;
}
#elif defined(__linux__)
/* Linux based */
opus_uint32 opus_cpu_capabilities(void)
{
opus_uint32 flags = 0;
FILE *cpuinfo;
/* Reading /proc/self/auxv would be easier, but that doesn't work reliably on
* Android */
cpuinfo = fopen("/proc/cpuinfo", "r");
if(cpuinfo != NULL)
{
/* 512 should be enough for anybody (it's even enough for all the flags that
* x86 has accumulated... so far). */
char buf[512];
while(fgets(buf, 512, cpuinfo) != NULL)
{
# if defined(OPUS_ARM_MAY_HAVE_EDSP) || defined(OPUS_ARM_MAY_HAVE_MEDIA) \
|| defined(OPUS_ARM_MAY_HAVE_NEON) || defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
/* Search for edsp and neon flag */
if(memcmp(buf, "Features", 8) == 0)
{
char *p;
p = strstr(buf, " edsp");
if(p != NULL && (p[5] == ' ' || p[5] == '\n'))
flags |= OPUS_CPU_ARM_EDSP_FLAG;
# if defined(OPUS_ARM_MAY_HAVE_NEON) || defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
p = strstr(buf, " neon");
if(p != NULL && (p[5] == ' ' || p[5] == '\n'))
flags |= OPUS_CPU_ARM_NEON_FLAG;
# endif
}
# endif
# if defined(OPUS_ARM_MAY_HAVE_MEDIA) \
|| defined(OPUS_ARM_MAY_HAVE_NEON) || defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
/* Search for media capabilities (>= ARMv6) */
if(memcmp(buf, "CPU architecture:", 17) == 0)
{
int version;
version = atoi(buf+17);
if(version >= 6)
flags |= OPUS_CPU_ARM_MEDIA_FLAG;
}
# endif
}
fclose(cpuinfo);
}
return flags;
}
#else
/* The feature registers which can tell us what the processor supports are
* accessible in priveleged modes only, so we can't have a general user-space
* detection method like on x86.*/
# error "Configured to use ARM asm but no CPU detection method available for " \
"your platform. Reconfigure with --disable-rtcd (or send patches)."
#endif
int opus_select_arch(void)
{
opus_uint32 flags = opus_cpu_capabilities();
int arch = 0;
if(!(flags & OPUS_CPU_ARM_EDSP_FLAG)) {
/* Asserts ensure arch values are sequential */
celt_assert(arch == OPUS_ARCH_ARM_V4);
return arch;
}
arch++;
if(!(flags & OPUS_CPU_ARM_MEDIA_FLAG)) {
celt_assert(arch == OPUS_ARCH_ARM_EDSP);
return arch;
}
arch++;
if(!(flags & OPUS_CPU_ARM_NEON_FLAG)) {
celt_assert(arch == OPUS_ARCH_ARM_MEDIA);
return arch;
}
arch++;
celt_assert(arch == OPUS_ARCH_ARM_NEON);
return arch;
}
#endif

View file

@ -0,0 +1,77 @@
/* 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.
*/
#if !defined(ARMCPU_H)
# define ARMCPU_H
# if defined(OPUS_ARM_MAY_HAVE_EDSP)
# define MAY_HAVE_EDSP(name) name ## _edsp
# else
# define MAY_HAVE_EDSP(name) name ## _c
# endif
# if defined(OPUS_ARM_MAY_HAVE_MEDIA)
# define MAY_HAVE_MEDIA(name) name ## _media
# else
# define MAY_HAVE_MEDIA(name) MAY_HAVE_EDSP(name)
# endif
# if defined(OPUS_ARM_MAY_HAVE_NEON)
# define MAY_HAVE_NEON(name) name ## _neon
# else
# define MAY_HAVE_NEON(name) MAY_HAVE_MEDIA(name)
# endif
# if defined(OPUS_ARM_PRESUME_EDSP)
# define PRESUME_EDSP(name) name ## _edsp
# else
# define PRESUME_EDSP(name) name ## _c
# endif
# if defined(OPUS_ARM_PRESUME_MEDIA)
# define PRESUME_MEDIA(name) name ## _media
# else
# define PRESUME_MEDIA(name) PRESUME_EDSP(name)
# endif
# if defined(OPUS_ARM_PRESUME_NEON)
# define PRESUME_NEON(name) name ## _neon
# else
# define PRESUME_NEON(name) PRESUME_MEDIA(name)
# endif
# if defined(OPUS_HAVE_RTCD)
int opus_select_arch(void);
#define OPUS_ARCH_ARM_V4 (0)
#define OPUS_ARCH_ARM_EDSP (1)
#define OPUS_ARCH_ARM_MEDIA (2)
#define OPUS_ARCH_ARM_NEON (3)
# endif
#endif

View file

@ -0,0 +1,37 @@
/* Copyright (C) 2013 Mozilla Corporation */
/*
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.
*/
; Set the following to 1 if we have EDSP instructions
; (LDRD/STRD, etc., ARMv5E and later).
OPUS_ARM_MAY_HAVE_EDSP * @OPUS_ARM_MAY_HAVE_EDSP@
; Set the following to 1 if we have ARMv6 media instructions.
OPUS_ARM_MAY_HAVE_MEDIA * @OPUS_ARM_MAY_HAVE_MEDIA@
; Set the following to 1 if we have NEON (some ARMv7)
OPUS_ARM_MAY_HAVE_NEON * @OPUS_ARM_MAY_HAVE_NEON@
END

View file

@ -0,0 +1,173 @@
/* Copyright (c) 2015 Xiph.Org Foundation
Written by Viswanath Puttagunta */
/**
@file celt_fft_ne10.c
@brief ARM Neon optimizations for fft using NE10 library
*/
/*
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 SKIP_CONFIG_H
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#endif
#include <NE10_dsp.h>
#include "os_support.h"
#include "kiss_fft.h"
#include "stack_alloc.h"
#if !defined(FIXED_POINT)
# define NE10_FFT_ALLOC_C2C_TYPE_NEON ne10_fft_alloc_c2c_float32_neon
# define NE10_FFT_CFG_TYPE_T ne10_fft_cfg_float32_t
# define NE10_FFT_STATE_TYPE_T ne10_fft_state_float32_t
# define NE10_FFT_DESTROY_C2C_TYPE ne10_fft_destroy_c2c_float32
# define NE10_FFT_CPX_TYPE_T ne10_fft_cpx_float32_t
# define NE10_FFT_C2C_1D_TYPE_NEON ne10_fft_c2c_1d_float32_neon
#else
# define NE10_FFT_ALLOC_C2C_TYPE_NEON(nfft) ne10_fft_alloc_c2c_int32_neon(nfft)
# define NE10_FFT_CFG_TYPE_T ne10_fft_cfg_int32_t
# define NE10_FFT_STATE_TYPE_T ne10_fft_state_int32_t
# define NE10_FFT_DESTROY_C2C_TYPE ne10_fft_destroy_c2c_int32
# define NE10_FFT_DESTROY_C2C_TYPE ne10_fft_destroy_c2c_int32
# define NE10_FFT_CPX_TYPE_T ne10_fft_cpx_int32_t
# define NE10_FFT_C2C_1D_TYPE_NEON ne10_fft_c2c_1d_int32_neon
#endif
#if defined(CUSTOM_MODES)
/* nfft lengths in NE10 that support scaled fft */
# define NE10_FFTSCALED_SUPPORT_MAX 4
static const int ne10_fft_scaled_support[NE10_FFTSCALED_SUPPORT_MAX] = {
480, 240, 120, 60
};
int opus_fft_alloc_arm_neon(kiss_fft_state *st)
{
int i;
size_t memneeded = sizeof(struct arch_fft_state);
st->arch_fft = (arch_fft_state *)opus_alloc(memneeded);
if (!st->arch_fft)
return -1;
for (i = 0; i < NE10_FFTSCALED_SUPPORT_MAX; i++) {
if(st->nfft == ne10_fft_scaled_support[i])
break;
}
if (i == NE10_FFTSCALED_SUPPORT_MAX) {
/* This nfft length (scaled fft) is not supported in NE10 */
st->arch_fft->is_supported = 0;
st->arch_fft->priv = NULL;
}
else {
st->arch_fft->is_supported = 1;
st->arch_fft->priv = (void *)NE10_FFT_ALLOC_C2C_TYPE_NEON(st->nfft);
if (st->arch_fft->priv == NULL) {
return -1;
}
}
return 0;
}
void opus_fft_free_arm_neon(kiss_fft_state *st)
{
NE10_FFT_CFG_TYPE_T cfg;
if (!st->arch_fft)
return;
cfg = (NE10_FFT_CFG_TYPE_T)st->arch_fft->priv;
if (cfg)
NE10_FFT_DESTROY_C2C_TYPE(cfg);
opus_free(st->arch_fft);
}
#endif
void opus_fft_neon(const kiss_fft_state *st,
const kiss_fft_cpx *fin,
kiss_fft_cpx *fout)
{
NE10_FFT_STATE_TYPE_T state;
NE10_FFT_CFG_TYPE_T cfg = &state;
VARDECL(NE10_FFT_CPX_TYPE_T, buffer);
SAVE_STACK;
ALLOC(buffer, st->nfft, NE10_FFT_CPX_TYPE_T);
if (!st->arch_fft->is_supported) {
/* This nfft length (scaled fft) not supported in NE10 */
opus_fft_c(st, fin, fout);
}
else {
memcpy((void *)cfg, st->arch_fft->priv, sizeof(NE10_FFT_STATE_TYPE_T));
state.buffer = (NE10_FFT_CPX_TYPE_T *)&buffer[0];
#if !defined(FIXED_POINT)
state.is_forward_scaled = 1;
NE10_FFT_C2C_1D_TYPE_NEON((NE10_FFT_CPX_TYPE_T *)fout,
(NE10_FFT_CPX_TYPE_T *)fin,
cfg, 0);
#else
NE10_FFT_C2C_1D_TYPE_NEON((NE10_FFT_CPX_TYPE_T *)fout,
(NE10_FFT_CPX_TYPE_T *)fin,
cfg, 0, 1);
#endif
}
RESTORE_STACK;
}
void opus_ifft_neon(const kiss_fft_state *st,
const kiss_fft_cpx *fin,
kiss_fft_cpx *fout)
{
NE10_FFT_STATE_TYPE_T state;
NE10_FFT_CFG_TYPE_T cfg = &state;
VARDECL(NE10_FFT_CPX_TYPE_T, buffer);
SAVE_STACK;
ALLOC(buffer, st->nfft, NE10_FFT_CPX_TYPE_T);
if (!st->arch_fft->is_supported) {
/* This nfft length (scaled fft) not supported in NE10 */
opus_ifft_c(st, fin, fout);
}
else {
memcpy((void *)cfg, st->arch_fft->priv, sizeof(NE10_FFT_STATE_TYPE_T));
state.buffer = (NE10_FFT_CPX_TYPE_T *)&buffer[0];
#if !defined(FIXED_POINT)
state.is_backward_scaled = 0;
NE10_FFT_C2C_1D_TYPE_NEON((NE10_FFT_CPX_TYPE_T *)fout,
(NE10_FFT_CPX_TYPE_T *)fin,
cfg, 1);
#else
NE10_FFT_C2C_1D_TYPE_NEON((NE10_FFT_CPX_TYPE_T *)fout,
(NE10_FFT_CPX_TYPE_T *)fin,
cfg, 1, 0);
#endif
}
RESTORE_STACK;
}

View file

@ -0,0 +1,258 @@
/* Copyright (c) 2015 Xiph.Org Foundation
Written by Viswanath Puttagunta */
/**
@file celt_mdct_ne10.c
@brief ARM Neon optimizations for mdct using NE10 library
*/
/*
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 SKIP_CONFIG_H
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#endif
#include "kiss_fft.h"
#include "_kiss_fft_guts.h"
#include "mdct.h"
#include "stack_alloc.h"
void clt_mdct_forward_neon(const mdct_lookup *l,
kiss_fft_scalar *in,
kiss_fft_scalar * OPUS_RESTRICT out,
const opus_val16 *window,
int overlap, int shift, int stride, int 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;
SAVE_STACK;
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 opus_val16 * OPUS_RESTRICT wp1 = window+(overlap>>1);
const opus_val16 * 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++ = MULT16_32_Q15(*wp2, xp1[N2]) + MULT16_32_Q15(*wp1,*xp2);
*yp++ = MULT16_32_Q15(*wp1, *xp1) - MULT16_32_Q15(*wp2, xp2[-N2]);
xp1+=2;
xp2-=2;
wp1+=2;
wp2-=2;
}
wp1 = window;
wp2 = window+overlap-1;
for(;i<N4-((overlap+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++ = -MULT16_32_Q15(*wp1, xp1[-N2]) + MULT16_32_Q15(*wp2, *xp2);
*yp++ = MULT16_32_Q15(*wp2, *xp1) + MULT16_32_Q15(*wp1, xp2[N2]);
xp1+=2;
xp2-=2;
wp1+=2;
wp2-=2;
}
}
/* Pre-rotation */
{
kiss_fft_scalar * OPUS_RESTRICT yp = f;
const kiss_twiddle_scalar *t = &trig[0];
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);
yc.r = yr;
yc.i = yi;
f2[i] = yc;
}
}
opus_fft(st, f2, (kiss_fft_cpx *)f, arch);
/* Post-rotate */
{
/* Temp pointers to make it really clear to the compiler what we're doing */
const kiss_fft_cpx * OPUS_RESTRICT fp = (kiss_fft_cpx *)f;
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;
yr = S_MUL(fp->i,t[N4+i]) - S_MUL(fp->r,t[i]);
yi = S_MUL(fp->r,t[N4+i]) + S_MUL(fp->i,t[i]);
*yp1 = yr;
*yp2 = yi;
fp++;
yp1 += 2*stride;
yp2 -= 2*stride;
}
}
RESTORE_STACK;
}
void clt_mdct_backward_neon(const mdct_lookup *l,
kiss_fft_scalar *in,
kiss_fft_scalar * OPUS_RESTRICT out,
const opus_val16 * OPUS_RESTRICT window,
int overlap, int shift, int stride, int arch)
{
int i;
int N, N2, N4;
VARDECL(kiss_fft_scalar, f);
const kiss_twiddle_scalar *trig;
const kiss_fft_state *st = l->kfft[shift];
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);
/* 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 = f;
const kiss_twiddle_scalar * OPUS_RESTRICT t = &trig[0];
for(i=0;i<N4;i++)
{
kiss_fft_scalar yr, yi;
yr = S_MUL(*xp2, t[i]) + S_MUL(*xp1, t[N4+i]);
yi = S_MUL(*xp1, t[i]) - S_MUL(*xp2, t[N4+i]);
yp[2*i] = yr;
yp[2*i+1] = yi;
xp1+=2*stride;
xp2-=2*stride;
}
}
opus_ifft(st, (kiss_fft_cpx *)f, (kiss_fft_cpx*)(out+(overlap>>1)), arch);
/* 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;
re = yp0[0];
im = yp0[1];
t0 = t[i];
t1 = t[N4+i];
/* We'd scale up by 2 here, but instead it's done when mixing the windows */
yr = S_MUL(re,t0) + S_MUL(im,t1);
yi = S_MUL(re,t1) - S_MUL(im,t0);
re = yp1[0];
im = yp1[1];
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 = S_MUL(re,t0) + S_MUL(im,t1);
yi = S_MUL(re,t1) - S_MUL(im,t0);
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 opus_val16 * OPUS_RESTRICT wp1 = window;
const opus_val16 * OPUS_RESTRICT wp2 = window+overlap-1;
for(i = 0; i < overlap/2; i++)
{
kiss_fft_scalar x1, x2;
x1 = *xp1;
x2 = *yp1;
*yp1++ = MULT16_32_Q15(*wp2, x2) - MULT16_32_Q15(*wp1, x1);
*xp1-- = MULT16_32_Q15(*wp1, x2) + MULT16_32_Q15(*wp2, x1);
wp1++;
wp2--;
}
}
RESTORE_STACK;
}

View file

@ -0,0 +1,211 @@
/* Copyright (c) 2014-2015 Xiph.Org Foundation
Written by Viswanath Puttagunta */
/**
@file celt_neon_intr.c
@brief ARM Neon Intrinsic optimizations 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.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <arm_neon.h>
#include "../pitch.h"
#if defined(FIXED_POINT)
void xcorr_kernel_neon_fixed(const opus_val16 * x, const opus_val16 * y, opus_val32 sum[4], int len)
{
int j;
int32x4_t a = vld1q_s32(sum);
/* Load y[0...3] */
/* This requires len>0 to always be valid (which we assert in the C code). */
int16x4_t y0 = vld1_s16(y);
y += 4;
for (j = 0; j + 8 <= len; j += 8)
{
/* Load x[0...7] */
int16x8_t xx = vld1q_s16(x);
int16x4_t x0 = vget_low_s16(xx);
int16x4_t x4 = vget_high_s16(xx);
/* Load y[4...11] */
int16x8_t yy = vld1q_s16(y);
int16x4_t y4 = vget_low_s16(yy);
int16x4_t y8 = vget_high_s16(yy);
int32x4_t a0 = vmlal_lane_s16(a, y0, x0, 0);
int32x4_t a1 = vmlal_lane_s16(a0, y4, x4, 0);
int16x4_t y1 = vext_s16(y0, y4, 1);
int16x4_t y5 = vext_s16(y4, y8, 1);
int32x4_t a2 = vmlal_lane_s16(a1, y1, x0, 1);
int32x4_t a3 = vmlal_lane_s16(a2, y5, x4, 1);
int16x4_t y2 = vext_s16(y0, y4, 2);
int16x4_t y6 = vext_s16(y4, y8, 2);
int32x4_t a4 = vmlal_lane_s16(a3, y2, x0, 2);
int32x4_t a5 = vmlal_lane_s16(a4, y6, x4, 2);
int16x4_t y3 = vext_s16(y0, y4, 3);
int16x4_t y7 = vext_s16(y4, y8, 3);
int32x4_t a6 = vmlal_lane_s16(a5, y3, x0, 3);
int32x4_t a7 = vmlal_lane_s16(a6, y7, x4, 3);
y0 = y8;
a = a7;
x += 8;
y += 8;
}
for (; j < len; j++)
{
int16x4_t x0 = vld1_dup_s16(x); /* load next x */
int32x4_t a0 = vmlal_s16(a, y0, x0);
int16x4_t y4 = vld1_dup_s16(y); /* load next y */
y0 = vext_s16(y0, y4, 1);
a = a0;
x++;
y++;
}
vst1q_s32(sum, a);
}
#else
/*
* Function: xcorr_kernel_neon_float
* ---------------------------------
* Computes 4 correlation values and stores them in sum[4]
*/
static void xcorr_kernel_neon_float(const float32_t *x, const float32_t *y,
float32_t sum[4], int len) {
float32x4_t YY[3];
float32x4_t YEXT[3];
float32x4_t XX[2];
float32x2_t XX_2;
float32x4_t SUMM;
const float32_t *xi = x;
const float32_t *yi = y;
celt_assert(len>0);
YY[0] = vld1q_f32(yi);
SUMM = vdupq_n_f32(0);
/* Consume 8 elements in x vector and 12 elements in y
* vector. However, the 12'th element never really gets
* touched in this loop. So, if len == 8, then we only
* must access y[0] to y[10]. y[11] must not be accessed
* hence make sure len > 8 and not len >= 8
*/
while (len > 8) {
yi += 4;
YY[1] = vld1q_f32(yi);
yi += 4;
YY[2] = vld1q_f32(yi);
XX[0] = vld1q_f32(xi);
xi += 4;
XX[1] = vld1q_f32(xi);
xi += 4;
SUMM = vmlaq_lane_f32(SUMM, YY[0], vget_low_f32(XX[0]), 0);
YEXT[0] = vextq_f32(YY[0], YY[1], 1);
SUMM = vmlaq_lane_f32(SUMM, YEXT[0], vget_low_f32(XX[0]), 1);
YEXT[1] = vextq_f32(YY[0], YY[1], 2);
SUMM = vmlaq_lane_f32(SUMM, YEXT[1], vget_high_f32(XX[0]), 0);
YEXT[2] = vextq_f32(YY[0], YY[1], 3);
SUMM = vmlaq_lane_f32(SUMM, YEXT[2], vget_high_f32(XX[0]), 1);
SUMM = vmlaq_lane_f32(SUMM, YY[1], vget_low_f32(XX[1]), 0);
YEXT[0] = vextq_f32(YY[1], YY[2], 1);
SUMM = vmlaq_lane_f32(SUMM, YEXT[0], vget_low_f32(XX[1]), 1);
YEXT[1] = vextq_f32(YY[1], YY[2], 2);
SUMM = vmlaq_lane_f32(SUMM, YEXT[1], vget_high_f32(XX[1]), 0);
YEXT[2] = vextq_f32(YY[1], YY[2], 3);
SUMM = vmlaq_lane_f32(SUMM, YEXT[2], vget_high_f32(XX[1]), 1);
YY[0] = YY[2];
len -= 8;
}
/* Consume 4 elements in x vector and 8 elements in y
* vector. However, the 8'th element in y never really gets
* touched in this loop. So, if len == 4, then we only
* must access y[0] to y[6]. y[7] must not be accessed
* hence make sure len>4 and not len>=4
*/
if (len > 4) {
yi += 4;
YY[1] = vld1q_f32(yi);
XX[0] = vld1q_f32(xi);
xi += 4;
SUMM = vmlaq_lane_f32(SUMM, YY[0], vget_low_f32(XX[0]), 0);
YEXT[0] = vextq_f32(YY[0], YY[1], 1);
SUMM = vmlaq_lane_f32(SUMM, YEXT[0], vget_low_f32(XX[0]), 1);
YEXT[1] = vextq_f32(YY[0], YY[1], 2);
SUMM = vmlaq_lane_f32(SUMM, YEXT[1], vget_high_f32(XX[0]), 0);
YEXT[2] = vextq_f32(YY[0], YY[1], 3);
SUMM = vmlaq_lane_f32(SUMM, YEXT[2], vget_high_f32(XX[0]), 1);
YY[0] = YY[1];
len -= 4;
}
while (--len > 0) {
XX_2 = vld1_dup_f32(xi++);
SUMM = vmlaq_lane_f32(SUMM, YY[0], XX_2, 0);
YY[0]= vld1q_f32(++yi);
}
XX_2 = vld1_dup_f32(xi);
SUMM = vmlaq_lane_f32(SUMM, YY[0], XX_2, 0);
vst1q_f32(sum, SUMM);
}
void celt_pitch_xcorr_float_neon(const opus_val16 *_x, const opus_val16 *_y,
opus_val32 *xcorr, int len, int max_pitch, int arch) {
int i;
(void)arch;
celt_assert(max_pitch > 0);
celt_sig_assert((((unsigned char *)_x-(unsigned char *)NULL)&3)==0);
for (i = 0; i < (max_pitch-3); i += 4) {
xcorr_kernel_neon_float((const float32_t *)_x, (const float32_t *)_y+i,
(float32_t *)xcorr+i, len);
}
/* In case max_pitch isn't a multiple of 4, do non-unrolled version. */
for (; i < max_pitch; i++) {
xcorr[i] = celt_inner_prod_neon(_x, _y+i, len);
}
}
#endif

View file

@ -0,0 +1,551 @@
; Copyright (c) 2007-2008 CSIRO
; Copyright (c) 2007-2009 Xiph.Org Foundation
; Copyright (c) 2013 Parrot
; Written by Aurélien Zanelli
;
; 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.
AREA |.text|, CODE, READONLY
GET celt/arm/armopts.s
IF OPUS_ARM_MAY_HAVE_EDSP
EXPORT celt_pitch_xcorr_edsp
ENDIF
IF OPUS_ARM_MAY_HAVE_NEON
EXPORT celt_pitch_xcorr_neon
ENDIF
IF OPUS_ARM_MAY_HAVE_NEON
; Compute sum[k]=sum(x[j]*y[j+k],j=0...len-1), k=0...3
xcorr_kernel_neon PROC
xcorr_kernel_neon_start
; input:
; r3 = int len
; r4 = opus_val16 *x
; r5 = opus_val16 *y
; q0 = opus_val32 sum[4]
; output:
; q0 = opus_val32 sum[4]
; preserved: r0-r3, r6-r11, d2, q4-q7, q9-q15
; internal usage:
; r12 = int j
; d3 = y_3|y_2|y_1|y_0
; q2 = y_B|y_A|y_9|y_8|y_7|y_6|y_5|y_4
; q3 = x_7|x_6|x_5|x_4|x_3|x_2|x_1|x_0
; q8 = scratch
;
; Load y[0...3]
; This requires len>0 to always be valid (which we assert in the C code).
VLD1.16 {d5}, [r5]!
SUBS r12, r3, #8
BLE xcorr_kernel_neon_process4
; Process 8 samples at a time.
; This loop loads one y value more than we actually need. Therefore we have to
; stop as soon as there are 8 or fewer samples left (instead of 7), to avoid
; reading past the end of the array.
xcorr_kernel_neon_process8
; This loop has 19 total instructions (10 cycles to issue, minimum), with
; - 2 cycles of ARM insrtuctions,
; - 10 cycles of load/store/byte permute instructions, and
; - 9 cycles of data processing instructions.
; On a Cortex A8, we dual-issue the maximum amount (9 cycles) between the
; latter two categories, meaning the whole loop should run in 10 cycles per
; iteration, barring cache misses.
;
; Load x[0...7]
VLD1.16 {d6, d7}, [r4]!
; Unlike VMOV, VAND is a data processsing instruction (and doesn't get
; assembled to VMOV, like VORR would), so it dual-issues with the prior VLD1.
VAND d3, d5, d5
SUBS r12, r12, #8
; Load y[4...11]
VLD1.16 {d4, d5}, [r5]!
VMLAL.S16 q0, d3, d6[0]
VEXT.16 d16, d3, d4, #1
VMLAL.S16 q0, d4, d7[0]
VEXT.16 d17, d4, d5, #1
VMLAL.S16 q0, d16, d6[1]
VEXT.16 d16, d3, d4, #2
VMLAL.S16 q0, d17, d7[1]
VEXT.16 d17, d4, d5, #2
VMLAL.S16 q0, d16, d6[2]
VEXT.16 d16, d3, d4, #3
VMLAL.S16 q0, d17, d7[2]
VEXT.16 d17, d4, d5, #3
VMLAL.S16 q0, d16, d6[3]
VMLAL.S16 q0, d17, d7[3]
BGT xcorr_kernel_neon_process8
; Process 4 samples here if we have > 4 left (still reading one extra y value).
xcorr_kernel_neon_process4
ADDS r12, r12, #4
BLE xcorr_kernel_neon_process2
; Load x[0...3]
VLD1.16 d6, [r4]!
; Use VAND since it's a data processing instruction again.
VAND d4, d5, d5
SUB r12, r12, #4
; Load y[4...7]
VLD1.16 d5, [r5]!
VMLAL.S16 q0, d4, d6[0]
VEXT.16 d16, d4, d5, #1
VMLAL.S16 q0, d16, d6[1]
VEXT.16 d16, d4, d5, #2
VMLAL.S16 q0, d16, d6[2]
VEXT.16 d16, d4, d5, #3
VMLAL.S16 q0, d16, d6[3]
; Process 2 samples here if we have > 2 left (still reading one extra y value).
xcorr_kernel_neon_process2
ADDS r12, r12, #2
BLE xcorr_kernel_neon_process1
; Load x[0...1]
VLD2.16 {d6[],d7[]}, [r4]!
; Use VAND since it's a data processing instruction again.
VAND d4, d5, d5
SUB r12, r12, #2
; Load y[4...5]
VLD1.32 {d5[]}, [r5]!
VMLAL.S16 q0, d4, d6
VEXT.16 d16, d4, d5, #1
; Replace bottom copy of {y5,y4} in d5 with {y3,y2} from d4, using VSRI
; instead of VEXT, since it's a data-processing instruction.
VSRI.64 d5, d4, #32
VMLAL.S16 q0, d16, d7
; Process 1 sample using the extra y value we loaded above.
xcorr_kernel_neon_process1
; Load next *x
VLD1.16 {d6[]}, [r4]!
ADDS r12, r12, #1
; y[0...3] are left in d5 from prior iteration(s) (if any)
VMLAL.S16 q0, d5, d6
MOVLE pc, lr
; Now process 1 last sample, not reading ahead.
; Load last *y
VLD1.16 {d4[]}, [r5]!
VSRI.64 d4, d5, #16
; Load last *x
VLD1.16 {d6[]}, [r4]!
VMLAL.S16 q0, d4, d6
MOV pc, lr
ENDP
; opus_val32 celt_pitch_xcorr_neon(opus_val16 *_x, opus_val16 *_y,
; opus_val32 *xcorr, int len, int max_pitch, int arch)
celt_pitch_xcorr_neon PROC
; input:
; r0 = opus_val16 *_x
; r1 = opus_val16 *_y
; r2 = opus_val32 *xcorr
; r3 = int len
; output:
; r0 = int maxcorr
; internal usage:
; r4 = opus_val16 *x (for xcorr_kernel_neon())
; r5 = opus_val16 *y (for xcorr_kernel_neon())
; r6 = int max_pitch
; r12 = int j
; q15 = int maxcorr[4] (q15 is not used by xcorr_kernel_neon())
; ignored:
; int arch
STMFD sp!, {r4-r6, lr}
LDR r6, [sp, #16]
VMOV.S32 q15, #1
; if (max_pitch < 4) goto celt_pitch_xcorr_neon_process4_done
SUBS r6, r6, #4
BLT celt_pitch_xcorr_neon_process4_done
celt_pitch_xcorr_neon_process4
; xcorr_kernel_neon parameters:
; r3 = len, r4 = _x, r5 = _y, q0 = {0, 0, 0, 0}
MOV r4, r0
MOV r5, r1
VEOR q0, q0, q0
; xcorr_kernel_neon only modifies r4, r5, r12, and q0...q3.
; So we don't save/restore any other registers.
BL xcorr_kernel_neon_start
SUBS r6, r6, #4
VST1.32 {q0}, [r2]!
; _y += 4
ADD r1, r1, #8
VMAX.S32 q15, q15, q0
; if (max_pitch < 4) goto celt_pitch_xcorr_neon_process4_done
BGE celt_pitch_xcorr_neon_process4
; We have less than 4 sums left to compute.
celt_pitch_xcorr_neon_process4_done
ADDS r6, r6, #4
; Reduce maxcorr to a single value
VMAX.S32 d30, d30, d31
VPMAX.S32 d30, d30, d30
; if (max_pitch <= 0) goto celt_pitch_xcorr_neon_done
BLE celt_pitch_xcorr_neon_done
; Now compute each remaining sum one at a time.
celt_pitch_xcorr_neon_process_remaining
MOV r4, r0
MOV r5, r1
VMOV.I32 q0, #0
SUBS r12, r3, #8
BLT celt_pitch_xcorr_neon_process_remaining4
; Sum terms 8 at a time.
celt_pitch_xcorr_neon_process_remaining_loop8
; Load x[0...7]
VLD1.16 {q1}, [r4]!
; Load y[0...7]
VLD1.16 {q2}, [r5]!
SUBS r12, r12, #8
VMLAL.S16 q0, d4, d2
VMLAL.S16 q0, d5, d3
BGE celt_pitch_xcorr_neon_process_remaining_loop8
; Sum terms 4 at a time.
celt_pitch_xcorr_neon_process_remaining4
ADDS r12, r12, #4
BLT celt_pitch_xcorr_neon_process_remaining4_done
; Load x[0...3]
VLD1.16 {d2}, [r4]!
; Load y[0...3]
VLD1.16 {d3}, [r5]!
SUB r12, r12, #4
VMLAL.S16 q0, d3, d2
celt_pitch_xcorr_neon_process_remaining4_done
; Reduce the sum to a single value.
VADD.S32 d0, d0, d1
VPADDL.S32 d0, d0
ADDS r12, r12, #4
BLE celt_pitch_xcorr_neon_process_remaining_loop_done
; Sum terms 1 at a time.
celt_pitch_xcorr_neon_process_remaining_loop1
VLD1.16 {d2[]}, [r4]!
VLD1.16 {d3[]}, [r5]!
SUBS r12, r12, #1
VMLAL.S16 q0, d2, d3
BGT celt_pitch_xcorr_neon_process_remaining_loop1
celt_pitch_xcorr_neon_process_remaining_loop_done
VST1.32 {d0[0]}, [r2]!
VMAX.S32 d30, d30, d0
SUBS r6, r6, #1
; _y++
ADD r1, r1, #2
; if (--max_pitch > 0) goto celt_pitch_xcorr_neon_process_remaining
BGT celt_pitch_xcorr_neon_process_remaining
celt_pitch_xcorr_neon_done
VMOV.32 r0, d30[0]
LDMFD sp!, {r4-r6, pc}
ENDP
ENDIF
IF OPUS_ARM_MAY_HAVE_EDSP
; This will get used on ARMv7 devices without NEON, so it has been optimized
; to take advantage of dual-issuing where possible.
xcorr_kernel_edsp PROC
xcorr_kernel_edsp_start
; input:
; r3 = int len
; r4 = opus_val16 *_x (must be 32-bit aligned)
; r5 = opus_val16 *_y (must be 32-bit aligned)
; r6...r9 = opus_val32 sum[4]
; output:
; r6...r9 = opus_val32 sum[4]
; preserved: r0-r5
; internal usage
; r2 = int j
; r12,r14 = opus_val16 x[4]
; r10,r11 = opus_val16 y[4]
STMFD sp!, {r2,r4,r5,lr}
LDR r10, [r5], #4 ; Load y[0...1]
SUBS r2, r3, #4 ; j = len-4
LDR r11, [r5], #4 ; Load y[2...3]
BLE xcorr_kernel_edsp_process4_done
LDR r12, [r4], #4 ; Load x[0...1]
; Stall
xcorr_kernel_edsp_process4
; The multiplies must issue from pipeline 0, and can't dual-issue with each
; other. Every other instruction here dual-issues with a multiply, and is
; thus "free". There should be no stalls in the body of the loop.
SMLABB r6, r12, r10, r6 ; sum[0] = MAC16_16(sum[0],x_0,y_0)
LDR r14, [r4], #4 ; Load x[2...3]
SMLABT r7, r12, r10, r7 ; sum[1] = MAC16_16(sum[1],x_0,y_1)
SUBS r2, r2, #4 ; j-=4
SMLABB r8, r12, r11, r8 ; sum[2] = MAC16_16(sum[2],x_0,y_2)
SMLABT r9, r12, r11, r9 ; sum[3] = MAC16_16(sum[3],x_0,y_3)
SMLATT r6, r12, r10, r6 ; sum[0] = MAC16_16(sum[0],x_1,y_1)
LDR r10, [r5], #4 ; Load y[4...5]
SMLATB r7, r12, r11, r7 ; sum[1] = MAC16_16(sum[1],x_1,y_2)
SMLATT r8, r12, r11, r8 ; sum[2] = MAC16_16(sum[2],x_1,y_3)
SMLATB r9, r12, r10, r9 ; sum[3] = MAC16_16(sum[3],x_1,y_4)
LDRGT r12, [r4], #4 ; Load x[0...1]
SMLABB r6, r14, r11, r6 ; sum[0] = MAC16_16(sum[0],x_2,y_2)
SMLABT r7, r14, r11, r7 ; sum[1] = MAC16_16(sum[1],x_2,y_3)
SMLABB r8, r14, r10, r8 ; sum[2] = MAC16_16(sum[2],x_2,y_4)
SMLABT r9, r14, r10, r9 ; sum[3] = MAC16_16(sum[3],x_2,y_5)
SMLATT r6, r14, r11, r6 ; sum[0] = MAC16_16(sum[0],x_3,y_3)
LDR r11, [r5], #4 ; Load y[6...7]
SMLATB r7, r14, r10, r7 ; sum[1] = MAC16_16(sum[1],x_3,y_4)
SMLATT r8, r14, r10, r8 ; sum[2] = MAC16_16(sum[2],x_3,y_5)
SMLATB r9, r14, r11, r9 ; sum[3] = MAC16_16(sum[3],x_3,y_6)
BGT xcorr_kernel_edsp_process4
xcorr_kernel_edsp_process4_done
ADDS r2, r2, #4
BLE xcorr_kernel_edsp_done
LDRH r12, [r4], #2 ; r12 = *x++
SUBS r2, r2, #1 ; j--
; Stall
SMLABB r6, r12, r10, r6 ; sum[0] = MAC16_16(sum[0],x,y_0)
LDRHGT r14, [r4], #2 ; r14 = *x++
SMLABT r7, r12, r10, r7 ; sum[1] = MAC16_16(sum[1],x,y_1)
SMLABB r8, r12, r11, r8 ; sum[2] = MAC16_16(sum[2],x,y_2)
SMLABT r9, r12, r11, r9 ; sum[3] = MAC16_16(sum[3],x,y_3)
BLE xcorr_kernel_edsp_done
SMLABT r6, r14, r10, r6 ; sum[0] = MAC16_16(sum[0],x,y_1)
SUBS r2, r2, #1 ; j--
SMLABB r7, r14, r11, r7 ; sum[1] = MAC16_16(sum[1],x,y_2)
LDRH r10, [r5], #2 ; r10 = y_4 = *y++
SMLABT r8, r14, r11, r8 ; sum[2] = MAC16_16(sum[2],x,y_3)
LDRHGT r12, [r4], #2 ; r12 = *x++
SMLABB r9, r14, r10, r9 ; sum[3] = MAC16_16(sum[3],x,y_4)
BLE xcorr_kernel_edsp_done
SMLABB r6, r12, r11, r6 ; sum[0] = MAC16_16(sum[0],tmp,y_2)
CMP r2, #1 ; j--
SMLABT r7, r12, r11, r7 ; sum[1] = MAC16_16(sum[1],tmp,y_3)
LDRH r2, [r5], #2 ; r2 = y_5 = *y++
SMLABB r8, r12, r10, r8 ; sum[2] = MAC16_16(sum[2],tmp,y_4)
LDRHGT r14, [r4] ; r14 = *x
SMLABB r9, r12, r2, r9 ; sum[3] = MAC16_16(sum[3],tmp,y_5)
BLE xcorr_kernel_edsp_done
SMLABT r6, r14, r11, r6 ; sum[0] = MAC16_16(sum[0],tmp,y_3)
LDRH r11, [r5] ; r11 = y_6 = *y
SMLABB r7, r14, r10, r7 ; sum[1] = MAC16_16(sum[1],tmp,y_4)
SMLABB r8, r14, r2, r8 ; sum[2] = MAC16_16(sum[2],tmp,y_5)
SMLABB r9, r14, r11, r9 ; sum[3] = MAC16_16(sum[3],tmp,y_6)
xcorr_kernel_edsp_done
LDMFD sp!, {r2,r4,r5,pc}
ENDP
celt_pitch_xcorr_edsp PROC
; input:
; r0 = opus_val16 *_x (must be 32-bit aligned)
; r1 = opus_val16 *_y (only needs to be 16-bit aligned)
; r2 = opus_val32 *xcorr
; r3 = int len
; output:
; r0 = maxcorr
; internal usage
; r4 = opus_val16 *x
; r5 = opus_val16 *y
; r6 = opus_val32 sum0
; r7 = opus_val32 sum1
; r8 = opus_val32 sum2
; r9 = opus_val32 sum3
; r1 = int max_pitch
; r12 = int j
; ignored:
; int arch
STMFD sp!, {r4-r11, lr}
MOV r5, r1
LDR r1, [sp, #36]
MOV r4, r0
TST r5, #3
; maxcorr = 1
MOV r0, #1
BEQ celt_pitch_xcorr_edsp_process1u_done
; Compute one sum at the start to make y 32-bit aligned.
SUBS r12, r3, #4
; r14 = sum = 0
MOV r14, #0
LDRH r8, [r5], #2
BLE celt_pitch_xcorr_edsp_process1u_loop4_done
LDR r6, [r4], #4
MOV r8, r8, LSL #16
celt_pitch_xcorr_edsp_process1u_loop4
LDR r9, [r5], #4
SMLABT r14, r6, r8, r14 ; sum = MAC16_16(sum, x_0, y_0)
LDR r7, [r4], #4
SMLATB r14, r6, r9, r14 ; sum = MAC16_16(sum, x_1, y_1)
LDR r8, [r5], #4
SMLABT r14, r7, r9, r14 ; sum = MAC16_16(sum, x_2, y_2)
SUBS r12, r12, #4 ; j-=4
SMLATB r14, r7, r8, r14 ; sum = MAC16_16(sum, x_3, y_3)
LDRGT r6, [r4], #4
BGT celt_pitch_xcorr_edsp_process1u_loop4
MOV r8, r8, LSR #16
celt_pitch_xcorr_edsp_process1u_loop4_done
ADDS r12, r12, #4
celt_pitch_xcorr_edsp_process1u_loop1
LDRHGE r6, [r4], #2
; Stall
SMLABBGE r14, r6, r8, r14 ; sum = MAC16_16(sum, *x, *y)
SUBSGE r12, r12, #1
LDRHGT r8, [r5], #2
BGT celt_pitch_xcorr_edsp_process1u_loop1
; Restore _x
SUB r4, r4, r3, LSL #1
; Restore and advance _y
SUB r5, r5, r3, LSL #1
; maxcorr = max(maxcorr, sum)
CMP r0, r14
ADD r5, r5, #2
MOVLT r0, r14
SUBS r1, r1, #1
; xcorr[i] = sum
STR r14, [r2], #4
BLE celt_pitch_xcorr_edsp_done
celt_pitch_xcorr_edsp_process1u_done
; if (max_pitch < 4) goto celt_pitch_xcorr_edsp_process2
SUBS r1, r1, #4
BLT celt_pitch_xcorr_edsp_process2
celt_pitch_xcorr_edsp_process4
; xcorr_kernel_edsp parameters:
; r3 = len, r4 = _x, r5 = _y, r6...r9 = sum[4] = {0, 0, 0, 0}
MOV r6, #0
MOV r7, #0
MOV r8, #0
MOV r9, #0
BL xcorr_kernel_edsp_start ; xcorr_kernel_edsp(_x, _y+i, xcorr+i, len)
; maxcorr = max(maxcorr, sum0, sum1, sum2, sum3)
CMP r0, r6
; _y+=4
ADD r5, r5, #8
MOVLT r0, r6
CMP r0, r7
MOVLT r0, r7
CMP r0, r8
MOVLT r0, r8
CMP r0, r9
MOVLT r0, r9
STMIA r2!, {r6-r9}
SUBS r1, r1, #4
BGE celt_pitch_xcorr_edsp_process4
celt_pitch_xcorr_edsp_process2
ADDS r1, r1, #2
BLT celt_pitch_xcorr_edsp_process1a
SUBS r12, r3, #4
; {r10, r11} = {sum0, sum1} = {0, 0}
MOV r10, #0
MOV r11, #0
LDR r8, [r5], #4
BLE celt_pitch_xcorr_edsp_process2_loop_done
LDR r6, [r4], #4
LDR r9, [r5], #4
celt_pitch_xcorr_edsp_process2_loop4
SMLABB r10, r6, r8, r10 ; sum0 = MAC16_16(sum0, x_0, y_0)
LDR r7, [r4], #4
SMLABT r11, r6, r8, r11 ; sum1 = MAC16_16(sum1, x_0, y_1)
SUBS r12, r12, #4 ; j-=4
SMLATT r10, r6, r8, r10 ; sum0 = MAC16_16(sum0, x_1, y_1)
LDR r8, [r5], #4
SMLATB r11, r6, r9, r11 ; sum1 = MAC16_16(sum1, x_1, y_2)
LDRGT r6, [r4], #4
SMLABB r10, r7, r9, r10 ; sum0 = MAC16_16(sum0, x_2, y_2)
SMLABT r11, r7, r9, r11 ; sum1 = MAC16_16(sum1, x_2, y_3)
SMLATT r10, r7, r9, r10 ; sum0 = MAC16_16(sum0, x_3, y_3)
LDRGT r9, [r5], #4
SMLATB r11, r7, r8, r11 ; sum1 = MAC16_16(sum1, x_3, y_4)
BGT celt_pitch_xcorr_edsp_process2_loop4
celt_pitch_xcorr_edsp_process2_loop_done
ADDS r12, r12, #2
BLE celt_pitch_xcorr_edsp_process2_1
LDR r6, [r4], #4
; Stall
SMLABB r10, r6, r8, r10 ; sum0 = MAC16_16(sum0, x_0, y_0)
LDR r9, [r5], #4
SMLABT r11, r6, r8, r11 ; sum1 = MAC16_16(sum1, x_0, y_1)
SUB r12, r12, #2
SMLATT r10, r6, r8, r10 ; sum0 = MAC16_16(sum0, x_1, y_1)
MOV r8, r9
SMLATB r11, r6, r9, r11 ; sum1 = MAC16_16(sum1, x_1, y_2)
celt_pitch_xcorr_edsp_process2_1
LDRH r6, [r4], #2
ADDS r12, r12, #1
; Stall
SMLABB r10, r6, r8, r10 ; sum0 = MAC16_16(sum0, x_0, y_0)
LDRHGT r7, [r4], #2
SMLABT r11, r6, r8, r11 ; sum1 = MAC16_16(sum1, x_0, y_1)
BLE celt_pitch_xcorr_edsp_process2_done
LDRH r9, [r5], #2
SMLABT r10, r7, r8, r10 ; sum0 = MAC16_16(sum0, x_0, y_1)
SMLABB r11, r7, r9, r11 ; sum1 = MAC16_16(sum1, x_0, y_2)
celt_pitch_xcorr_edsp_process2_done
; Restore _x
SUB r4, r4, r3, LSL #1
; Restore and advance _y
SUB r5, r5, r3, LSL #1
; maxcorr = max(maxcorr, sum0)
CMP r0, r10
ADD r5, r5, #2
MOVLT r0, r10
SUB r1, r1, #2
; maxcorr = max(maxcorr, sum1)
CMP r0, r11
; xcorr[i] = sum
STR r10, [r2], #4
MOVLT r0, r11
STR r11, [r2], #4
celt_pitch_xcorr_edsp_process1a
ADDS r1, r1, #1
BLT celt_pitch_xcorr_edsp_done
SUBS r12, r3, #4
; r14 = sum = 0
MOV r14, #0
BLT celt_pitch_xcorr_edsp_process1a_loop_done
LDR r6, [r4], #4
LDR r8, [r5], #4
LDR r7, [r4], #4
LDR r9, [r5], #4
celt_pitch_xcorr_edsp_process1a_loop4
SMLABB r14, r6, r8, r14 ; sum = MAC16_16(sum, x_0, y_0)
SUBS r12, r12, #4 ; j-=4
SMLATT r14, r6, r8, r14 ; sum = MAC16_16(sum, x_1, y_1)
LDRGE r6, [r4], #4
SMLABB r14, r7, r9, r14 ; sum = MAC16_16(sum, x_2, y_2)
LDRGE r8, [r5], #4
SMLATT r14, r7, r9, r14 ; sum = MAC16_16(sum, x_3, y_3)
LDRGE r7, [r4], #4
LDRGE r9, [r5], #4
BGE celt_pitch_xcorr_edsp_process1a_loop4
celt_pitch_xcorr_edsp_process1a_loop_done
ADDS r12, r12, #2
LDRGE r6, [r4], #4
LDRGE r8, [r5], #4
; Stall
SMLABBGE r14, r6, r8, r14 ; sum = MAC16_16(sum, x_0, y_0)
SUBGE r12, r12, #2
SMLATTGE r14, r6, r8, r14 ; sum = MAC16_16(sum, x_1, y_1)
ADDS r12, r12, #1
LDRHGE r6, [r4], #2
LDRHGE r8, [r5], #2
; Stall
SMLABBGE r14, r6, r8, r14 ; sum = MAC16_16(sum, *x, *y)
; maxcorr = max(maxcorr, sum)
CMP r0, r14
; xcorr[i] = sum
STR r14, [r2], #4
MOVLT r0, r14
celt_pitch_xcorr_edsp_done
LDMFD sp!, {r4-r11, pc}
ENDP
ENDIF
END

View file

@ -0,0 +1,71 @@
/* Copyright (c) 2015 Xiph.Org Foundation
Written by Viswanath Puttagunta */
/**
@file fft_arm.h
@brief ARM Neon Intrinsic optimizations for fft using NE10 library
*/
/*
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(FFT_ARM_H)
#define FFT_ARM_H
#include "kiss_fft.h"
#if defined(HAVE_ARM_NE10)
int opus_fft_alloc_arm_neon(kiss_fft_state *st);
void opus_fft_free_arm_neon(kiss_fft_state *st);
void opus_fft_neon(const kiss_fft_state *st,
const kiss_fft_cpx *fin,
kiss_fft_cpx *fout);
void opus_ifft_neon(const kiss_fft_state *st,
const kiss_fft_cpx *fin,
kiss_fft_cpx *fout);
#if !defined(OPUS_HAVE_RTCD)
#define OVERRIDE_OPUS_FFT (1)
#define opus_fft_alloc_arch(_st, arch) \
((void)(arch), opus_fft_alloc_arm_neon(_st))
#define opus_fft_free_arch(_st, arch) \
((void)(arch), opus_fft_free_arm_neon(_st))
#define opus_fft(_st, _fin, _fout, arch) \
((void)(arch), opus_fft_neon(_st, _fin, _fout))
#define opus_ifft(_st, _fin, _fout, arch) \
((void)(arch), opus_ifft_neon(_st, _fin, _fout))
#endif /* OPUS_HAVE_RTCD */
#endif /* HAVE_ARM_NE10 */
#endif

View file

@ -0,0 +1,35 @@
/* Copyright (C) 2015 Vidyo */
/*
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_ARM64_H
#define FIXED_ARM64_H
#include <arm_neon.h>
#undef SIG2WORD16
#define SIG2WORD16(x) (vqmovns_s32(PSHR32((x), SIG_SHIFT)))
#endif

View file

@ -37,7 +37,7 @@ static OPUS_INLINE opus_val32 MULT16_32_Q16_armv4(opus_val16 a, opus_val32 b)
"#MULT16_32_Q16\n\t" "#MULT16_32_Q16\n\t"
"smull %0, %1, %2, %3\n\t" "smull %0, %1, %2, %3\n\t"
: "=&r"(rd_lo), "=&r"(rd_hi) : "=&r"(rd_lo), "=&r"(rd_hi)
: "%r"(b),"r"(a<<16) : "%r"(b),"r"(SHL32(a,16))
); );
return rd_hi; return rd_hi;
} }
@ -54,10 +54,10 @@ static OPUS_INLINE opus_val32 MULT16_32_Q15_armv4(opus_val16 a, opus_val32 b)
"#MULT16_32_Q15\n\t" "#MULT16_32_Q15\n\t"
"smull %0, %1, %2, %3\n\t" "smull %0, %1, %2, %3\n\t"
: "=&r"(rd_lo), "=&r"(rd_hi) : "=&r"(rd_lo), "=&r"(rd_hi)
: "%r"(b), "r"(a<<16) : "%r"(b), "r"(SHL32(a,16))
); );
/*We intentionally don't OR in the high bit of rd_lo for speed.*/ /*We intentionally don't OR in the high bit of rd_lo for speed.*/
return rd_hi<<1; return SHL32(rd_hi,1);
} }
#define MULT16_32_Q15(a, b) (MULT16_32_Q15_armv4(a, b)) #define MULT16_32_Q15(a, b) (MULT16_32_Q15_armv4(a, b))

View file

@ -59,7 +59,7 @@ static OPUS_INLINE opus_val32 MULT16_32_Q15_armv5e(opus_val16 a, opus_val32 b)
: "=r"(res) : "=r"(res)
: "r"(b), "r"(a) : "r"(b), "r"(a)
); );
return res<<1; return SHL32(res,1);
} }
#define MULT16_32_Q15(a, b) (MULT16_32_Q15_armv5e(a, b)) #define MULT16_32_Q15(a, b) (MULT16_32_Q15_armv5e(a, b))
@ -76,7 +76,7 @@ static OPUS_INLINE opus_val32 MAC16_32_Q15_armv5e(opus_val32 c, opus_val16 a,
"#MAC16_32_Q15\n\t" "#MAC16_32_Q15\n\t"
"smlawb %0, %1, %2, %3;\n" "smlawb %0, %1, %2, %3;\n"
: "=r"(res) : "=r"(res)
: "r"(b<<1), "r"(a), "r"(c) : "r"(SHL32(b,1)), "r"(a), "r"(c)
); );
return res; return res;
} }

View file

@ -0,0 +1,59 @@
/* Copyright (c) 2015 Xiph.Org Foundation
Written by Viswanath Puttagunta */
/**
@file arm_mdct.h
@brief ARM Neon Intrinsic optimizations for mdct using NE10 library
*/
/*
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(MDCT_ARM_H)
#define MDCT_ARM_H
#include "mdct.h"
#if defined(HAVE_ARM_NE10)
/** Compute a forward MDCT and scale by 4/N, trashes the input array */
void clt_mdct_forward_neon(const mdct_lookup *l, kiss_fft_scalar *in,
kiss_fft_scalar * OPUS_RESTRICT out,
const opus_val16 *window, int overlap,
int shift, int stride, int arch);
void clt_mdct_backward_neon(const mdct_lookup *l, kiss_fft_scalar *in,
kiss_fft_scalar * OPUS_RESTRICT out,
const opus_val16 *window, int overlap,
int shift, int stride, int arch);
#if !defined(OPUS_HAVE_RTCD)
#define OVERRIDE_OPUS_MDCT (1)
#define clt_mdct_forward(_l, _in, _out, _window, _int, _shift, _stride, _arch) \
clt_mdct_forward_neon(_l, _in, _out, _window, _int, _shift, _stride, _arch)
#define clt_mdct_backward(_l, _in, _out, _window, _int, _shift, _stride, _arch) \
clt_mdct_backward_neon(_l, _in, _out, _window, _int, _shift, _stride, _arch)
#endif /* OPUS_HAVE_RTCD */
#endif /* HAVE_ARM_NE10 */
#endif

View file

@ -0,0 +1,160 @@
/* 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.
*/
#if !defined(PITCH_ARM_H)
# define PITCH_ARM_H
# include "armcpu.h"
# if defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
opus_val32 celt_inner_prod_neon(const opus_val16 *x, const opus_val16 *y, int N);
void dual_inner_prod_neon(const opus_val16 *x, const opus_val16 *y01,
const opus_val16 *y02, int N, opus_val32 *xy1, opus_val32 *xy2);
# if !defined(OPUS_HAVE_RTCD) && defined(OPUS_ARM_PRESUME_NEON)
# define OVERRIDE_CELT_INNER_PROD (1)
# define OVERRIDE_DUAL_INNER_PROD (1)
# define celt_inner_prod(x, y, N, arch) ((void)(arch), PRESUME_NEON(celt_inner_prod)(x, y, N))
# define dual_inner_prod(x, y01, y02, N, xy1, xy2, arch) ((void)(arch), PRESUME_NEON(dual_inner_prod)(x, y01, y02, N, xy1, xy2))
# endif
# endif
# if !defined(OVERRIDE_CELT_INNER_PROD)
# if defined(OPUS_HAVE_RTCD) && (defined(OPUS_ARM_MAY_HAVE_NEON_INTR) && !defined(OPUS_ARM_PRESUME_NEON_INTR))
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 (1)
# define celt_inner_prod(x, y, N, arch) ((*CELT_INNER_PROD_IMPL[(arch)&OPUS_ARCHMASK])(x, y, N))
# elif defined(OPUS_ARM_PRESUME_NEON_INTR)
# define OVERRIDE_CELT_INNER_PROD (1)
# define celt_inner_prod(x, y, N, arch) ((void)(arch), celt_inner_prod_neon(x, y, N))
# endif
# endif
# if !defined(OVERRIDE_DUAL_INNER_PROD)
# if defined(OPUS_HAVE_RTCD) && (defined(OPUS_ARM_MAY_HAVE_NEON_INTR) && !defined(OPUS_ARM_PRESUME_NEON_INTR))
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 OVERRIDE_DUAL_INNER_PROD (1)
# define dual_inner_prod(x, y01, y02, N, xy1, xy2, arch) ((*DUAL_INNER_PROD_IMPL[(arch)&OPUS_ARCHMASK])(x, y01, y02, N, xy1, xy2))
# elif defined(OPUS_ARM_PRESUME_NEON_INTR)
# define OVERRIDE_DUAL_INNER_PROD (1)
# define dual_inner_prod(x, y01, y02, N, xy1, xy2, arch) ((void)(arch), dual_inner_prod_neon(x, y01, y02, N, xy1, xy2))
# endif
# endif
# if defined(FIXED_POINT)
# if defined(OPUS_ARM_MAY_HAVE_NEON)
opus_val32 celt_pitch_xcorr_neon(const opus_val16 *_x, const opus_val16 *_y,
opus_val32 *xcorr, int len, int max_pitch, int arch);
# endif
# if defined(OPUS_ARM_MAY_HAVE_MEDIA)
# define celt_pitch_xcorr_media MAY_HAVE_EDSP(celt_pitch_xcorr)
# endif
# if defined(OPUS_ARM_MAY_HAVE_EDSP)
opus_val32 celt_pitch_xcorr_edsp(const opus_val16 *_x, const opus_val16 *_y,
opus_val32 *xcorr, int len, int max_pitch, int arch);
# endif
# if defined(OPUS_HAVE_RTCD) && \
((defined(OPUS_ARM_MAY_HAVE_NEON) && !defined(OPUS_ARM_PRESUME_NEON)) || \
(defined(OPUS_ARM_MAY_HAVE_MEDIA) && !defined(OPUS_ARM_PRESUME_MEDIA)) || \
(defined(OPUS_ARM_MAY_HAVE_EDSP) && !defined(OPUS_ARM_PRESUME_EDSP)))
extern opus_val32
(*const CELT_PITCH_XCORR_IMPL[OPUS_ARCHMASK+1])(const opus_val16 *,
const opus_val16 *, opus_val32 *, int, int, int);
# define OVERRIDE_PITCH_XCORR (1)
# define celt_pitch_xcorr(_x, _y, xcorr, len, max_pitch, arch) \
((*CELT_PITCH_XCORR_IMPL[(arch)&OPUS_ARCHMASK])(_x, _y, \
xcorr, len, max_pitch, arch))
# elif defined(OPUS_ARM_PRESUME_EDSP) || \
defined(OPUS_ARM_PRESUME_MEDIA) || \
defined(OPUS_ARM_PRESUME_NEON)
# define OVERRIDE_PITCH_XCORR (1)
# define celt_pitch_xcorr (PRESUME_NEON(celt_pitch_xcorr))
# endif
# if defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
void xcorr_kernel_neon_fixed(
const opus_val16 *x,
const opus_val16 *y,
opus_val32 sum[4],
int len);
# endif
# if defined(OPUS_HAVE_RTCD) && \
(defined(OPUS_ARM_MAY_HAVE_NEON_INTR) && !defined(OPUS_ARM_PRESUME_NEON_INTR))
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 (1)
# define xcorr_kernel(x, y, sum, len, arch) \
((*XCORR_KERNEL_IMPL[(arch) & OPUS_ARCHMASK])(x, y, sum, len))
# elif defined(OPUS_ARM_PRESUME_NEON_INTR)
# define OVERRIDE_XCORR_KERNEL (1)
# define xcorr_kernel(x, y, sum, len, arch) \
((void)arch, xcorr_kernel_neon_fixed(x, y, sum, len))
# endif
#else /* Start !FIXED_POINT */
/* Float case */
#if defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
void celt_pitch_xcorr_float_neon(const opus_val16 *_x, const opus_val16 *_y,
opus_val32 *xcorr, int len, int max_pitch, int arch);
#endif
# if defined(OPUS_HAVE_RTCD) && \
(defined(OPUS_ARM_MAY_HAVE_NEON_INTR) && !defined(OPUS_ARM_PRESUME_NEON_INTR))
extern void
(*const CELT_PITCH_XCORR_IMPL[OPUS_ARCHMASK+1])(const opus_val16 *,
const opus_val16 *, opus_val32 *, int, int, int);
# define OVERRIDE_PITCH_XCORR (1)
# define celt_pitch_xcorr(_x, _y, xcorr, len, max_pitch, arch) \
((*CELT_PITCH_XCORR_IMPL[(arch)&OPUS_ARCHMASK])(_x, _y, \
xcorr, len, max_pitch, arch))
# elif defined(OPUS_ARM_PRESUME_NEON_INTR)
# define OVERRIDE_PITCH_XCORR (1)
# define celt_pitch_xcorr celt_pitch_xcorr_float_neon
# endif
#endif /* end !FIXED_POINT */
#endif

View file

@ -0,0 +1,290 @@
/***********************************************************************
Copyright (c) 2017 Google Inc.
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 <arm_neon.h>
#include "pitch.h"
#ifdef FIXED_POINT
opus_val32 celt_inner_prod_neon(const opus_val16 *x, const opus_val16 *y, int N)
{
int i;
opus_val32 xy;
int16x8_t x_s16x8, y_s16x8;
int32x4_t xy_s32x4 = vdupq_n_s32(0);
int64x2_t xy_s64x2;
int64x1_t xy_s64x1;
for (i = 0; i < N - 7; i += 8) {
x_s16x8 = vld1q_s16(&x[i]);
y_s16x8 = vld1q_s16(&y[i]);
xy_s32x4 = vmlal_s16(xy_s32x4, vget_low_s16 (x_s16x8), vget_low_s16 (y_s16x8));
xy_s32x4 = vmlal_s16(xy_s32x4, vget_high_s16(x_s16x8), vget_high_s16(y_s16x8));
}
if (N - i >= 4) {
const int16x4_t x_s16x4 = vld1_s16(&x[i]);
const int16x4_t y_s16x4 = vld1_s16(&y[i]);
xy_s32x4 = vmlal_s16(xy_s32x4, x_s16x4, y_s16x4);
i += 4;
}
xy_s64x2 = vpaddlq_s32(xy_s32x4);
xy_s64x1 = vadd_s64(vget_low_s64(xy_s64x2), vget_high_s64(xy_s64x2));
xy = vget_lane_s32(vreinterpret_s32_s64(xy_s64x1), 0);
for (; i < N; i++) {
xy = MAC16_16(xy, x[i], y[i]);
}
#ifdef OPUS_CHECK_ASM
celt_assert(celt_inner_prod_c(x, y, N) == xy);
#endif
return xy;
}
void dual_inner_prod_neon(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, xy02;
int16x8_t x_s16x8, y01_s16x8, y02_s16x8;
int32x4_t xy01_s32x4 = vdupq_n_s32(0);
int32x4_t xy02_s32x4 = vdupq_n_s32(0);
int64x2_t xy01_s64x2, xy02_s64x2;
int64x1_t xy01_s64x1, xy02_s64x1;
for (i = 0; i < N - 7; i += 8) {
x_s16x8 = vld1q_s16(&x[i]);
y01_s16x8 = vld1q_s16(&y01[i]);
y02_s16x8 = vld1q_s16(&y02[i]);
xy01_s32x4 = vmlal_s16(xy01_s32x4, vget_low_s16 (x_s16x8), vget_low_s16 (y01_s16x8));
xy02_s32x4 = vmlal_s16(xy02_s32x4, vget_low_s16 (x_s16x8), vget_low_s16 (y02_s16x8));
xy01_s32x4 = vmlal_s16(xy01_s32x4, vget_high_s16(x_s16x8), vget_high_s16(y01_s16x8));
xy02_s32x4 = vmlal_s16(xy02_s32x4, vget_high_s16(x_s16x8), vget_high_s16(y02_s16x8));
}
if (N - i >= 4) {
const int16x4_t x_s16x4 = vld1_s16(&x[i]);
const int16x4_t y01_s16x4 = vld1_s16(&y01[i]);
const int16x4_t y02_s16x4 = vld1_s16(&y02[i]);
xy01_s32x4 = vmlal_s16(xy01_s32x4, x_s16x4, y01_s16x4);
xy02_s32x4 = vmlal_s16(xy02_s32x4, x_s16x4, y02_s16x4);
i += 4;
}
xy01_s64x2 = vpaddlq_s32(xy01_s32x4);
xy02_s64x2 = vpaddlq_s32(xy02_s32x4);
xy01_s64x1 = vadd_s64(vget_low_s64(xy01_s64x2), vget_high_s64(xy01_s64x2));
xy02_s64x1 = vadd_s64(vget_low_s64(xy02_s64x2), vget_high_s64(xy02_s64x2));
xy01 = vget_lane_s32(vreinterpret_s32_s64(xy01_s64x1), 0);
xy02 = vget_lane_s32(vreinterpret_s32_s64(xy02_s64x1), 0);
for (; i < N; i++) {
xy01 = MAC16_16(xy01, x[i], y01[i]);
xy02 = MAC16_16(xy02, x[i], y02[i]);
}
*xy1 = xy01;
*xy2 = xy02;
#ifdef OPUS_CHECK_ASM
{
opus_val32 xy1_c, xy2_c;
dual_inner_prod_c(x, y01, y02, N, &xy1_c, &xy2_c);
celt_assert(xy1_c == *xy1);
celt_assert(xy2_c == *xy2);
}
#endif
}
#else /* !FIXED_POINT */
/* ========================================================================== */
#ifdef OPUS_CHECK_ASM
/* This part of code simulates floating-point NEON operations. */
/* celt_inner_prod_neon_float_c_simulation() simulates the floating-point */
/* operations of celt_inner_prod_neon(), and both functions should have bit */
/* exact output. */
static opus_val32 celt_inner_prod_neon_float_c_simulation(const opus_val16 *x, const opus_val16 *y, int N)
{
int i;
opus_val32 xy, xy0 = 0, xy1 = 0, xy2 = 0, xy3 = 0;
for (i = 0; i < N - 3; i += 4) {
xy0 = MAC16_16(xy0, x[i + 0], y[i + 0]);
xy1 = MAC16_16(xy1, x[i + 1], y[i + 1]);
xy2 = MAC16_16(xy2, x[i + 2], y[i + 2]);
xy3 = MAC16_16(xy3, x[i + 3], y[i + 3]);
}
xy0 += xy2;
xy1 += xy3;
xy = xy0 + xy1;
for (; i < N; i++) {
xy = MAC16_16(xy, x[i], y[i]);
}
return xy;
}
/* dual_inner_prod_neon_float_c_simulation() simulates the floating-point */
/* operations of dual_inner_prod_neon(), and both functions should have bit */
/* exact output. */
static void dual_inner_prod_neon_float_c_simulation(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, xy02, xy01_0 = 0, xy01_1 = 0, xy01_2 = 0, xy01_3 = 0, xy02_0 = 0, xy02_1 = 0, xy02_2 = 0, xy02_3 = 0;
for (i = 0; i < N - 3; i += 4) {
xy01_0 = MAC16_16(xy01_0, x[i + 0], y01[i + 0]);
xy01_1 = MAC16_16(xy01_1, x[i + 1], y01[i + 1]);
xy01_2 = MAC16_16(xy01_2, x[i + 2], y01[i + 2]);
xy01_3 = MAC16_16(xy01_3, x[i + 3], y01[i + 3]);
xy02_0 = MAC16_16(xy02_0, x[i + 0], y02[i + 0]);
xy02_1 = MAC16_16(xy02_1, x[i + 1], y02[i + 1]);
xy02_2 = MAC16_16(xy02_2, x[i + 2], y02[i + 2]);
xy02_3 = MAC16_16(xy02_3, x[i + 3], y02[i + 3]);
}
xy01_0 += xy01_2;
xy02_0 += xy02_2;
xy01_1 += xy01_3;
xy02_1 += xy02_3;
xy01 = xy01_0 + xy01_1;
xy02 = xy02_0 + xy02_1;
for (; i < N; i++) {
xy01 = MAC16_16(xy01, x[i], y01[i]);
xy02 = MAC16_16(xy02, x[i], y02[i]);
}
*xy1 = xy01;
*xy2 = xy02;
}
#endif /* OPUS_CHECK_ASM */
/* ========================================================================== */
opus_val32 celt_inner_prod_neon(const opus_val16 *x, const opus_val16 *y, int N)
{
int i;
opus_val32 xy;
float32x4_t xy_f32x4 = vdupq_n_f32(0);
float32x2_t xy_f32x2;
for (i = 0; i < N - 7; i += 8) {
float32x4_t x_f32x4, y_f32x4;
x_f32x4 = vld1q_f32(&x[i]);
y_f32x4 = vld1q_f32(&y[i]);
xy_f32x4 = vmlaq_f32(xy_f32x4, x_f32x4, y_f32x4);
x_f32x4 = vld1q_f32(&x[i + 4]);
y_f32x4 = vld1q_f32(&y[i + 4]);
xy_f32x4 = vmlaq_f32(xy_f32x4, x_f32x4, y_f32x4);
}
if (N - i >= 4) {
const float32x4_t x_f32x4 = vld1q_f32(&x[i]);
const float32x4_t y_f32x4 = vld1q_f32(&y[i]);
xy_f32x4 = vmlaq_f32(xy_f32x4, x_f32x4, y_f32x4);
i += 4;
}
xy_f32x2 = vadd_f32(vget_low_f32(xy_f32x4), vget_high_f32(xy_f32x4));
xy_f32x2 = vpadd_f32(xy_f32x2, xy_f32x2);
xy = vget_lane_f32(xy_f32x2, 0);
for (; i < N; i++) {
xy = MAC16_16(xy, x[i], y[i]);
}
#ifdef OPUS_CHECK_ASM
celt_assert(ABS32(celt_inner_prod_neon_float_c_simulation(x, y, N) - xy) <= VERY_SMALL);
#endif
return xy;
}
void dual_inner_prod_neon(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, xy02;
float32x4_t xy01_f32x4 = vdupq_n_f32(0);
float32x4_t xy02_f32x4 = vdupq_n_f32(0);
float32x2_t xy01_f32x2, xy02_f32x2;
for (i = 0; i < N - 7; i += 8) {
float32x4_t x_f32x4, y01_f32x4, y02_f32x4;
x_f32x4 = vld1q_f32(&x[i]);
y01_f32x4 = vld1q_f32(&y01[i]);
y02_f32x4 = vld1q_f32(&y02[i]);
xy01_f32x4 = vmlaq_f32(xy01_f32x4, x_f32x4, y01_f32x4);
xy02_f32x4 = vmlaq_f32(xy02_f32x4, x_f32x4, y02_f32x4);
x_f32x4 = vld1q_f32(&x[i + 4]);
y01_f32x4 = vld1q_f32(&y01[i + 4]);
y02_f32x4 = vld1q_f32(&y02[i + 4]);
xy01_f32x4 = vmlaq_f32(xy01_f32x4, x_f32x4, y01_f32x4);
xy02_f32x4 = vmlaq_f32(xy02_f32x4, x_f32x4, y02_f32x4);
}
if (N - i >= 4) {
const float32x4_t x_f32x4 = vld1q_f32(&x[i]);
const float32x4_t y01_f32x4 = vld1q_f32(&y01[i]);
const float32x4_t y02_f32x4 = vld1q_f32(&y02[i]);
xy01_f32x4 = vmlaq_f32(xy01_f32x4, x_f32x4, y01_f32x4);
xy02_f32x4 = vmlaq_f32(xy02_f32x4, x_f32x4, y02_f32x4);
i += 4;
}
xy01_f32x2 = vadd_f32(vget_low_f32(xy01_f32x4), vget_high_f32(xy01_f32x4));
xy02_f32x2 = vadd_f32(vget_low_f32(xy02_f32x4), vget_high_f32(xy02_f32x4));
xy01_f32x2 = vpadd_f32(xy01_f32x2, xy01_f32x2);
xy02_f32x2 = vpadd_f32(xy02_f32x2, xy02_f32x2);
xy01 = vget_lane_f32(xy01_f32x2, 0);
xy02 = vget_lane_f32(xy02_f32x2, 0);
for (; i < N; i++) {
xy01 = MAC16_16(xy01, x[i], y01[i]);
xy02 = MAC16_16(xy02, x[i], y02[i]);
}
*xy1 = xy01;
*xy2 = xy02;
#ifdef OPUS_CHECK_ASM
{
opus_val32 xy1_c, xy2_c;
dual_inner_prod_neon_float_c_simulation(x, y01, y02, N, &xy1_c, &xy2_c);
celt_assert(ABS32(xy1_c - *xy1) <= VERY_SMALL);
celt_assert(ABS32(xy2_c - *xy2) <= VERY_SMALL);
}
#endif
}
#endif /* FIXED_POINT */

View file

@ -65,19 +65,19 @@ opus_uint32 celt_lcg_rand(opus_uint32 seed)
/* This is a cos() approximation designed to be bit-exact on any platform. Bit exactness /* This is a cos() approximation designed to be bit-exact on any platform. Bit exactness
with this approximation is important because it has an impact on the bit allocation */ with this approximation is important because it has an impact on the bit allocation */
static opus_int16 bitexact_cos(opus_int16 x) opus_int16 bitexact_cos(opus_int16 x)
{ {
opus_int32 tmp; opus_int32 tmp;
opus_int16 x2; opus_int16 x2;
tmp = (4096+((opus_int32)(x)*(x)))>>13; tmp = (4096+((opus_int32)(x)*(x)))>>13;
celt_assert(tmp<=32767); celt_sig_assert(tmp<=32767);
x2 = tmp; x2 = tmp;
x2 = (32767-x2) + FRAC_MUL16(x2, (-7651 + FRAC_MUL16(x2, (8277 + FRAC_MUL16(-626, x2))))); x2 = (32767-x2) + FRAC_MUL16(x2, (-7651 + FRAC_MUL16(x2, (8277 + FRAC_MUL16(-626, x2)))));
celt_assert(x2<=32766); celt_sig_assert(x2<=32766);
return 1+x2; return 1+x2;
} }
static int bitexact_log2tan(int isin,int icos) int bitexact_log2tan(int isin,int icos)
{ {
int lc; int lc;
int ls; int ls;
@ -90,13 +90,13 @@ static int bitexact_log2tan(int isin,int icos)
-FRAC_MUL16(icos, FRAC_MUL16(icos, -2597) + 7932); -FRAC_MUL16(icos, FRAC_MUL16(icos, -2597) + 7932);
} }
#if 0
#ifdef FIXED_POINT #ifdef FIXED_POINT
/* Compute the amplitude (sqrt energy) in each of the bands */ /* Compute the amplitude (sqrt energy) in each of the bands */
void compute_band_energies(const CELTMode *m, const celt_sig *X, celt_ener *bandE, int end, int C, int LM) void compute_band_energies(const CELTMode *m, const celt_sig *X, celt_ener *bandE, int end, int C, int LM, int arch)
{ {
int i, c, N; int i, c, N;
const opus_int16 *eBands = m->eBands; const opus_int16 *eBands = m->eBands;
(void)arch;
N = m->shortMdctSize<<LM; N = m->shortMdctSize<<LM;
c=0; do { c=0; do {
for (i=0;i<end;i++) for (i=0;i<end;i++)
@ -156,7 +156,7 @@ void normalise_bands(const CELTMode *m, const celt_sig * OPUS_RESTRICT freq, cel
#else /* FIXED_POINT */ #else /* FIXED_POINT */
/* Compute the amplitude (sqrt energy) in each of the bands */ /* Compute the amplitude (sqrt energy) in each of the bands */
void compute_band_energies(const CELTMode *m, const celt_sig *X, celt_ener *bandE, int end, int C, int LM) void compute_band_energies(const CELTMode *m, const celt_sig *X, celt_ener *bandE, int end, int C, int LM, int arch)
{ {
int i, c, N; int i, c, N;
const opus_int16 *eBands = m->eBands; const opus_int16 *eBands = m->eBands;
@ -165,7 +165,7 @@ void compute_band_energies(const CELTMode *m, const celt_sig *X, celt_ener *band
for (i=0;i<end;i++) for (i=0;i<end;i++)
{ {
opus_val32 sum; opus_val32 sum;
sum = 1e-27f + celt_inner_prod(&X[c*N+(eBands[i]<<LM)], &X[c*N+(eBands[i]<<LM)], (eBands[i+1]-eBands[i])<<LM); sum = 1e-27f + celt_inner_prod(&X[c*N+(eBands[i]<<LM)], &X[c*N+(eBands[i]<<LM)], (eBands[i+1]-eBands[i])<<LM, arch);
bandE[i+c*m->nbEBands] = celt_sqrt(sum); bandE[i+c*m->nbEBands] = celt_sqrt(sum);
/*printf ("%f ", bandE[i+c*m->nbEBands]);*/ /*printf ("%f ", bandE[i+c*m->nbEBands]);*/
} }
@ -191,7 +191,6 @@ void normalise_bands(const CELTMode *m, const celt_sig * OPUS_RESTRICT freq, cel
} }
#endif /* FIXED_POINT */ #endif /* FIXED_POINT */
#endif
/* De-normalise the energy to produce the synthesis from the unit-energy bands */ /* De-normalise the energy to produce the synthesis from the unit-energy bands */
void denormalise_bands(const CELTMode *m, const celt_norm * OPUS_RESTRICT X, void denormalise_bands(const CELTMode *m, const celt_norm * OPUS_RESTRICT X,
@ -226,9 +225,9 @@ void denormalise_bands(const CELTMode *m, const celt_norm * OPUS_RESTRICT X,
#endif #endif
j=M*eBands[i]; j=M*eBands[i];
band_end = M*eBands[i+1]; band_end = M*eBands[i+1];
lg = ADD16(bandLogE[i], SHL16((opus_val16)eMeans[i],6)); lg = SATURATE16(ADD32(bandLogE[i], SHL32((opus_val32)eMeans[i],6)));
#ifndef FIXED_POINT #ifndef FIXED_POINT
g = celt_exp2(lg); g = celt_exp2(MIN32(32.f, lg));
#else #else
/* Handle the integer part of the log energy */ /* Handle the integer part of the log energy */
shift = 16-(lg>>DB_SHIFT); shift = 16-(lg>>DB_SHIFT);
@ -243,12 +242,12 @@ void denormalise_bands(const CELTMode *m, const celt_norm * OPUS_RESTRICT X,
/* Handle extreme gains with negative shift. */ /* Handle extreme gains with negative shift. */
if (shift<0) if (shift<0)
{ {
/* For shift < -2 we'd be likely to overflow, so we're capping /* For shift <= -2 and g > 16384 we'd be likely to overflow, so we're
the gain here. This shouldn't happen unless the bitstream is capping the gain here, which is equivalent to a cap of 18 on lg.
already corrupted. */ This shouldn't trigger unless the bitstream is already corrupted. */
if (shift < -2) if (shift <= -2)
{ {
g = 32767; g = 16384;
shift = -2; shift = -2;
} }
do { do {
@ -268,7 +267,7 @@ void denormalise_bands(const CELTMode *m, const celt_norm * OPUS_RESTRICT X,
/* This prevents energy collapse for transients with multiple short MDCTs */ /* This prevents energy collapse for transients with multiple short MDCTs */
void anti_collapse(const CELTMode *m, celt_norm *X_, unsigned char *collapse_masks, int LM, int C, int size, void anti_collapse(const CELTMode *m, celt_norm *X_, unsigned char *collapse_masks, int LM, int C, int size,
int start, int end, const opus_val16 *logE, const opus_val16 *prev1logE, int start, int end, const opus_val16 *logE, const opus_val16 *prev1logE,
const opus_val16 *prev2logE, const int *pulses, opus_uint32 seed) const opus_val16 *prev2logE, const int *pulses, opus_uint32 seed, int arch)
{ {
int c, i, j, k; int c, i, j, k;
for (i=start;i<end;i++) for (i=start;i<end;i++)
@ -283,7 +282,7 @@ void anti_collapse(const CELTMode *m, celt_norm *X_, unsigned char *collapse_mas
N0 = m->eBands[i+1]-m->eBands[i]; N0 = m->eBands[i+1]-m->eBands[i];
/* depth in 1/8 bits */ /* depth in 1/8 bits */
celt_assert(pulses[i]>=0); celt_sig_assert(pulses[i]>=0);
depth = celt_udiv(1+pulses[i], (m->eBands[i+1]-m->eBands[i]))>>LM; depth = celt_udiv(1+pulses[i], (m->eBands[i+1]-m->eBands[i]))>>LM;
#ifdef FIXED_POINT #ifdef FIXED_POINT
@ -357,11 +356,35 @@ void anti_collapse(const CELTMode *m, celt_norm *X_, unsigned char *collapse_mas
} }
/* We just added some energy, so we need to renormalise */ /* We just added some energy, so we need to renormalise */
if (renormalize) if (renormalize)
renormalise_vector(X, N0<<LM, Q15ONE); renormalise_vector(X, N0<<LM, Q15ONE, arch);
} while (++c<C); } while (++c<C);
} }
} }
/* Compute the weights to use for optimizing normalized distortion across
channels. We use the amplitude to weight square distortion, which means
that we use the square root of the value we would have been using if we
wanted to minimize the MSE in the non-normalized domain. This roughly
corresponds to some quick-and-dirty perceptual experiments I ran to
measure inter-aural masking (there doesn't seem to be any published data
on the topic). */
static void compute_channel_weights(celt_ener Ex, celt_ener Ey, opus_val16 w[2])
{
celt_ener minE;
#ifdef FIXED_POINT
int shift;
#endif
minE = MIN32(Ex, Ey);
/* Adjustment to make the weights a bit more conservative. */
Ex = ADD32(Ex, minE/3);
Ey = ADD32(Ey, minE/3);
#ifdef FIXED_POINT
shift = celt_ilog2(EPSILON+MAX32(Ex, Ey))-14;
#endif
w[0] = VSHR32(Ex, shift);
w[1] = VSHR32(Ey, shift);
}
static void intensity_stereo(const CELTMode *m, celt_norm * OPUS_RESTRICT X, const celt_norm * OPUS_RESTRICT Y, const celt_ener *bandE, int bandID, int N) static void intensity_stereo(const CELTMode *m, celt_norm * OPUS_RESTRICT X, const celt_norm * OPUS_RESTRICT Y, const celt_ener *bandE, int bandID, int N)
{ {
int i = bandID; int i = bandID;
@ -400,7 +423,7 @@ static void stereo_split(celt_norm * OPUS_RESTRICT X, celt_norm * OPUS_RESTRICT
} }
} }
static void stereo_merge(celt_norm * OPUS_RESTRICT X, celt_norm * OPUS_RESTRICT Y, opus_val16 mid, int N) static void stereo_merge(celt_norm * OPUS_RESTRICT X, celt_norm * OPUS_RESTRICT Y, opus_val16 mid, int N, int arch)
{ {
int j; int j;
opus_val32 xp=0, side=0; opus_val32 xp=0, side=0;
@ -412,11 +435,11 @@ static void stereo_merge(celt_norm * OPUS_RESTRICT X, celt_norm * OPUS_RESTRICT
opus_val32 t, lgain, rgain; opus_val32 t, lgain, rgain;
/* Compute the norm of X+Y and X-Y as |X|^2 + |Y|^2 +/- sum(xy) */ /* Compute the norm of X+Y and X-Y as |X|^2 + |Y|^2 +/- sum(xy) */
dual_inner_prod(Y, X, Y, N, &xp, &side); dual_inner_prod(Y, X, Y, N, &xp, &side, arch);
/* Compensating for the mid normalization */ /* Compensating for the mid normalization */
xp = MULT16_32_Q15(mid, xp); xp = MULT16_32_Q15(mid, xp);
/* mid and side are in Q15, not Q14 like X and Y */ /* mid and side are in Q15, not Q14 like X and Y */
mid2 = SHR32(mid, 1); mid2 = SHR16(mid, 1);
El = MULT16_16(mid2, mid2) + side - 2*xp; El = MULT16_16(mid2, mid2) + side - 2*xp;
Er = MULT16_16(mid2, mid2) + side + 2*xp; Er = MULT16_16(mid2, mid2) + side + 2*xp;
if (Er < QCONST32(6e-4f, 28) || El < QCONST32(6e-4f, 28)) if (Er < QCONST32(6e-4f, 28) || El < QCONST32(6e-4f, 28))
@ -452,11 +475,10 @@ static void stereo_merge(celt_norm * OPUS_RESTRICT X, celt_norm * OPUS_RESTRICT
} }
} }
#if 0
/* Decide whether we should spread the pulses in the current frame */ /* Decide whether we should spread the pulses in the current frame */
int spreading_decision(const CELTMode *m, const celt_norm *X, int *average, 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 last_decision, int *hf_average, int *tapset_decision, int update_hf,
int end, int C, int M) int end, int C, int M, const int *spread_weight)
{ {
int i, c, N0; int i, c, N0;
int sum = 0, nbBands=0; int sum = 0, nbBands=0;
@ -497,8 +519,8 @@ int spreading_decision(const CELTMode *m, const celt_norm *X, int *average,
if (i>m->nbEBands-4) if (i>m->nbEBands-4)
hf_sum += celt_udiv(32*(tcount[1]+tcount[0]), N); hf_sum += celt_udiv(32*(tcount[1]+tcount[0]), N);
tmp = (2*tcount[2] >= N) + (2*tcount[1] >= N) + (2*tcount[0] >= N); tmp = (2*tcount[2] >= N) + (2*tcount[1] >= N) + (2*tcount[0] >= N);
sum += tmp*256; sum += tmp*spread_weight[i];
nbBands++; nbBands+=spread_weight[i];
} }
} while (++c<C); } while (++c<C);
@ -522,7 +544,7 @@ int spreading_decision(const CELTMode *m, const celt_norm *X, int *average,
/*printf("%d %d %d\n", hf_sum, *hf_average, *tapset_decision);*/ /*printf("%d %d %d\n", hf_sum, *hf_average, *tapset_decision);*/
celt_assert(nbBands>0); /* end has to be non-zero */ celt_assert(nbBands>0); /* end has to be non-zero */
celt_assert(sum>=0); celt_assert(sum>=0);
sum = celt_udiv(sum, nbBands); sum = celt_udiv((opus_int32)sum<<8, nbBands);
/* Recursive averaging */ /* Recursive averaging */
sum = (sum+*average)>>1; sum = (sum+*average)>>1;
*average = sum; *average = sum;
@ -546,7 +568,6 @@ int spreading_decision(const CELTMode *m, const celt_norm *X, int *average,
#endif #endif
return decision; return decision;
} }
#endif
/* Indexing table for converting from natural Hadamard to ordery Hadamard /* Indexing table for converting from natural Hadamard to ordery Hadamard
This is essentially a bit-reversed Gray, on top of which we've added This is essentially a bit-reversed Gray, on top of which we've added
@ -651,6 +672,7 @@ static int compute_qn(int N, int b, int offset, int pulse_cap, int stereo)
struct band_ctx { struct band_ctx {
int encode; int encode;
int resynth;
const CELTMode *m; const CELTMode *m;
int i; int i;
int intensity; int intensity;
@ -660,6 +682,10 @@ struct band_ctx {
opus_int32 remaining_bits; opus_int32 remaining_bits;
const celt_ener *bandE; const celt_ener *bandE;
opus_uint32 seed; opus_uint32 seed;
int arch;
int theta_round;
int disable_inv;
int avoid_split_noise;
}; };
struct split_ctx { struct split_ctx {
@ -711,14 +737,41 @@ static void compute_theta(struct band_ctx *ctx, struct split_ctx *sctx,
side and mid. With just that parameter, we can re-scale both side and mid. With just that parameter, we can re-scale both
mid and side because we know that 1) they have unit norm and mid and side because we know that 1) they have unit norm and
2) they are orthogonal. */ 2) they are orthogonal. */
itheta = stereo_itheta(X, Y, stereo, N); itheta = stereo_itheta(X, Y, stereo, N, ctx->arch);
} }
tell = ec_tell_frac(ec); tell = ec_tell_frac(ec);
if (qn!=1) if (qn!=1)
{ {
if (encode) if (encode)
itheta = (itheta*qn+8192)>>14; {
if (!stereo || ctx->theta_round == 0)
{
itheta = (itheta*(opus_int32)qn+8192)>>14;
if (!stereo && ctx->avoid_split_noise && itheta > 0 && itheta < qn)
{
/* Check if the selected value of theta will cause the bit allocation
to inject noise on one side. If so, make sure the energy of that side
is zero. */
int unquantized = celt_udiv((opus_int32)itheta*16384, qn);
imid = bitexact_cos((opus_int16)unquantized);
iside = bitexact_cos((opus_int16)(16384-unquantized));
delta = FRAC_MUL16((N-1)<<7,bitexact_log2tan(iside,imid));
if (delta > *b)
itheta = qn;
else if (delta < -*b)
itheta = 0;
}
} else {
int down;
/* Bias quantization towards itheta=0 and itheta=16384. */
int bias = itheta > 8192 ? 32767/qn : -32767/qn;
down = IMIN(qn-1, IMAX(0, (itheta*(opus_int32)qn + bias)>>14));
if (ctx->theta_round < 0)
itheta = down;
else
itheta = down+1;
}
}
/* Entropy coding of the angle. We use a uniform pdf for the /* Entropy coding of the angle. We use a uniform pdf for the
time split, a step for stereo, and a triangular one for the rest. */ time split, a step for stereo, and a triangular one for the rest. */
if (stereo && N>2) if (stereo && N>2)
@ -796,7 +849,7 @@ static void compute_theta(struct band_ctx *ctx, struct split_ctx *sctx,
} else if (stereo) { } else if (stereo) {
if (encode) if (encode)
{ {
inv = itheta > 8192; inv = itheta > 8192 && !ctx->disable_inv;
if (inv) if (inv)
{ {
int j; int j;
@ -813,6 +866,9 @@ static void compute_theta(struct band_ctx *ctx, struct split_ctx *sctx,
inv = ec_dec_bit_logp(ec, 2); inv = ec_dec_bit_logp(ec, 2);
} else } else
inv = 0; inv = 0;
/* inv flag override to avoid problems with downmixing. */
if (ctx->disable_inv)
inv = 0;
itheta = 0; itheta = 0;
} }
qalloc = ec_tell_frac(ec) - tell; qalloc = ec_tell_frac(ec) - tell;
@ -848,11 +904,6 @@ static void compute_theta(struct band_ctx *ctx, struct split_ctx *sctx,
static unsigned quant_band_n1(struct band_ctx *ctx, celt_norm *X, celt_norm *Y, int b, static unsigned quant_band_n1(struct band_ctx *ctx, celt_norm *X, celt_norm *Y, int b,
celt_norm *lowband_out) celt_norm *lowband_out)
{ {
#ifdef RESYNTH
int resynth = 1;
#else
int resynth = !ctx->encode;
#endif
int c; int c;
int stereo; int stereo;
celt_norm *x = X; celt_norm *x = X;
@ -877,7 +928,7 @@ static unsigned quant_band_n1(struct band_ctx *ctx, celt_norm *X, celt_norm *Y,
ctx->remaining_bits -= 1<<BITRES; ctx->remaining_bits -= 1<<BITRES;
b-=1<<BITRES; b-=1<<BITRES;
} }
if (resynth) if (ctx->resynth)
x[0] = sign ? -NORM_SCALING : NORM_SCALING; x[0] = sign ? -NORM_SCALING : NORM_SCALING;
x = Y; x = Y;
} while (++c<1+stereo); } while (++c<1+stereo);
@ -902,11 +953,6 @@ static unsigned quant_partition(struct band_ctx *ctx, celt_norm *X,
int B0=B; int B0=B;
opus_val16 mid=0, side=0; opus_val16 mid=0, side=0;
unsigned cm=0; unsigned cm=0;
#ifdef RESYNTH
int resynth = 1;
#else
int resynth = !ctx->encode;
#endif
celt_norm *Y=NULL; celt_norm *Y=NULL;
int encode; int encode;
const CELTMode *m; const CELTMode *m;
@ -938,8 +984,7 @@ static unsigned quant_partition(struct band_ctx *ctx, celt_norm *X,
fill = (fill&1)|(fill<<1); fill = (fill&1)|(fill<<1);
B = (B+1)>>1; B = (B+1)>>1;
compute_theta(ctx, &sctx, X, Y, N, &b, B, B0, compute_theta(ctx, &sctx, X, Y, N, &b, B, B0, LM, 0, &fill);
LM, 0, &fill);
imid = sctx.imid; imid = sctx.imid;
iside = sctx.iside; iside = sctx.iside;
delta = sctx.delta; delta = sctx.delta;
@ -973,24 +1018,20 @@ static unsigned quant_partition(struct band_ctx *ctx, celt_norm *X,
rebalance = ctx->remaining_bits; rebalance = ctx->remaining_bits;
if (mbits >= sbits) if (mbits >= sbits)
{ {
cm = quant_partition(ctx, X, N, mbits, B, cm = quant_partition(ctx, X, N, mbits, B, lowband, LM,
lowband, LM,
MULT16_16_P15(gain,mid), fill); MULT16_16_P15(gain,mid), fill);
rebalance = mbits - (rebalance-ctx->remaining_bits); rebalance = mbits - (rebalance-ctx->remaining_bits);
if (rebalance > 3<<BITRES && itheta!=0) if (rebalance > 3<<BITRES && itheta!=0)
sbits += rebalance - (3<<BITRES); sbits += rebalance - (3<<BITRES);
cm |= quant_partition(ctx, Y, N, sbits, B, cm |= quant_partition(ctx, Y, N, sbits, B, next_lowband2, LM,
next_lowband2, LM,
MULT16_16_P15(gain,side), fill>>B)<<(B0>>1); MULT16_16_P15(gain,side), fill>>B)<<(B0>>1);
} else { } else {
cm = quant_partition(ctx, Y, N, sbits, B, cm = quant_partition(ctx, Y, N, sbits, B, next_lowband2, LM,
next_lowband2, LM,
MULT16_16_P15(gain,side), fill>>B)<<(B0>>1); MULT16_16_P15(gain,side), fill>>B)<<(B0>>1);
rebalance = sbits - (rebalance-ctx->remaining_bits); rebalance = sbits - (rebalance-ctx->remaining_bits);
if (rebalance > 3<<BITRES && itheta!=16384) if (rebalance > 3<<BITRES && itheta!=16384)
mbits += rebalance - (3<<BITRES); mbits += rebalance - (3<<BITRES);
cm |= quant_partition(ctx, X, N, mbits, B, cm |= quant_partition(ctx, X, N, mbits, B, lowband, LM,
lowband, LM,
MULT16_16_P15(gain,mid), fill); MULT16_16_P15(gain,mid), fill);
} }
} else { } else {
@ -1015,18 +1056,14 @@ static unsigned quant_partition(struct band_ctx *ctx, celt_norm *X,
/* Finally do the actual quantization */ /* Finally do the actual quantization */
if (encode) if (encode)
{ {
cm = alg_quant(X, N, K, spread, B, ec cm = alg_quant(X, N, K, spread, B, ec, gain, ctx->resynth, ctx->arch);
#ifdef RESYNTH
, gain
#endif
);
} else { } else {
cm = alg_unquant(X, N, K, spread, B, ec, gain); cm = alg_unquant(X, N, K, spread, B, ec, gain);
} }
} else { } else {
/* If there's no pulse, fill the band anyway */ /* If there's no pulse, fill the band anyway */
int j; int j;
if (resynth) if (ctx->resynth)
{ {
unsigned cm_mask; unsigned cm_mask;
/* B can be as large as 16, so this shift might overflow an int on a /* B can be as large as 16, so this shift might overflow an int on a
@ -1059,7 +1096,7 @@ static unsigned quant_partition(struct band_ctx *ctx, celt_norm *X,
} }
cm = fill; cm = fill;
} }
renormalise_vector(X, N, gain); renormalise_vector(X, N, gain, ctx->arch);
} }
} }
} }
@ -1083,11 +1120,6 @@ static unsigned quant_band(struct band_ctx *ctx, celt_norm *X,
int recombine=0; int recombine=0;
int longBlocks; int longBlocks;
unsigned cm=0; unsigned cm=0;
#ifdef RESYNTH
int resynth = 1;
#else
int resynth = !ctx->encode;
#endif
int k; int k;
int encode; int encode;
int tf_change; int tf_change;
@ -1154,11 +1186,10 @@ static unsigned quant_band(struct band_ctx *ctx, celt_norm *X,
deinterleave_hadamard(lowband, N_B>>recombine, B0<<recombine, longBlocks); deinterleave_hadamard(lowband, N_B>>recombine, B0<<recombine, longBlocks);
} }
cm = quant_partition(ctx, X, N, b, B, lowband, cm = quant_partition(ctx, X, N, b, B, lowband, LM, gain, fill);
LM, gain, fill);
/* This code is used by the decoder and by the resynthesis-enabled encoder */ /* This code is used by the decoder and by the resynthesis-enabled encoder */
if (resynth) if (ctx->resynth)
{ {
/* Undo the sample reorganization going from time order to frequency order */ /* Undo the sample reorganization going from time order to frequency order */
if (B0>1) if (B0>1)
@ -1211,11 +1242,6 @@ static unsigned quant_band_stereo(struct band_ctx *ctx, celt_norm *X, celt_norm
int inv = 0; int inv = 0;
opus_val16 mid=0, side=0; opus_val16 mid=0, side=0;
unsigned cm=0; unsigned cm=0;
#ifdef RESYNTH
int resynth = 1;
#else
int resynth = !ctx->encode;
#endif
int mbits, sbits, delta; int mbits, sbits, delta;
int itheta; int itheta;
int qalloc; int qalloc;
@ -1235,8 +1261,7 @@ static unsigned quant_band_stereo(struct band_ctx *ctx, celt_norm *X, celt_norm
orig_fill = fill; orig_fill = fill;
compute_theta(ctx, &sctx, X, Y, N, &b, B, B, compute_theta(ctx, &sctx, X, Y, N, &b, B, B, LM, 1, &fill);
LM, 1, &fill);
inv = sctx.inv; inv = sctx.inv;
imid = sctx.imid; imid = sctx.imid;
iside = sctx.iside; iside = sctx.iside;
@ -1284,13 +1309,13 @@ static unsigned quant_band_stereo(struct band_ctx *ctx, celt_norm *X, celt_norm
sign = 1-2*sign; sign = 1-2*sign;
/* We use orig_fill here because we want to fold the side, but if /* We use orig_fill here because we want to fold the side, but if
itheta==16384, we'll have cleared the low bits of fill. */ itheta==16384, we'll have cleared the low bits of fill. */
cm = quant_band(ctx, x2, N, mbits, B, lowband, cm = quant_band(ctx, x2, N, mbits, B, lowband, LM, lowband_out, Q15ONE,
LM, lowband_out, Q15ONE, lowband_scratch, orig_fill); lowband_scratch, orig_fill);
/* We don't split N=2 bands, so cm is either 1 or 0 (for a fold-collapse), /* We don't split N=2 bands, so cm is either 1 or 0 (for a fold-collapse),
and there's no need to worry about mixing with the other channel. */ and there's no need to worry about mixing with the other channel. */
y2[0] = -sign*x2[1]; y2[0] = -sign*x2[1];
y2[1] = sign*x2[0]; y2[1] = sign*x2[0];
if (resynth) if (ctx->resynth)
{ {
celt_norm tmp; celt_norm tmp;
X[0] = MULT16_16_Q15(mid, X[0]); X[0] = MULT16_16_Q15(mid, X[0]);
@ -1317,41 +1342,35 @@ static unsigned quant_band_stereo(struct band_ctx *ctx, celt_norm *X, celt_norm
{ {
/* In stereo mode, we do not apply a scaling to the mid because we need the normalized /* In stereo mode, we do not apply a scaling to the mid because we need the normalized
mid for folding later. */ mid for folding later. */
cm = quant_band(ctx, X, N, mbits, B, cm = quant_band(ctx, X, N, mbits, B, lowband, LM, lowband_out, Q15ONE,
lowband, LM, lowband_out, lowband_scratch, fill);
Q15ONE, lowband_scratch, fill);
rebalance = mbits - (rebalance-ctx->remaining_bits); rebalance = mbits - (rebalance-ctx->remaining_bits);
if (rebalance > 3<<BITRES && itheta!=0) if (rebalance > 3<<BITRES && itheta!=0)
sbits += rebalance - (3<<BITRES); sbits += rebalance - (3<<BITRES);
/* For a stereo split, the high bits of fill are always zero, so no /* For a stereo split, the high bits of fill are always zero, so no
folding will be done to the side. */ folding will be done to the side. */
cm |= quant_band(ctx, Y, N, sbits, B, cm |= quant_band(ctx, Y, N, sbits, B, NULL, LM, NULL, side, NULL, fill>>B);
NULL, LM, NULL,
side, NULL, fill>>B);
} else { } else {
/* For a stereo split, the high bits of fill are always zero, so no /* For a stereo split, the high bits of fill are always zero, so no
folding will be done to the side. */ folding will be done to the side. */
cm = quant_band(ctx, Y, N, sbits, B, cm = quant_band(ctx, Y, N, sbits, B, NULL, LM, NULL, side, NULL, fill>>B);
NULL, LM, NULL,
side, NULL, fill>>B);
rebalance = sbits - (rebalance-ctx->remaining_bits); rebalance = sbits - (rebalance-ctx->remaining_bits);
if (rebalance > 3<<BITRES && itheta!=16384) if (rebalance > 3<<BITRES && itheta!=16384)
mbits += rebalance - (3<<BITRES); mbits += rebalance - (3<<BITRES);
/* In stereo mode, we do not apply a scaling to the mid because we need the normalized /* In stereo mode, we do not apply a scaling to the mid because we need the normalized
mid for folding later. */ mid for folding later. */
cm |= quant_band(ctx, X, N, mbits, B, cm |= quant_band(ctx, X, N, mbits, B, lowband, LM, lowband_out, Q15ONE,
lowband, LM, lowband_out, lowband_scratch, fill);
Q15ONE, lowband_scratch, fill);
} }
} }
/* This code is used by the decoder and by the resynthesis-enabled encoder */ /* This code is used by the decoder and by the resynthesis-enabled encoder */
if (resynth) if (ctx->resynth)
{ {
if (N!=2) if (N!=2)
stereo_merge(X, Y, mid, N); stereo_merge(X, Y, mid, N, ctx->arch);
if (inv) if (inv)
{ {
int j; int j;
@ -1362,17 +1381,38 @@ static unsigned quant_band_stereo(struct band_ctx *ctx, celt_norm *X, celt_norm
return cm; return cm;
} }
static void special_hybrid_folding(const CELTMode *m, celt_norm *norm, celt_norm *norm2, int start, int M, int dual_stereo)
{
int n1, n2;
const opus_int16 * OPUS_RESTRICT eBands = m->eBands;
n1 = M*(eBands[start+1]-eBands[start]);
n2 = M*(eBands[start+2]-eBands[start+1]);
/* Duplicate enough of the first band folding data to be able to fold the second band.
Copies no data for CELT-only mode. */
OPUS_COPY(&norm[n1], &norm[2*n1 - n2], n2-n1);
if (dual_stereo)
OPUS_COPY(&norm2[n1], &norm2[2*n1 - n2], n2-n1);
}
void quant_all_bands(int encode, const CELTMode *m, int start, int end, 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, celt_norm *X_, celt_norm *Y_, unsigned char *collapse_masks,
int shortBlocks, int spread, int dual_stereo, int intensity, int *tf_res, const celt_ener *bandE, int *pulses, int shortBlocks, int spread,
opus_int32 total_bits, opus_int32 balance, ec_ctx *ec, int LM, int codedBands, opus_uint32 *seed) int dual_stereo, int intensity, int *tf_res, opus_int32 total_bits,
opus_int32 balance, ec_ctx *ec, int LM, int codedBands,
opus_uint32 *seed, int complexity, int arch, int disable_inv)
{ {
int i; int i;
opus_int32 remaining_bits; opus_int32 remaining_bits;
const opus_int16 * OPUS_RESTRICT eBands = m->eBands; const opus_int16 * OPUS_RESTRICT eBands = m->eBands;
celt_norm * OPUS_RESTRICT norm, * OPUS_RESTRICT norm2; celt_norm * OPUS_RESTRICT norm, * OPUS_RESTRICT norm2;
VARDECL(celt_norm, _norm); VARDECL(celt_norm, _norm);
VARDECL(celt_norm, _lowband_scratch);
VARDECL(celt_norm, X_save);
VARDECL(celt_norm, Y_save);
VARDECL(celt_norm, X_save2);
VARDECL(celt_norm, Y_save2);
VARDECL(celt_norm, norm_save2);
int resynth_alloc;
celt_norm *lowband_scratch; celt_norm *lowband_scratch;
int B; int B;
int M; int M;
@ -1380,10 +1420,11 @@ void quant_all_bands(int encode, const CELTMode *m, int start, int end,
int update_lowband = 1; int update_lowband = 1;
int C = Y_ != NULL ? 2 : 1; int C = Y_ != NULL ? 2 : 1;
int norm_offset; int norm_offset;
int theta_rdo = encode && Y_!=NULL && !dual_stereo && complexity>=8;
#ifdef RESYNTH #ifdef RESYNTH
int resynth = 1; int resynth = 1;
#else #else
int resynth = !encode; int resynth = !encode || theta_rdo;
#endif #endif
struct band_ctx ctx; struct band_ctx ctx;
SAVE_STACK; SAVE_STACK;
@ -1396,9 +1437,24 @@ void quant_all_bands(int encode, const CELTMode *m, int start, int end,
ALLOC(_norm, C*(M*eBands[m->nbEBands-1]-norm_offset), celt_norm); ALLOC(_norm, C*(M*eBands[m->nbEBands-1]-norm_offset), celt_norm);
norm = _norm; norm = _norm;
norm2 = norm + M*eBands[m->nbEBands-1]-norm_offset; norm2 = norm + M*eBands[m->nbEBands-1]-norm_offset;
/* We can use the last band as scratch space because we don't need that
scratch space for the last band. */ /* For decoding, we can use the last band as scratch space because we don't need that
scratch space for the last band and we don't care about the data there until we're
decoding the last band. */
if (encode && resynth)
resynth_alloc = M*(eBands[m->nbEBands]-eBands[m->nbEBands-1]);
else
resynth_alloc = ALLOC_NONE;
ALLOC(_lowband_scratch, resynth_alloc, celt_norm);
if (encode && resynth)
lowband_scratch = _lowband_scratch;
else
lowband_scratch = X_+M*eBands[m->nbEBands-1]; lowband_scratch = X_+M*eBands[m->nbEBands-1];
ALLOC(X_save, resynth_alloc, celt_norm);
ALLOC(Y_save, resynth_alloc, celt_norm);
ALLOC(X_save2, resynth_alloc, celt_norm);
ALLOC(Y_save2, resynth_alloc, celt_norm);
ALLOC(norm_save2, resynth_alloc, celt_norm);
lowband_offset = 0; lowband_offset = 0;
ctx.bandE = bandE; ctx.bandE = bandE;
@ -1408,6 +1464,12 @@ void quant_all_bands(int encode, const CELTMode *m, int start, int end,
ctx.m = m; ctx.m = m;
ctx.seed = *seed; ctx.seed = *seed;
ctx.spread = spread; ctx.spread = spread;
ctx.arch = arch;
ctx.disable_inv = disable_inv;
ctx.resynth = resynth;
ctx.theta_round = 0;
/* Avoid injecting noise in the first band on transients. */
ctx.avoid_split_noise = B > 1;
for (i=start;i<end;i++) for (i=start;i<end;i++)
{ {
opus_int32 tell; opus_int32 tell;
@ -1430,6 +1492,7 @@ void quant_all_bands(int encode, const CELTMode *m, int start, int end,
else else
Y = NULL; Y = NULL;
N = M*eBands[i+1]-M*eBands[i]; N = M*eBands[i+1]-M*eBands[i];
celt_assert(N > 0);
tell = ec_tell_frac(ec); tell = ec_tell_frac(ec);
/* Compute how many bits we want to allocate to this band */ /* Compute how many bits we want to allocate to this band */
@ -1445,8 +1508,15 @@ void quant_all_bands(int encode, const CELTMode *m, int start, int end,
b = 0; b = 0;
} }
#ifndef DISABLE_UPDATE_DRAFT
if (resynth && (M*eBands[i]-N >= M*eBands[start] || i==start+1) && (update_lowband || lowband_offset==0))
lowband_offset = i;
if (i == start+1)
special_hybrid_folding(m, norm, norm2, start, M, dual_stereo);
#else
if (resynth && M*eBands[i]-N >= M*eBands[start] && (update_lowband || lowband_offset==0)) if (resynth && M*eBands[i]-N >= M*eBands[start] && (update_lowband || lowband_offset==0))
lowband_offset = i; lowband_offset = i;
#endif
tf_change = tf_res[i]; tf_change = tf_res[i];
ctx.tf_change = tf_change; ctx.tf_change = tf_change;
@ -1457,7 +1527,7 @@ void quant_all_bands(int encode, const CELTMode *m, int start, int end,
Y = norm; Y = norm;
lowband_scratch = NULL; lowband_scratch = NULL;
} }
if (i==end-1) if (last && !theta_rdo)
lowband_scratch = NULL; lowband_scratch = NULL;
/* Get a conservative estimate of the collapse_mask's for the bands we're /* Get a conservative estimate of the collapse_mask's for the bands we're
@ -1472,7 +1542,11 @@ void quant_all_bands(int encode, const CELTMode *m, int start, int end,
fold_start = lowband_offset; fold_start = lowband_offset;
while(M*eBands[--fold_start] > effective_lowband+norm_offset); while(M*eBands[--fold_start] > effective_lowband+norm_offset);
fold_end = lowband_offset-1; fold_end = lowband_offset-1;
#ifndef DISABLE_UPDATE_DRAFT
while(++fold_end < i && M*eBands[fold_end] < effective_lowband+norm_offset+N);
#else
while(M*eBands[++fold_end] < effective_lowband+norm_offset+N); while(M*eBands[++fold_end] < effective_lowband+norm_offset+N);
#endif
x_cm = y_cm = 0; x_cm = y_cm = 0;
fold_i = fold_start; do { fold_i = fold_start; do {
x_cm |= collapse_masks[fold_i*C+0]; x_cm |= collapse_masks[fold_i*C+0];
@ -1505,9 +1579,75 @@ void quant_all_bands(int encode, const CELTMode *m, int start, int end,
} else { } else {
if (Y!=NULL) if (Y!=NULL)
{ {
if (theta_rdo && i < intensity)
{
ec_ctx ec_save, ec_save2;
struct band_ctx ctx_save, ctx_save2;
opus_val32 dist0, dist1;
unsigned cm, cm2;
int nstart_bytes, nend_bytes, save_bytes;
unsigned char *bytes_buf;
unsigned char bytes_save[1275];
opus_val16 w[2];
compute_channel_weights(bandE[i], bandE[i+m->nbEBands], w);
/* Make a copy. */
cm = x_cm|y_cm;
ec_save = *ec;
ctx_save = ctx;
OPUS_COPY(X_save, X, N);
OPUS_COPY(Y_save, Y, N);
/* Encode and round down. */
ctx.theta_round = -1;
x_cm = quant_band_stereo(&ctx, X, Y, N, b, B,
effective_lowband != -1 ? norm+effective_lowband : NULL, LM,
last?NULL:norm+M*eBands[i]-norm_offset, lowband_scratch, cm);
dist0 = MULT16_32_Q15(w[0], celt_inner_prod(X_save, X, N, arch)) + MULT16_32_Q15(w[1], celt_inner_prod(Y_save, Y, N, arch));
/* Save first result. */
cm2 = x_cm;
ec_save2 = *ec;
ctx_save2 = ctx;
OPUS_COPY(X_save2, X, N);
OPUS_COPY(Y_save2, Y, N);
if (!last)
OPUS_COPY(norm_save2, norm+M*eBands[i]-norm_offset, N);
nstart_bytes = ec_save.offs;
nend_bytes = ec_save.storage;
bytes_buf = ec_save.buf+nstart_bytes;
save_bytes = nend_bytes-nstart_bytes;
OPUS_COPY(bytes_save, bytes_buf, save_bytes);
/* Restore */
*ec = ec_save;
ctx = ctx_save;
OPUS_COPY(X, X_save, N);
OPUS_COPY(Y, Y_save, N);
#ifndef DISABLE_UPDATE_DRAFT
if (i == start+1)
special_hybrid_folding(m, norm, norm2, start, M, dual_stereo);
#endif
/* Encode and round up. */
ctx.theta_round = 1;
x_cm = quant_band_stereo(&ctx, X, Y, N, b, B,
effective_lowband != -1 ? norm+effective_lowband : NULL, LM,
last?NULL:norm+M*eBands[i]-norm_offset, lowband_scratch, cm);
dist1 = MULT16_32_Q15(w[0], celt_inner_prod(X_save, X, N, arch)) + MULT16_32_Q15(w[1], celt_inner_prod(Y_save, Y, N, arch));
if (dist0 >= dist1) {
x_cm = cm2;
*ec = ec_save2;
ctx = ctx_save2;
OPUS_COPY(X, X_save2, N);
OPUS_COPY(Y, Y_save2, N);
if (!last)
OPUS_COPY(norm+M*eBands[i]-norm_offset, norm_save2, N);
OPUS_COPY(bytes_buf, bytes_save, save_bytes);
}
} else {
ctx.theta_round = 0;
x_cm = quant_band_stereo(&ctx, X, Y, N, b, B, x_cm = quant_band_stereo(&ctx, X, Y, N, b, B,
effective_lowband != -1 ? norm+effective_lowband : NULL, LM, effective_lowband != -1 ? norm+effective_lowband : NULL, LM,
last?NULL:norm+M*eBands[i]-norm_offset, lowband_scratch, x_cm|y_cm); last?NULL:norm+M*eBands[i]-norm_offset, lowband_scratch, x_cm|y_cm);
}
} else { } else {
x_cm = quant_band(&ctx, X, N, b, B, x_cm = quant_band(&ctx, X, N, b, B,
effective_lowband != -1 ? norm+effective_lowband : NULL, LM, effective_lowband != -1 ? norm+effective_lowband : NULL, LM,
@ -1521,6 +1661,9 @@ void quant_all_bands(int encode, const CELTMode *m, int start, int end,
/* Update the folding position only as long as we have 1 bit/sample depth. */ /* Update the folding position only as long as we have 1 bit/sample depth. */
update_lowband = b>(N<<BITRES); update_lowband = b>(N<<BITRES);
/* We only need to avoid noise on a split for the first band. After that, we
have folding. */
ctx.avoid_split_noise = 0;
} }
*seed = ctx.seed; *seed = ctx.seed;

View file

@ -36,12 +36,15 @@
#include "entdec.h" #include "entdec.h"
#include "rate.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 /** Compute the amplitude (sqrt energy) in each of the bands
* @param m Mode data * @param m Mode data
* @param X Spectrum * @param X Spectrum
* @param bandE Square root of the energy for each band (returned) * @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); 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);*/ /*void compute_noise_energies(const CELTMode *m, const celt_sig *X, const opus_val16 *tonality, celt_ener *bandE);*/
@ -69,7 +72,7 @@ void denormalise_bands(const CELTMode *m, const celt_norm * OPUS_RESTRICT X,
int spreading_decision(const CELTMode *m, const celt_norm *X, int *average, 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 last_decision, int *hf_average, int *tapset_decision, int update_hf,
int end, int C, int M); int end, int C, int M, const int *spread_weight);
#ifdef MEASURE_NORM_MSE #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); void measure_norm_mse(const CELTMode *m, float *X, float *X0, float *bandE, float *bandE0, int M, int N, int C);
@ -98,15 +101,20 @@ void haar1(celt_norm *X, int N0, int stride);
* @param LM log2() of the number of 2.5 subframes in the frame * @param LM log2() of the number of 2.5 subframes in the frame
* @param codedBands Last band to receive bits + 1 * @param codedBands Last band to receive bits + 1
* @param seed Random generator seed * @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, 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, celt_norm * X, celt_norm * Y, unsigned char *collapse_masks,
int shortBlocks, int spread, int dual_stereo, int intensity, int *tf_res, const celt_ener *bandE, int *pulses, int shortBlocks, int spread,
opus_int32 total_bits, opus_int32 balance, ec_ctx *ec, int M, int codedBands, opus_uint32 *seed); 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);
void anti_collapse(const CELTMode *m, celt_norm *X_, unsigned char *collapse_masks, int LM, int C, int size, void anti_collapse(const CELTMode *m, celt_norm *X_,
int start, int end, const opus_val16 *logE, const opus_val16 *prev1logE, unsigned char *collapse_masks, int LM, int C, int size, int start,
const opus_val16 *prev2logE, const int *pulses, opus_uint32 seed); int end, const opus_val16 *logE, const opus_val16 *prev1logE,
const opus_val16 *prev2logE, const int *pulses, opus_uint32 seed,
int arch);
opus_uint32 celt_lcg_rand(opus_uint32 seed); opus_uint32 celt_lcg_rand(opus_uint32 seed);

View file

@ -89,10 +89,13 @@ int resampling_factor(opus_int32 rate)
return ret; return ret;
} }
#ifndef OVERRIDE_COMB_FILTER_CONST #if !defined(OVERRIDE_COMB_FILTER_CONST) || defined(NON_STATIC_COMB_FILTER_CONST_C)
/* This version should be faster on ARM */ /* This version should be faster on ARM */
#ifdef OPUS_ARM_ASM #ifdef OPUS_ARM_ASM
static void comb_filter_const(opus_val32 *y, opus_val32 *x, int T, int N, #ifndef NON_STATIC_COMB_FILTER_CONST_C
static
#endif
void comb_filter_const_c(opus_val32 *y, opus_val32 *x, int T, int N,
opus_val16 g10, opus_val16 g11, opus_val16 g12) opus_val16 g10, opus_val16 g11, opus_val16 g12)
{ {
opus_val32 x0, x1, x2, x3, x4; opus_val32 x0, x1, x2, x3, x4;
@ -108,26 +111,31 @@ static void comb_filter_const(opus_val32 *y, opus_val32 *x, int T, int N,
t = MAC16_32_Q16(x[i], g10, x2); t = MAC16_32_Q16(x[i], g10, x2);
t = MAC16_32_Q16(t, g11, ADD32(x1,x3)); t = MAC16_32_Q16(t, g11, ADD32(x1,x3));
t = MAC16_32_Q16(t, g12, ADD32(x0,x4)); t = MAC16_32_Q16(t, g12, ADD32(x0,x4));
t = SATURATE(t, SIG_SAT);
y[i] = t; y[i] = t;
x4=SHL32(x[i-T+3],1); x4=SHL32(x[i-T+3],1);
t = MAC16_32_Q16(x[i+1], g10, x1); t = MAC16_32_Q16(x[i+1], g10, x1);
t = MAC16_32_Q16(t, g11, ADD32(x0,x2)); t = MAC16_32_Q16(t, g11, ADD32(x0,x2));
t = MAC16_32_Q16(t, g12, ADD32(x4,x3)); t = MAC16_32_Q16(t, g12, ADD32(x4,x3));
t = SATURATE(t, SIG_SAT);
y[i+1] = t; y[i+1] = t;
x3=SHL32(x[i-T+4],1); x3=SHL32(x[i-T+4],1);
t = MAC16_32_Q16(x[i+2], g10, x0); t = MAC16_32_Q16(x[i+2], g10, x0);
t = MAC16_32_Q16(t, g11, ADD32(x4,x1)); t = MAC16_32_Q16(t, g11, ADD32(x4,x1));
t = MAC16_32_Q16(t, g12, ADD32(x3,x2)); t = MAC16_32_Q16(t, g12, ADD32(x3,x2));
t = SATURATE(t, SIG_SAT);
y[i+2] = t; y[i+2] = t;
x2=SHL32(x[i-T+5],1); x2=SHL32(x[i-T+5],1);
t = MAC16_32_Q16(x[i+3], g10, x4); t = MAC16_32_Q16(x[i+3], g10, x4);
t = MAC16_32_Q16(t, g11, ADD32(x3,x0)); t = MAC16_32_Q16(t, g11, ADD32(x3,x0));
t = MAC16_32_Q16(t, g12, ADD32(x2,x1)); t = MAC16_32_Q16(t, g12, ADD32(x2,x1));
t = SATURATE(t, SIG_SAT);
y[i+3] = t; y[i+3] = t;
x1=SHL32(x[i-T+6],1); x1=SHL32(x[i-T+6],1);
t = MAC16_32_Q16(x[i+4], g10, x3); t = MAC16_32_Q16(x[i+4], g10, x3);
t = MAC16_32_Q16(t, g11, ADD32(x2,x4)); t = MAC16_32_Q16(t, g11, ADD32(x2,x4));
t = MAC16_32_Q16(t, g12, ADD32(x1,x0)); t = MAC16_32_Q16(t, g12, ADD32(x1,x0));
t = SATURATE(t, SIG_SAT);
y[i+4] = t; y[i+4] = t;
} }
#ifdef CUSTOM_MODES #ifdef CUSTOM_MODES
@ -138,6 +146,7 @@ static void comb_filter_const(opus_val32 *y, opus_val32 *x, int T, int N,
t = MAC16_32_Q16(x[i], g10, x2); t = MAC16_32_Q16(x[i], g10, x2);
t = MAC16_32_Q16(t, g11, ADD32(x1,x3)); t = MAC16_32_Q16(t, g11, ADD32(x1,x3));
t = MAC16_32_Q16(t, g12, ADD32(x0,x4)); t = MAC16_32_Q16(t, g12, ADD32(x0,x4));
t = SATURATE(t, SIG_SAT);
y[i] = t; y[i] = t;
x4=x3; x4=x3;
x3=x2; x3=x2;
@ -147,7 +156,10 @@ static void comb_filter_const(opus_val32 *y, opus_val32 *x, int T, int N,
#endif #endif
} }
#else #else
static void comb_filter_const(opus_val32 *y, opus_val32 *x, int T, int N, #ifndef NON_STATIC_COMB_FILTER_CONST_C
static
#endif
void comb_filter_const_c(opus_val32 *y, opus_val32 *x, int T, int N,
opus_val16 g10, opus_val16 g11, opus_val16 g12) opus_val16 g10, opus_val16 g11, opus_val16 g12)
{ {
opus_val32 x0, x1, x2, x3, x4; opus_val32 x0, x1, x2, x3, x4;
@ -163,6 +175,7 @@ static void comb_filter_const(opus_val32 *y, opus_val32 *x, int T, int N,
+ MULT16_32_Q15(g10,x2) + MULT16_32_Q15(g10,x2)
+ MULT16_32_Q15(g11,ADD32(x1,x3)) + MULT16_32_Q15(g11,ADD32(x1,x3))
+ MULT16_32_Q15(g12,ADD32(x0,x4)); + MULT16_32_Q15(g12,ADD32(x0,x4));
y[i] = SATURATE(y[i], SIG_SAT);
x4=x3; x4=x3;
x3=x2; x3=x2;
x2=x1; x2=x1;
@ -176,7 +189,7 @@ static void comb_filter_const(opus_val32 *y, opus_val32 *x, int T, int N,
#ifndef OVERRIDE_comb_filter #ifndef OVERRIDE_comb_filter
void comb_filter(opus_val32 *y, opus_val32 *x, int T0, int T1, int N, 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, opus_val16 g0, opus_val16 g1, int tapset0, int tapset1,
const opus_val16 *window, int overlap) const opus_val16 *window, int overlap, int arch)
{ {
int i; int i;
/* printf ("%d %d %f %f\n", T0, T1, g0, g1); */ /* printf ("%d %d %f %f\n", T0, T1, g0, g1); */
@ -194,6 +207,10 @@ void comb_filter(opus_val32 *y, opus_val32 *x, int T0, int T1, int N,
OPUS_MOVE(y, x, N); OPUS_MOVE(y, x, N);
return; 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 = MULT16_16_P15(g0, gains[tapset0][0]); g00 = MULT16_16_P15(g0, gains[tapset0][0]);
g01 = MULT16_16_P15(g0, gains[tapset0][1]); g01 = MULT16_16_P15(g0, gains[tapset0][1]);
g02 = MULT16_16_P15(g0, gains[tapset0][2]); g02 = MULT16_16_P15(g0, gains[tapset0][2]);
@ -219,6 +236,7 @@ void comb_filter(opus_val32 *y, opus_val32 *x, int T0, int T1, int N,
+ MULT16_32_Q15(MULT16_16_Q15(f,g10),x2) + MULT16_32_Q15(MULT16_16_Q15(f,g10),x2)
+ MULT16_32_Q15(MULT16_16_Q15(f,g11),ADD32(x1,x3)) + MULT16_32_Q15(MULT16_16_Q15(f,g11),ADD32(x1,x3))
+ MULT16_32_Q15(MULT16_16_Q15(f,g12),ADD32(x0,x4)); + MULT16_32_Q15(MULT16_16_Q15(f,g12),ADD32(x0,x4));
y[i] = SATURATE(y[i], SIG_SAT);
x4=x3; x4=x3;
x3=x2; x3=x2;
x2=x1; x2=x1;
@ -234,15 +252,20 @@ void comb_filter(opus_val32 *y, opus_val32 *x, int T0, int T1, int N,
} }
/* Compute the part with the constant filter. */ /* Compute the part with the constant filter. */
comb_filter_const(y+i, x+i, T1, N-i, g10, g11, g12); comb_filter_const(y+i, x+i, T1, N-i, g10, g11, g12, arch);
} }
#endif /* OVERRIDE_comb_filter */ #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] = { const signed char tf_select_table[4][8] = {
{0, -1, 0, -1, 0,-1, 0,-1}, /*isTransient=0 isTransient=1 */
{0, -1, 0, -2, 1, 0, 1,-1}, {0, -1, 0, -1, 0,-1, 0,-1}, /* 2.5 ms */
{0, -2, 0, -3, 2, 0, 1,-1}, {0, -1, 0, -2, 1, 0, 1,-1}, /* 5 ms */
{0, -2, 0, -3, 3, 0, 1,-1}, {0, -2, 0, -3, 2, 0, 1,-1}, /* 10 ms */
{0, -2, 0, -3, 3, 0, 1,-1}, /* 20 ms */
}; };
@ -280,6 +303,9 @@ const char *opus_strerror(int error)
const char *opus_get_version_string(void) const char *opus_get_version_string(void)
{ {
return "libopus " PACKAGE_VERSION 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 #ifdef FIXED_POINT
"-fixed" "-fixed"
#endif #endif

View file

@ -50,6 +50,8 @@ extern "C" {
#define CELTDecoder OpusCustomDecoder #define CELTDecoder OpusCustomDecoder
#define CELTMode OpusCustomMode #define CELTMode OpusCustomMode
#define LEAK_BANDS 19
typedef struct { typedef struct {
int valid; int valid;
float tonality; float tonality;
@ -57,17 +59,27 @@ typedef struct {
float noisiness; float noisiness;
float activity; float activity;
float music_prob; float music_prob;
float music_prob_min;
float music_prob_max;
int bandwidth; int bandwidth;
float activity_probability;
float max_pitch_ratio;
/* Store as Q6 char to save space. */
unsigned char leak_boost[LEAK_BANDS];
} AnalysisInfo; } AnalysisInfo;
typedef struct {
int signalType;
int offset;
} SILKInfo;
#define __celt_check_mode_ptr_ptr(ptr) ((ptr) + ((ptr) - (const CELTMode**)(ptr))) #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_analysis_ptr(ptr) ((ptr) + ((ptr) - (const AnalysisInfo*)(ptr)))
/* Encoder/decoder Requests */ #define __celt_check_silkinfo_ptr(ptr) ((ptr) + ((ptr) - (const SILKInfo*)(ptr)))
/* Expose this option again when variable framesize actually works */ /* Encoder/decoder Requests */
#define OPUS_FRAMESIZE_VARIABLE 5010 /**< Optimize the frame size dynamically */
#define CELT_SET_PREDICTION_REQUEST 10002 #define CELT_SET_PREDICTION_REQUEST 10002
@ -116,6 +128,9 @@ typedef struct {
#define OPUS_SET_ENERGY_MASK_REQUEST 10026 #define OPUS_SET_ENERGY_MASK_REQUEST 10026
#define OPUS_SET_ENERGY_MASK(x) OPUS_SET_ENERGY_MASK_REQUEST, __opus_check_val16_ptr(x) #define OPUS_SET_ENERGY_MASK(x) OPUS_SET_ENERGY_MASK_REQUEST, __opus_check_val16_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)
/* Encoder stuff */ /* Encoder stuff */
int celt_encoder_get_size(int channels); int celt_encoder_get_size(int channels);
@ -194,6 +209,13 @@ static OPUS_INLINE int fromOpus(unsigned char c)
extern const signed char tf_select_table[4][8]; 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); int resampling_factor(opus_int32 rate);
void celt_preemphasis(const opus_val16 * OPUS_RESTRICT pcmp, celt_sig * OPUS_RESTRICT inp, void celt_preemphasis(const opus_val16 * OPUS_RESTRICT pcmp, celt_sig * OPUS_RESTRICT inp,
@ -201,7 +223,17 @@ void celt_preemphasis(const opus_val16 * OPUS_RESTRICT pcmp, celt_sig * OPUS_RES
void comb_filter(opus_val32 *y, opus_val32 *x, int T0, int T1, int N, 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, opus_val16 g0, opus_val16 g1, int tapset0, int tapset1,
const opus_val16 *window, int overlap); const opus_val16 *window, int overlap, int arch);
#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
void init_caps(const CELTMode *m,int *cap,int LM,int C); void init_caps(const CELTMode *m,int *cap,int LM,int C);

View file

@ -51,6 +51,14 @@
#include "celt_lpc.h" #include "celt_lpc.h"
#include "vq.h" #include "vq.h"
/* The maximum pitch lag to allow in the pitch-based PLC. It's possible to save
CPU time in the PLC pitch search by making this smaller than MAX_PERIOD. The
current value corresponds to a pitch of 66.67 Hz. */
#define PLC_PITCH_LAG_MAX (720)
/* The minimum pitch lag to allow in the pitch-based PLC. This corresponds to a
pitch of 480 Hz. */
#define PLC_PITCH_LAG_MIN (100)
#if defined(SMALL_FOOTPRINT) && defined(FIXED_POINT) #if defined(SMALL_FOOTPRINT) && defined(FIXED_POINT)
#define NORM_ALIASING_HACK #define NORM_ALIASING_HACK
#endif #endif
@ -73,6 +81,7 @@ struct OpusCustomDecoder {
int downsample; int downsample;
int start, end; int start, end;
int signalling; int signalling;
int disable_inv;
int arch; int arch;
/* Everything beyond this point gets cleared on a reset */ /* Everything beyond this point gets cleared on a reset */
@ -82,6 +91,7 @@ struct OpusCustomDecoder {
int error; int error;
int last_pitch_index; int last_pitch_index;
int loss_count; int loss_count;
int skip_plc;
int postfilter_period; int postfilter_period;
int postfilter_period_old; int postfilter_period_old;
opus_val16 postfilter_gain; opus_val16 postfilter_gain;
@ -99,6 +109,38 @@ struct OpusCustomDecoder {
/* opus_val16 backgroundLogE[], Size = 2*mode->nbEBands */ /* opus_val16 backgroundLogE[], Size = 2*mode->nbEBands */
}; };
#if defined(ENABLE_HARDENING) || defined(ENABLE_ASSERTIONS)
/* Make basic checks on the CELT state to ensure we don't end
up writing all over memory. */
void validate_celt_decoder(CELTDecoder *st)
{
#ifndef CUSTOM_MODES
celt_assert(st->mode == opus_custom_mode_create(48000, 960, NULL));
celt_assert(st->overlap == 120);
#endif
celt_assert(st->channels == 1 || st->channels == 2);
celt_assert(st->stream_channels == 1 || st->stream_channels == 2);
celt_assert(st->downsample > 0);
celt_assert(st->start == 0 || st->start == 17);
celt_assert(st->start < st->end);
celt_assert(st->end <= 21);
#ifdef OPUS_ARCHMASK
celt_assert(st->arch >= 0);
celt_assert(st->arch <= OPUS_ARCHMASK);
#endif
celt_assert(st->last_pitch_index <= PLC_PITCH_LAG_MAX);
celt_assert(st->last_pitch_index >= PLC_PITCH_LAG_MIN || st->last_pitch_index == 0);
celt_assert(st->postfilter_period < MAX_PERIOD);
celt_assert(st->postfilter_period >= COMBFILTER_MINPERIOD || st->postfilter_period == 0);
celt_assert(st->postfilter_period_old < MAX_PERIOD);
celt_assert(st->postfilter_period_old >= COMBFILTER_MINPERIOD || st->postfilter_period_old == 0);
celt_assert(st->postfilter_tapset <= 2);
celt_assert(st->postfilter_tapset >= 0);
celt_assert(st->postfilter_tapset_old <= 2);
celt_assert(st->postfilter_tapset_old >= 0);
}
#endif
int celt_decoder_get_size(int channels) int celt_decoder_get_size(int channels)
{ {
const CELTMode *mode = opus_custom_mode_create(48000, 960, NULL); const CELTMode *mode = opus_custom_mode_create(48000, 960, NULL);
@ -162,10 +204,13 @@ OPUS_CUSTOM_NOSTATIC int opus_custom_decoder_init(CELTDecoder *st, const CELTMod
st->start = 0; st->start = 0;
st->end = st->mode->effEBands; st->end = st->mode->effEBands;
st->signalling = 1; st->signalling = 1;
#ifndef DISABLE_UPDATE_DRAFT
st->disable_inv = channels == 1;
#else
st->disable_inv = 0;
#endif
st->arch = opus_select_arch(); st->arch = opus_select_arch();
st->loss_count = 0;
opus_custom_decoder_ctl(st, OPUS_RESET_STATE); opus_custom_decoder_ctl(st, OPUS_RESET_STATE);
return OPUS_OK; return OPUS_OK;
@ -178,6 +223,36 @@ void opus_custom_decoder_destroy(CELTDecoder *st)
} }
#endif /* CUSTOM_MODES */ #endif /* CUSTOM_MODES */
#ifndef CUSTOM_MODES
/* Special case for stereo with no downsampling and no accumulation. This is
quite common and we can make it faster by processing both channels in the
same loop, reducing overhead due to the dependency loop in the IIR filter. */
static void deemphasis_stereo_simple(celt_sig *in[], opus_val16 *pcm, int N, const opus_val16 coef0,
celt_sig *mem)
{
celt_sig * OPUS_RESTRICT x0;
celt_sig * OPUS_RESTRICT x1;
celt_sig m0, m1;
int j;
x0=in[0];
x1=in[1];
m0 = mem[0];
m1 = mem[1];
for (j=0;j<N;j++)
{
celt_sig tmp0, tmp1;
/* Add VERY_SMALL to x[] first to reduce dependency chain. */
tmp0 = x0[j] + VERY_SMALL + m0;
tmp1 = x1[j] + VERY_SMALL + m1;
m0 = MULT16_32_Q15(coef0, tmp0);
m1 = MULT16_32_Q15(coef0, tmp1);
pcm[2*j ] = SCALEOUT(SIG2WORD16(tmp0));
pcm[2*j+1] = SCALEOUT(SIG2WORD16(tmp1));
}
mem[0] = m0;
mem[1] = m1;
}
#endif
#ifndef RESYNTH #ifndef RESYNTH
static static
@ -191,6 +266,14 @@ void deemphasis(celt_sig *in[], opus_val16 *pcm, int N, int C, int downsample, c
opus_val16 coef0; opus_val16 coef0;
VARDECL(celt_sig, scratch); VARDECL(celt_sig, scratch);
SAVE_STACK; SAVE_STACK;
#ifndef CUSTOM_MODES
/* Short version for common case. */
if (downsample == 1 && C == 2 && !accum)
{
deemphasis_stereo_simple(in, pcm, N, coef[0], mem);
return;
}
#endif
#ifndef FIXED_POINT #ifndef FIXED_POINT
(void)accum; (void)accum;
celt_assert(accum==0); celt_assert(accum==0);
@ -226,7 +309,7 @@ void deemphasis(celt_sig *in[], opus_val16 *pcm, int N, int C, int downsample, c
/* Shortcut for the standard (non-custom modes) case */ /* Shortcut for the standard (non-custom modes) case */
for (j=0;j<N;j++) for (j=0;j<N;j++)
{ {
celt_sig tmp = x[j] + m + VERY_SMALL; celt_sig tmp = x[j] + VERY_SMALL + m;
m = MULT16_32_Q15(coef0, tmp); m = MULT16_32_Q15(coef0, tmp);
scratch[j] = tmp; scratch[j] = tmp;
} }
@ -247,7 +330,7 @@ void deemphasis(celt_sig *in[], opus_val16 *pcm, int N, int C, int downsample, c
{ {
for (j=0;j<N;j++) for (j=0;j<N;j++)
{ {
celt_sig tmp = x[j] + m + VERY_SMALL; celt_sig tmp = x[j] + VERY_SMALL + m;
m = MULT16_32_Q15(coef0, tmp); m = MULT16_32_Q15(coef0, tmp);
y[j*C] = SCALEOUT(SIG2WORD16(tmp)); y[j*C] = SCALEOUT(SIG2WORD16(tmp));
} }
@ -278,8 +361,9 @@ void deemphasis(celt_sig *in[], opus_val16 *pcm, int N, int C, int downsample, c
static static
#endif #endif
void celt_synthesis(const CELTMode *mode, celt_norm *X, celt_sig * out_syn[], void celt_synthesis(const CELTMode *mode, celt_norm *X, celt_sig * out_syn[],
opus_val16 *oldBandE, int start, int effEnd, int C, int CC, int isTransient, opus_val16 *oldBandE, int start, int effEnd, int C, int CC,
int LM, int downsample, int silence) int isTransient, int LM, int downsample,
int silence, int arch)
{ {
int c, i; int c, i;
int M; int M;
@ -319,9 +403,9 @@ void celt_synthesis(const CELTMode *mode, celt_norm *X, celt_sig * out_syn[],
freq2 = out_syn[1]+overlap/2; freq2 = out_syn[1]+overlap/2;
OPUS_COPY(freq2, freq, N); OPUS_COPY(freq2, freq, N);
for (b=0;b<B;b++) for (b=0;b<B;b++)
clt_mdct_backward(&mode->mdct, &freq2[b], out_syn[0]+NB*b, mode->window, overlap, shift, B); clt_mdct_backward(&mode->mdct, &freq2[b], out_syn[0]+NB*b, mode->window, overlap, shift, B, arch);
for (b=0;b<B;b++) for (b=0;b<B;b++)
clt_mdct_backward(&mode->mdct, &freq[b], out_syn[1]+NB*b, mode->window, overlap, shift, B); clt_mdct_backward(&mode->mdct, &freq[b], out_syn[1]+NB*b, mode->window, overlap, shift, B, arch);
} else if (CC==1&&C==2) } else if (CC==1&&C==2)
{ {
/* Downmixing a stereo stream to mono */ /* Downmixing a stereo stream to mono */
@ -333,18 +417,24 @@ void celt_synthesis(const CELTMode *mode, celt_norm *X, celt_sig * out_syn[],
denormalise_bands(mode, X+N, freq2, oldBandE+nbEBands, start, effEnd, M, denormalise_bands(mode, X+N, freq2, oldBandE+nbEBands, start, effEnd, M,
downsample, silence); downsample, silence);
for (i=0;i<N;i++) for (i=0;i<N;i++)
freq[i] = HALF32(ADD32(freq[i],freq2[i])); freq[i] = ADD32(HALF32(freq[i]), HALF32(freq2[i]));
for (b=0;b<B;b++) for (b=0;b<B;b++)
clt_mdct_backward(&mode->mdct, &freq[b], out_syn[0]+NB*b, mode->window, overlap, shift, B); clt_mdct_backward(&mode->mdct, &freq[b], out_syn[0]+NB*b, mode->window, overlap, shift, B, arch);
} else { } else {
/* Normal case (mono or stereo) */ /* Normal case (mono or stereo) */
c=0; do { c=0; do {
denormalise_bands(mode, X+c*N, freq, oldBandE+c*nbEBands, start, effEnd, M, denormalise_bands(mode, X+c*N, freq, oldBandE+c*nbEBands, start, effEnd, M,
downsample, silence); downsample, silence);
for (b=0;b<B;b++) for (b=0;b<B;b++)
clt_mdct_backward(&mode->mdct, &freq[b], out_syn[c]+NB*b, mode->window, overlap, shift, B); clt_mdct_backward(&mode->mdct, &freq[b], out_syn[c]+NB*b, mode->window, overlap, shift, B, arch);
} while (++c<CC); } while (++c<CC);
} }
/* Saturate IMDCT output so that we can't overflow in the pitch postfilter
or in the */
c=0; do {
for (i=0;i<N;i++)
out_syn[c][i] = SATURATE(out_syn[c][i], SIG_SAT);
} while (++c<CC);
RESTORE_STACK; RESTORE_STACK;
} }
@ -387,14 +477,6 @@ static void tf_decode(int start, int end, int isTransient, int *tf_res, int LM,
} }
} }
/* The maximum pitch lag to allow in the pitch-based PLC. It's possible to save
CPU time in the PLC pitch search by making this smaller than MAX_PERIOD. The
current value corresponds to a pitch of 66.67 Hz. */
#define PLC_PITCH_LAG_MAX (720)
/* The minimum pitch lag to allow in the pitch-based PLC. This corresponds to a
pitch of 480 Hz. */
#define PLC_PITCH_LAG_MIN (100)
static int celt_plc_pitch_search(celt_sig *decode_mem[2], int C, int arch) static int celt_plc_pitch_search(celt_sig *decode_mem[2], int C, int arch)
{ {
int pitch_index; int pitch_index;
@ -446,7 +528,7 @@ static void celt_decode_lost(CELTDecoder * OPUS_RESTRICT st, int N, int LM)
loss_count = st->loss_count; loss_count = st->loss_count;
start = st->start; start = st->start;
noise_based = loss_count >= 5 || start != 0; noise_based = loss_count >= 5 || start != 0 || st->skip_plc;
if (noise_based) if (noise_based)
{ {
/* Noise-based PLC/CNG */ /* Noise-based PLC/CNG */
@ -456,10 +538,9 @@ static void celt_decode_lost(CELTDecoder * OPUS_RESTRICT st, int N, int LM)
VARDECL(celt_norm, X); VARDECL(celt_norm, X);
#endif #endif
opus_uint32 seed; opus_uint32 seed;
opus_val16 *plcLogE;
int end; int end;
int effEnd; int effEnd;
opus_val16 decay;
end = st->end; end = st->end;
effEnd = IMAX(start, IMIN(end, mode->effEBands)); effEnd = IMAX(start, IMIN(end, mode->effEBands));
@ -471,19 +552,13 @@ static void celt_decode_lost(CELTDecoder * OPUS_RESTRICT st, int N, int LM)
ALLOC(X, C*N, celt_norm); /**< Interleaved normalised MDCTs */ ALLOC(X, C*N, celt_norm); /**< Interleaved normalised MDCTs */
#endif #endif
if (loss_count >= 5)
plcLogE = backgroundLogE;
else {
/* Energy decay */ /* Energy decay */
opus_val16 decay = loss_count==0 ? decay = loss_count==0 ? QCONST16(1.5f, DB_SHIFT) : QCONST16(.5f, DB_SHIFT);
QCONST16(1.5f, DB_SHIFT) : QCONST16(.5f, DB_SHIFT);
c=0; do c=0; do
{ {
for (i=start;i<end;i++) for (i=start;i<end;i++)
oldBandE[c*nbEBands+i] -= decay; oldBandE[c*nbEBands+i] = MAX16(backgroundLogE[c*nbEBands+i], oldBandE[c*nbEBands+i] - decay);
} while (++c<C); } while (++c<C);
plcLogE = oldBandE;
}
seed = st->rng; seed = st->rng;
for (c=0;c<C;c++) for (c=0;c<C;c++)
{ {
@ -499,7 +574,7 @@ static void celt_decode_lost(CELTDecoder * OPUS_RESTRICT st, int N, int LM)
seed = celt_lcg_rand(seed); seed = celt_lcg_rand(seed);
X[boffs+j] = (celt_norm)((opus_int32)seed>>20); X[boffs+j] = (celt_norm)((opus_int32)seed>>20);
} }
renormalise_vector(X+boffs, blen, Q15ONE); renormalise_vector(X+boffs, blen, Q15ONE, st->arch);
} }
} }
st->rng = seed; st->rng = seed;
@ -509,14 +584,17 @@ static void celt_decode_lost(CELTDecoder * OPUS_RESTRICT st, int N, int LM)
DECODE_BUFFER_SIZE-N+(overlap>>1)); DECODE_BUFFER_SIZE-N+(overlap>>1));
} while (++c<C); } while (++c<C);
celt_synthesis(mode, X, out_syn, plcLogE, start, effEnd, C, C, 0, LM, st->downsample, 0); celt_synthesis(mode, X, out_syn, oldBandE, start, effEnd, C, C, 0, LM, st->downsample, 0, st->arch);
} else { } else {
int exc_length;
/* Pitch-based PLC */ /* Pitch-based PLC */
const opus_val16 *window; const opus_val16 *window;
opus_val16 *exc;
opus_val16 fade = Q15ONE; opus_val16 fade = Q15ONE;
int pitch_index; int pitch_index;
VARDECL(opus_val32, etmp); VARDECL(opus_val32, etmp);
VARDECL(opus_val16, exc); VARDECL(opus_val16, _exc);
VARDECL(opus_val16, fir_tmp);
if (loss_count == 0) if (loss_count == 0)
{ {
@ -526,8 +604,14 @@ static void celt_decode_lost(CELTDecoder * OPUS_RESTRICT st, int N, int LM)
fade = QCONST16(.8f,15); fade = QCONST16(.8f,15);
} }
/* We want the excitation for 2 pitch periods in order to look for a
decaying signal, but we can't get more than MAX_PERIOD. */
exc_length = IMIN(2*pitch_index, MAX_PERIOD);
ALLOC(etmp, overlap, opus_val32); ALLOC(etmp, overlap, opus_val32);
ALLOC(exc, MAX_PERIOD, opus_val16); ALLOC(_exc, MAX_PERIOD+LPC_ORDER, opus_val16);
ALLOC(fir_tmp, exc_length, opus_val16);
exc = _exc+LPC_ORDER;
window = mode->window; window = mode->window;
c=0; do { c=0; do {
opus_val16 decay; opus_val16 decay;
@ -536,13 +620,11 @@ static void celt_decode_lost(CELTDecoder * OPUS_RESTRICT st, int N, int LM)
celt_sig *buf; celt_sig *buf;
int extrapolation_offset; int extrapolation_offset;
int extrapolation_len; int extrapolation_len;
int exc_length;
int j; int j;
buf = decode_mem[c]; buf = decode_mem[c];
for (i=0;i<MAX_PERIOD;i++) { for (i=0;i<MAX_PERIOD+LPC_ORDER;i++)
exc[i] = ROUND16(buf[DECODE_BUFFER_SIZE-MAX_PERIOD+i], SIG_SHIFT); exc[i-LPC_ORDER] = ROUND16(buf[DECODE_BUFFER_SIZE-MAX_PERIOD-LPC_ORDER+i], SIG_SHIFT);
}
if (loss_count == 0) if (loss_count == 0)
{ {
@ -568,22 +650,32 @@ static void celt_decode_lost(CELTDecoder * OPUS_RESTRICT st, int N, int LM)
#endif #endif
} }
_celt_lpc(lpc+c*LPC_ORDER, ac, LPC_ORDER); _celt_lpc(lpc+c*LPC_ORDER, ac, LPC_ORDER);
#ifdef FIXED_POINT
/* For fixed-point, apply bandwidth expansion until we can guarantee that
no overflow can happen in the IIR filter. This means:
32768*sum(abs(filter)) < 2^31 */
while (1) {
opus_val16 tmp=Q15ONE;
opus_val32 sum=QCONST16(1., SIG_SHIFT);
for (i=0;i<LPC_ORDER;i++)
sum += ABS16(lpc[c*LPC_ORDER+i]);
if (sum < 65535) break;
for (i=0;i<LPC_ORDER;i++)
{
tmp = MULT16_16_Q15(QCONST16(.99f,15), tmp);
lpc[c*LPC_ORDER+i] = MULT16_16_Q15(lpc[c*LPC_ORDER+i], tmp);
}
}
#endif
} }
/* We want the excitation for 2 pitch periods in order to look for a
decaying signal, but we can't get more than MAX_PERIOD. */
exc_length = IMIN(2*pitch_index, MAX_PERIOD);
/* Initialize the LPC history with the samples just before the start /* Initialize the LPC history with the samples just before the start
of the region for which we're computing the excitation. */ of the region for which we're computing the excitation. */
{ {
opus_val16 lpc_mem[LPC_ORDER]; /* Compute the excitation for exc_length samples before the loss. We need the copy
for (i=0;i<LPC_ORDER;i++) because celt_fir() cannot filter in-place. */
{
lpc_mem[i] =
ROUND16(buf[DECODE_BUFFER_SIZE-exc_length-1-i], SIG_SHIFT);
}
/* Compute the excitation for exc_length samples before the loss. */
celt_fir(exc+MAX_PERIOD-exc_length, lpc+c*LPC_ORDER, celt_fir(exc+MAX_PERIOD-exc_length, lpc+c*LPC_ORDER,
exc+MAX_PERIOD-exc_length, exc_length, LPC_ORDER, lpc_mem); fir_tmp, exc_length, LPC_ORDER, st->arch);
OPUS_COPY(exc+MAX_PERIOD-exc_length, fir_tmp, exc_length);
} }
/* Check if the waveform is decaying, and if so how fast. /* Check if the waveform is decaying, and if so how fast.
@ -637,9 +729,8 @@ static void celt_decode_lost(CELTDecoder * OPUS_RESTRICT st, int N, int LM)
tmp = ROUND16( tmp = ROUND16(
buf[DECODE_BUFFER_SIZE-MAX_PERIOD-N+extrapolation_offset+j], buf[DECODE_BUFFER_SIZE-MAX_PERIOD-N+extrapolation_offset+j],
SIG_SHIFT); SIG_SHIFT);
S1 += SHR32(MULT16_16(tmp, tmp), 8); S1 += SHR32(MULT16_16(tmp, tmp), 10);
} }
{ {
opus_val16 lpc_mem[LPC_ORDER]; opus_val16 lpc_mem[LPC_ORDER];
/* Copy the last decoded samples (prior to the overlap region) to /* Copy the last decoded samples (prior to the overlap region) to
@ -650,7 +741,11 @@ static void celt_decode_lost(CELTDecoder * OPUS_RESTRICT st, int N, int LM)
the signal domain. */ the signal domain. */
celt_iir(buf+DECODE_BUFFER_SIZE-N, lpc+c*LPC_ORDER, celt_iir(buf+DECODE_BUFFER_SIZE-N, lpc+c*LPC_ORDER,
buf+DECODE_BUFFER_SIZE-N, extrapolation_len, LPC_ORDER, buf+DECODE_BUFFER_SIZE-N, extrapolation_len, LPC_ORDER,
lpc_mem); lpc_mem, st->arch);
#ifdef FIXED_POINT
for (i=0; i < extrapolation_len; i++)
buf[DECODE_BUFFER_SIZE-N+i] = SATURATE(buf[DECODE_BUFFER_SIZE-N+i], SIG_SAT);
#endif
} }
/* Check if the synthesis energy is higher than expected, which can /* Check if the synthesis energy is higher than expected, which can
@ -661,7 +756,7 @@ static void celt_decode_lost(CELTDecoder * OPUS_RESTRICT st, int N, int LM)
for (i=0;i<extrapolation_len;i++) for (i=0;i<extrapolation_len;i++)
{ {
opus_val16 tmp = ROUND16(buf[DECODE_BUFFER_SIZE-N+i], SIG_SHIFT); opus_val16 tmp = ROUND16(buf[DECODE_BUFFER_SIZE-N+i], SIG_SHIFT);
S2 += SHR32(MULT16_16(tmp, tmp), 8); S2 += SHR32(MULT16_16(tmp, tmp), 10);
} }
/* This checks for an "explosion" in the synthesis. */ /* This checks for an "explosion" in the synthesis. */
#ifdef FIXED_POINT #ifdef FIXED_POINT
@ -698,7 +793,7 @@ static void celt_decode_lost(CELTDecoder * OPUS_RESTRICT st, int N, int LM)
comb_filter(etmp, buf+DECODE_BUFFER_SIZE, comb_filter(etmp, buf+DECODE_BUFFER_SIZE,
st->postfilter_period, st->postfilter_period, overlap, st->postfilter_period, st->postfilter_period, overlap,
-st->postfilter_gain, -st->postfilter_gain, -st->postfilter_gain, -st->postfilter_gain,
st->postfilter_tapset, st->postfilter_tapset, NULL, 0); st->postfilter_tapset, st->postfilter_tapset, NULL, 0, st->arch);
/* Simulate TDAC on the concealed audio so that it blends with the /* Simulate TDAC on the concealed audio so that it blends with the
MDCT of the next frame. */ MDCT of the next frame. */
@ -769,6 +864,7 @@ int celt_decode_with_ec(CELTDecoder * OPUS_RESTRICT st, const unsigned char *dat
const opus_int16 *eBands; const opus_int16 *eBands;
ALLOC_STACK; ALLOC_STACK;
VALIDATE_CELT_DECODER(st);
mode = st->mode; mode = st->mode;
nbEBands = mode->nbEBands; nbEBands = mode->nbEBands;
overlap = mode->overlap; overlap = mode->overlap;
@ -838,6 +934,10 @@ int celt_decode_with_ec(CELTDecoder * OPUS_RESTRICT st, const unsigned char *dat
return frame_size/st->downsample; return frame_size/st->downsample;
} }
/* Check if there are at least two packets received consecutively before
* turning on the pitch-based PLC */
st->skip_plc = st->loss_count != 0;
if (dec == NULL) if (dec == NULL)
{ {
ec_dec_init(&_dec,(unsigned char*)data,len); ec_dec_init(&_dec,(unsigned char*)data,len);
@ -959,7 +1059,7 @@ int celt_decode_with_ec(CELTDecoder * OPUS_RESTRICT st, const unsigned char *dat
ALLOC(pulses, nbEBands, int); ALLOC(pulses, nbEBands, int);
ALLOC(fine_priority, nbEBands, int); ALLOC(fine_priority, nbEBands, int);
codedBands = compute_allocation(mode, start, end, offsets, cap, codedBands = clt_compute_allocation(mode, start, end, offsets, cap,
alloc_trim, &intensity, &dual_stereo, bits, &balance, pulses, alloc_trim, &intensity, &dual_stereo, bits, &balance, pulses,
fine_quant, fine_priority, C, LM, dec, 0, 0, 0); fine_quant, fine_priority, C, LM, dec, 0, 0, 0);
@ -982,7 +1082,8 @@ int celt_decode_with_ec(CELTDecoder * OPUS_RESTRICT st, const unsigned char *dat
quant_all_bands(0, mode, start, end, X, C==2 ? X+N : NULL, collapse_masks, quant_all_bands(0, mode, start, end, X, C==2 ? X+N : NULL, collapse_masks,
NULL, pulses, shortBlocks, spread_decision, dual_stereo, intensity, tf_res, NULL, pulses, shortBlocks, spread_decision, dual_stereo, intensity, tf_res,
len*(8<<BITRES)-anti_collapse_rsv, balance, dec, LM, codedBands, &st->rng); len*(8<<BITRES)-anti_collapse_rsv, balance, dec, LM, codedBands, &st->rng, 0,
st->arch, st->disable_inv);
if (anti_collapse_rsv > 0) if (anti_collapse_rsv > 0)
{ {
@ -994,7 +1095,7 @@ int celt_decode_with_ec(CELTDecoder * OPUS_RESTRICT st, const unsigned char *dat
if (anti_collapse_on) if (anti_collapse_on)
anti_collapse(mode, X, collapse_masks, LM, C, N, anti_collapse(mode, X, collapse_masks, LM, C, N,
start, end, oldBandE, oldLogE, oldLogE2, pulses, st->rng); start, end, oldBandE, oldLogE, oldLogE2, pulses, st->rng, st->arch);
if (silence) if (silence)
{ {
@ -1002,18 +1103,19 @@ int celt_decode_with_ec(CELTDecoder * OPUS_RESTRICT st, const unsigned char *dat
oldBandE[i] = -QCONST16(28.f,DB_SHIFT); oldBandE[i] = -QCONST16(28.f,DB_SHIFT);
} }
celt_synthesis(mode, X, out_syn, oldBandE, start, effEnd, C, CC, isTransient, LM, st->downsample, silence); celt_synthesis(mode, X, out_syn, oldBandE, start, effEnd,
C, CC, isTransient, LM, st->downsample, silence, st->arch);
c=0; do { c=0; do {
st->postfilter_period=IMAX(st->postfilter_period, COMBFILTER_MINPERIOD); st->postfilter_period=IMAX(st->postfilter_period, COMBFILTER_MINPERIOD);
st->postfilter_period_old=IMAX(st->postfilter_period_old, COMBFILTER_MINPERIOD); st->postfilter_period_old=IMAX(st->postfilter_period_old, COMBFILTER_MINPERIOD);
comb_filter(out_syn[c], out_syn[c], st->postfilter_period_old, st->postfilter_period, mode->shortMdctSize, comb_filter(out_syn[c], out_syn[c], st->postfilter_period_old, st->postfilter_period, mode->shortMdctSize,
st->postfilter_gain_old, st->postfilter_gain, st->postfilter_tapset_old, st->postfilter_tapset, st->postfilter_gain_old, st->postfilter_gain, st->postfilter_tapset_old, st->postfilter_tapset,
mode->window, overlap); mode->window, overlap, st->arch);
if (LM!=0) if (LM!=0)
comb_filter(out_syn[c]+mode->shortMdctSize, out_syn[c]+mode->shortMdctSize, st->postfilter_period, postfilter_pitch, N-mode->shortMdctSize, comb_filter(out_syn[c]+mode->shortMdctSize, out_syn[c]+mode->shortMdctSize, st->postfilter_period, postfilter_pitch, N-mode->shortMdctSize,
st->postfilter_gain, postfilter_gain, st->postfilter_tapset, postfilter_tapset, st->postfilter_gain, postfilter_gain, st->postfilter_tapset, postfilter_tapset,
mode->window, overlap); mode->window, overlap, st->arch);
} while (++c<CC); } while (++c<CC);
st->postfilter_period_old = st->postfilter_period; st->postfilter_period_old = st->postfilter_period;
@ -1035,10 +1137,18 @@ int celt_decode_with_ec(CELTDecoder * OPUS_RESTRICT st, const unsigned char *dat
/* In case start or end were to change */ /* In case start or end were to change */
if (!isTransient) if (!isTransient)
{ {
opus_val16 max_background_increase;
OPUS_COPY(oldLogE2, oldLogE, 2*nbEBands); OPUS_COPY(oldLogE2, oldLogE, 2*nbEBands);
OPUS_COPY(oldLogE, oldBandE, 2*nbEBands); OPUS_COPY(oldLogE, oldBandE, 2*nbEBands);
/* In normal circumstances, we only allow the noise floor to increase by
up to 2.4 dB/second, but when we're in DTX, we allow up to 6 dB
increase for each update.*/
if (st->loss_count < 10)
max_background_increase = M*QCONST16(0.001f,DB_SHIFT);
else
max_background_increase = QCONST16(1.f,DB_SHIFT);
for (i=0;i<2*nbEBands;i++) for (i=0;i<2*nbEBands;i++)
backgroundLogE[i] = MIN16(backgroundLogE[i] + M*QCONST16(0.001f,DB_SHIFT), oldBandE[i]); backgroundLogE[i] = MIN16(backgroundLogE[i] + max_background_increase, oldBandE[i]);
} else { } else {
for (i=0;i<2*nbEBands;i++) for (i=0;i<2*nbEBands;i++)
oldLogE[i] = MIN16(oldLogE[i], oldBandE[i]); oldLogE[i] = MIN16(oldLogE[i], oldBandE[i]);
@ -1195,6 +1305,7 @@ int opus_custom_decoder_ctl(CELTDecoder * OPUS_RESTRICT st, int request, ...)
((char*)&st->DECODER_RESET_START - (char*)st)); ((char*)&st->DECODER_RESET_START - (char*)st));
for (i=0;i<2*st->mode->nbEBands;i++) for (i=0;i<2*st->mode->nbEBands;i++)
oldLogE[i]=oldLogE2[i]=-QCONST16(28.f,DB_SHIFT); oldLogE[i]=oldLogE2[i]=-QCONST16(28.f,DB_SHIFT);
st->skip_plc = 1;
} }
break; break;
case OPUS_GET_PITCH_REQUEST: case OPUS_GET_PITCH_REQUEST:
@ -1227,6 +1338,26 @@ int opus_custom_decoder_ctl(CELTDecoder * OPUS_RESTRICT st, int request, ...)
*value=st->rng; *value=st->rng;
} }
break; break;
case OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST:
{
opus_int32 value = va_arg(ap, opus_int32);
if(value<0 || value>1)
{
goto bad_arg;
}
st->disable_inv = value;
}
break;
case OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST:
{
opus_int32 *value = va_arg(ap, opus_int32*);
if (!value)
{
goto bad_arg;
}
*value = st->disable_inv;
}
break;
default: default:
goto bad_request; goto bad_request;
} }

File diff suppressed because it is too large Load diff

View file

@ -49,8 +49,7 @@ int p
float *lpc = _lpc; float *lpc = _lpc;
#endif #endif
for (i = 0; i < p; i++) OPUS_CLEAR(lpc, p);
lpc[i] = 0;
if (ac[0] != 0) if (ac[0] != 0)
{ {
for (i = 0; i < p; i++) { for (i = 0; i < p; i++) {
@ -88,56 +87,42 @@ int p
#endif #endif
} }
void celt_fir(const opus_val16 *_x,
void celt_fir_c(
const opus_val16 *x,
const opus_val16 *num, const opus_val16 *num,
opus_val16 *_y, opus_val16 *y,
int N, int N,
int ord, int ord,
opus_val16 *mem) int arch)
{ {
int i,j; int i,j;
VARDECL(opus_val16, rnum); VARDECL(opus_val16, rnum);
VARDECL(opus_val16, x);
SAVE_STACK; SAVE_STACK;
celt_assert(x != y);
ALLOC(rnum, ord, opus_val16); ALLOC(rnum, ord, opus_val16);
ALLOC(x, N+ord, opus_val16);
for(i=0;i<ord;i++) for(i=0;i<ord;i++)
rnum[i] = num[ord-i-1]; rnum[i] = num[ord-i-1];
for(i=0;i<ord;i++)
x[i] = mem[ord-i-1];
for (i=0;i<N;i++)
x[i+ord]=_x[i];
for(i=0;i<ord;i++)
mem[i] = _x[N-i-1];
#ifdef SMALL_FOOTPRINT
for (i=0;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]);
}
_y[i] = SATURATE16(PSHR32(sum, SIG_SHIFT));
}
#else
for (i=0;i<N-3;i+=4) for (i=0;i<N-3;i+=4)
{ {
opus_val32 sum[4]={0,0,0,0}; opus_val32 sum[4];
xcorr_kernel(rnum, x+i, sum, ord); sum[0] = SHL32(EXTEND32(x[i ]), SIG_SHIFT);
_y[i ] = SATURATE16(ADD32(EXTEND32(_x[i ]), PSHR32(sum[0], SIG_SHIFT))); sum[1] = SHL32(EXTEND32(x[i+1]), SIG_SHIFT);
_y[i+1] = SATURATE16(ADD32(EXTEND32(_x[i+1]), PSHR32(sum[1], SIG_SHIFT))); sum[2] = SHL32(EXTEND32(x[i+2]), SIG_SHIFT);
_y[i+2] = SATURATE16(ADD32(EXTEND32(_x[i+2]), PSHR32(sum[2], SIG_SHIFT))); sum[3] = SHL32(EXTEND32(x[i+3]), SIG_SHIFT);
_y[i+3] = SATURATE16(ADD32(EXTEND32(_x[i+3]), PSHR32(sum[3], SIG_SHIFT))); xcorr_kernel(rnum, x+i-ord, sum, ord, arch);
y[i ] = ROUND16(sum[0], SIG_SHIFT);
y[i+1] = ROUND16(sum[1], SIG_SHIFT);
y[i+2] = ROUND16(sum[2], SIG_SHIFT);
y[i+3] = ROUND16(sum[3], SIG_SHIFT);
} }
for (;i<N;i++) for (;i<N;i++)
{ {
opus_val32 sum = 0; opus_val32 sum = SHL32(EXTEND32(x[i]), SIG_SHIFT);
for (j=0;j<ord;j++) for (j=0;j<ord;j++)
sum = MAC16_16(sum,rnum[j],x[i+j]); sum = MAC16_16(sum,rnum[j],x[i+j-ord]);
_y[i] = SATURATE16(ADD32(EXTEND32(_x[i]), PSHR32(sum, SIG_SHIFT))); y[i] = ROUND16(sum, SIG_SHIFT);
} }
#endif
RESTORE_STACK; RESTORE_STACK;
} }
@ -146,10 +131,12 @@ void celt_iir(const opus_val32 *_x,
opus_val32 *_y, opus_val32 *_y,
int N, int N,
int ord, int ord,
opus_val16 *mem) opus_val16 *mem,
int arch)
{ {
#ifdef SMALL_FOOTPRINT #ifdef SMALL_FOOTPRINT
int i,j; int i,j;
(void)arch;
for (i=0;i<N;i++) for (i=0;i<N;i++)
{ {
opus_val32 sum = _x[i]; opus_val32 sum = _x[i];
@ -161,7 +148,7 @@ void celt_iir(const opus_val32 *_x,
{ {
mem[j]=mem[j-1]; mem[j]=mem[j-1];
} }
mem[0] = ROUND16(sum,SIG_SHIFT); mem[0] = SROUND16(sum, SIG_SHIFT);
_y[i] = sum; _y[i] = sum;
} }
#else #else
@ -187,23 +174,23 @@ void celt_iir(const opus_val32 *_x,
sum[1]=_x[i+1]; sum[1]=_x[i+1];
sum[2]=_x[i+2]; sum[2]=_x[i+2];
sum[3]=_x[i+3]; sum[3]=_x[i+3];
xcorr_kernel(rden, y+i, sum, ord); xcorr_kernel(rden, y+i, sum, ord, arch);
/* Patch up the result to compensate for the fact that this is an IIR */ /* Patch up the result to compensate for the fact that this is an IIR */
y[i+ord ] = -ROUND16(sum[0],SIG_SHIFT); y[i+ord ] = -SROUND16(sum[0],SIG_SHIFT);
_y[i ] = sum[0]; _y[i ] = sum[0];
sum[1] = MAC16_16(sum[1], y[i+ord ], den[0]); sum[1] = MAC16_16(sum[1], y[i+ord ], den[0]);
y[i+ord+1] = -ROUND16(sum[1],SIG_SHIFT); y[i+ord+1] = -SROUND16(sum[1],SIG_SHIFT);
_y[i+1] = sum[1]; _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+1], den[0]);
sum[2] = MAC16_16(sum[2], y[i+ord ], den[1]); sum[2] = MAC16_16(sum[2], y[i+ord ], den[1]);
y[i+ord+2] = -ROUND16(sum[2],SIG_SHIFT); y[i+ord+2] = -SROUND16(sum[2],SIG_SHIFT);
_y[i+2] = sum[2]; _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+2], den[0]);
sum[3] = MAC16_16(sum[3], y[i+ord+1], den[1]); sum[3] = MAC16_16(sum[3], y[i+ord+1], den[1]);
sum[3] = MAC16_16(sum[3], y[i+ord ], den[2]); sum[3] = MAC16_16(sum[3], y[i+ord ], den[2]);
y[i+ord+3] = -ROUND16(sum[3],SIG_SHIFT); y[i+ord+3] = -SROUND16(sum[3],SIG_SHIFT);
_y[i+3] = sum[3]; _y[i+3] = sum[3];
} }
for (;i<N;i++) for (;i<N;i++)
@ -211,7 +198,7 @@ void celt_iir(const opus_val32 *_x,
opus_val32 sum = _x[i]; opus_val32 sum = _x[i];
for (j=0;j<ord;j++) for (j=0;j<ord;j++)
sum -= MULT16_16(rden[j],y[i+j]); sum -= MULT16_16(rden[j],y[i+j]);
y[i+ord] = ROUND16(sum,SIG_SHIFT); y[i+ord] = SROUND16(sum,SIG_SHIFT);
_y[i] = sum; _y[i] = sum;
} }
for(i=0;i<ord;i++) for(i=0;i<ord;i++)

View file

@ -29,24 +29,36 @@
#define PLC_H #define PLC_H
#include "arch.h" #include "arch.h"
#include "cpu_support.h"
#if defined(OPUS_X86_MAY_HAVE_SSE4_1)
#include "x86/celt_lpc_sse.h"
#endif
#define LPC_ORDER 24 #define LPC_ORDER 24
void _celt_lpc(opus_val16 *_lpc, const opus_val32 *ac, int p); void _celt_lpc(opus_val16 *_lpc, const opus_val32 *ac, int p);
void celt_fir(const opus_val16 *x, void celt_fir_c(
const opus_val16 *x,
const opus_val16 *num, const opus_val16 *num,
opus_val16 *y, opus_val16 *y,
int N, int N,
int ord, int ord,
opus_val16 *mem); 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, void celt_iir(const opus_val32 *x,
const opus_val16 *den, const opus_val16 *den,
opus_val32 *y, opus_val32 *y,
int N, int N,
int ord, int ord,
opus_val16 *mem); opus_val16 *mem,
int arch);
int _celt_autocorr(const opus_val16 *x, opus_val32 *ac, int _celt_autocorr(const opus_val16 *x, opus_val32 *ac,
const opus_val16 *window, int overlap, int lag, int n, int arch); const opus_val16 *window, int overlap, int lag, int n, int arch);

View file

@ -31,7 +31,8 @@
#include "opus_types.h" #include "opus_types.h"
#include "opus_defines.h" #include "opus_defines.h"
#if defined(OPUS_HAVE_RTCD) && defined(OPUS_ARM_ASM) #if defined(OPUS_HAVE_RTCD) && \
(defined(OPUS_ARM_ASM) || defined(OPUS_ARM_MAY_HAVE_NEON_INTR))
#include "arm/armcpu.h" #include "arm/armcpu.h"
/* We currently support 4 ARM variants: /* We currently support 4 ARM variants:
@ -42,6 +43,22 @@
*/ */
#define OPUS_ARCHMASK 3 #define OPUS_ARCHMASK 3
#elif (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_AVX) && !defined(OPUS_X86_PRESUME_AVX))
#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 #else
#define OPUS_ARCHMASK 0 #define OPUS_ARCHMASK 0
@ -50,5 +67,4 @@ static OPUS_INLINE int opus_select_arch(void)
return 0; return 0;
} }
#endif #endif
#endif #endif

View file

@ -74,7 +74,7 @@ int log2_frac(opus_uint32 val, int frac)
/*Although derived separately, the pulse vector coding scheme is equivalent to /*Although derived separately, the pulse vector coding scheme is equivalent to
a Pyramid Vector Quantizer \cite{Fis86}. a Pyramid Vector Quantizer \cite{Fis86}.
Some additional notes about an early version appear at Some additional notes about an early version appear at
http://people.xiph.org/~tterribe/notes/cwrs.html, but the codebook ordering https://people.xiph.org/~tterribe/notes/cwrs.html, but the codebook ordering
and the definitions of some terms have evolved since that was written. 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 The conversion from a pulse vector to an integer index (encoding) and back
@ -210,7 +210,7 @@ int log2_frac(opus_uint32 val, int frac)
#if defined(CUSTOM_MODES) #if defined(CUSTOM_MODES)
static const opus_uint32 CELT_PVQ_U_DATA[1488]={ static const opus_uint32 CELT_PVQ_U_DATA[1488]={
#else #else
static const opus_uint32 CELT_PVQ_U_DATA[1272] ICONST_ATTR ={ static const opus_uint32 CELT_PVQ_U_DATA[1272]={
#endif #endif
/*N=0, K=0...176:*/ /*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, 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,
@ -418,7 +418,7 @@ static const opus_uint32 *const CELT_PVQ_U_ROW[15]={
CELT_PVQ_U_DATA+1464,CELT_PVQ_U_DATA+1470,CELT_PVQ_U_DATA+1473 CELT_PVQ_U_DATA+1464,CELT_PVQ_U_DATA+1470,CELT_PVQ_U_DATA+1473
}; };
#else #else
static const opus_uint32 *const CELT_PVQ_U_ROW[15] ICONST_ATTR ={ 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+ 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+ 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+1041,CELT_PVQ_U_DATA+1131,CELT_PVQ_U_DATA+1178,
@ -482,7 +482,7 @@ static opus_val32 cwrsi(int _n,int _k,opus_uint32 _i,int *_y){
k0=_k; k0=_k;
q=row[_n]; q=row[_n];
if(q>_i){ if(q>_i){
celt_assert(p>q); celt_sig_assert(p>q);
_k=_n; _k=_n;
do p=CELT_PVQ_U_ROW[--_k][_n]; do p=CELT_PVQ_U_ROW[--_k][_n];
while(p>_i); while(p>_i);

View file

@ -0,0 +1,32 @@
CFLAGS=-O2 -Wall -Wextra -DHAVE_CONFIG_H
INCLUDES=-I. -I../ -I../.. -I../../include
SOURCES = dump_modes.c \
../modes.c \
../cwrs.c \
../rate.c \
../entcode.c \
../entenc.c \
../entdec.c \
../mathops.c \
../mdct.c \
../kiss_fft.c
ifdef HAVE_ARM_NE10
CC = gcc
CFLAGS += -mfpu=neon
INCLUDES += -I$(NE10_INCDIR) -DHAVE_ARM_NE10 -DOPUS_ARM_PRESUME_NEON_INTR
LIBS = -L$(NE10_LIBDIR) -lNE10
SOURCES += ../arm/celt_ne10_fft.c \
dump_modes_arm_ne10.c \
../arm/armcpu.c
endif
all: dump_modes
dump_modes:
$(PREFIX)$(CC) $(CFLAGS) $(INCLUDES) -DCUSTOM_MODES_ONLY -DCUSTOM_MODES $(SOURCES) -o $@ $(LIBS) -lm
clean:
rm -f dump_modes

View file

@ -0,0 +1,353 @@
/* Copyright (c) 2008 CSIRO
Copyright (c) 2008-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 <stdlib.h>
#include <stdio.h>
#include "modes.h"
#include "celt.h"
#include "rate.h"
#include "dump_modes_arch.h"
#define INT16 "%d"
#define INT32 "%d"
#define FLOAT "%#0.8gf"
#ifdef FIXED_POINT
#define WORD16 INT16
#define WORD32 INT32
#else
#define WORD16 FLOAT
#define WORD32 FLOAT
#endif
void dump_modes(FILE *file, CELTMode **modes, int nb_modes)
{
int i, j, k;
int mdct_twiddles_size;
fprintf(file, "/* The contents of this file was automatically generated by dump_modes.c\n");
fprintf(file, " with arguments:");
for (i=0;i<nb_modes;i++)
{
CELTMode *mode = modes[i];
fprintf(file, " %d %d",mode->Fs,mode->shortMdctSize*mode->nbShortMdcts);
}
fprintf(file, "\n It contains static definitions for some pre-defined modes. */\n");
fprintf(file, "#include \"modes.h\"\n");
fprintf(file, "#include \"rate.h\"\n");
fprintf(file, "\n#ifdef HAVE_ARM_NE10\n");
fprintf(file, "#define OVERRIDE_FFT 1\n");
fprintf(file, "#include \"%s\"\n", ARM_NE10_ARCH_FILE_NAME);
fprintf(file, "#endif\n");
fprintf(file, "\n");
for (i=0;i<nb_modes;i++)
{
CELTMode *mode = modes[i];
int mdctSize;
int standard, framerate;
mdctSize = mode->shortMdctSize*mode->nbShortMdcts;
standard = (mode->Fs == 400*(opus_int32)mode->shortMdctSize);
framerate = mode->Fs/mode->shortMdctSize;
if (!standard)
{
fprintf(file, "#ifndef DEF_EBANDS%d_%d\n", mode->Fs, mdctSize);
fprintf(file, "#define DEF_EBANDS%d_%d\n", mode->Fs, mdctSize);
fprintf (file, "static const opus_int16 eBands%d_%d[%d] = {\n", mode->Fs, mdctSize, mode->nbEBands+2);
for (j=0;j<mode->nbEBands+2;j++)
fprintf (file, "%d, ", mode->eBands[j]);
fprintf (file, "};\n");
fprintf(file, "#endif\n");
fprintf(file, "\n");
}
fprintf(file, "#ifndef DEF_WINDOW%d\n", mode->overlap);
fprintf(file, "#define DEF_WINDOW%d\n", mode->overlap);
fprintf (file, "static const opus_val16 window%d[%d] = {\n", mode->overlap, mode->overlap);
for (j=0;j<mode->overlap;j++)
fprintf (file, WORD16 ",%c", mode->window[j],(j+6)%5==0?'\n':' ');
fprintf (file, "};\n");
fprintf(file, "#endif\n");
fprintf(file, "\n");
if (!standard)
{
fprintf(file, "#ifndef DEF_ALLOC_VECTORS%d_%d\n", mode->Fs, mdctSize);
fprintf(file, "#define DEF_ALLOC_VECTORS%d_%d\n", mode->Fs, mdctSize);
fprintf (file, "static const unsigned char allocVectors%d_%d[%d] = {\n", mode->Fs, mdctSize, mode->nbEBands*mode->nbAllocVectors);
for (j=0;j<mode->nbAllocVectors;j++)
{
for (k=0;k<mode->nbEBands;k++)
fprintf (file, "%2d, ", mode->allocVectors[j*mode->nbEBands+k]);
fprintf (file, "\n");
}
fprintf (file, "};\n");
fprintf(file, "#endif\n");
fprintf(file, "\n");
}
fprintf(file, "#ifndef DEF_LOGN%d\n", framerate);
fprintf(file, "#define DEF_LOGN%d\n", framerate);
fprintf (file, "static const opus_int16 logN%d[%d] = {\n", framerate, mode->nbEBands);
for (j=0;j<mode->nbEBands;j++)
fprintf (file, "%d, ", mode->logN[j]);
fprintf (file, "};\n");
fprintf(file, "#endif\n");
fprintf(file, "\n");
/* Pulse cache */
fprintf(file, "#ifndef DEF_PULSE_CACHE%d\n", mode->Fs/mdctSize);
fprintf(file, "#define DEF_PULSE_CACHE%d\n", mode->Fs/mdctSize);
fprintf (file, "static const opus_int16 cache_index%d[%d] = {\n", mode->Fs/mdctSize, (mode->maxLM+2)*mode->nbEBands);
for (j=0;j<mode->nbEBands*(mode->maxLM+2);j++)
fprintf (file, "%d,%c", mode->cache.index[j],(j+16)%15==0?'\n':' ');
fprintf (file, "};\n");
fprintf (file, "static const unsigned char cache_bits%d[%d] = {\n", mode->Fs/mdctSize, mode->cache.size);
for (j=0;j<mode->cache.size;j++)
fprintf (file, "%d,%c", mode->cache.bits[j],(j+16)%15==0?'\n':' ');
fprintf (file, "};\n");
fprintf (file, "static const unsigned char cache_caps%d[%d] = {\n", mode->Fs/mdctSize, (mode->maxLM+1)*2*mode->nbEBands);
for (j=0;j<(mode->maxLM+1)*2*mode->nbEBands;j++)
fprintf (file, "%d,%c", mode->cache.caps[j],(j+16)%15==0?'\n':' ');
fprintf (file, "};\n");
fprintf(file, "#endif\n");
fprintf(file, "\n");
/* FFT twiddles */
fprintf(file, "#ifndef FFT_TWIDDLES%d_%d\n", mode->Fs, mdctSize);
fprintf(file, "#define FFT_TWIDDLES%d_%d\n", mode->Fs, mdctSize);
fprintf (file, "static const kiss_twiddle_cpx fft_twiddles%d_%d[%d] = {\n",
mode->Fs, mdctSize, mode->mdct.kfft[0]->nfft);
for (j=0;j<mode->mdct.kfft[0]->nfft;j++)
fprintf (file, "{" WORD16 ", " WORD16 "},%c", mode->mdct.kfft[0]->twiddles[j].r, mode->mdct.kfft[0]->twiddles[j].i,(j+3)%2==0?'\n':' ');
fprintf (file, "};\n");
#ifdef OVERRIDE_FFT
dump_mode_arch(mode);
#endif
/* FFT Bitrev tables */
for (k=0;k<=mode->mdct.maxshift;k++)
{
fprintf(file, "#ifndef FFT_BITREV%d\n", mode->mdct.kfft[k]->nfft);
fprintf(file, "#define FFT_BITREV%d\n", mode->mdct.kfft[k]->nfft);
fprintf (file, "static const opus_int16 fft_bitrev%d[%d] = {\n",
mode->mdct.kfft[k]->nfft, mode->mdct.kfft[k]->nfft);
for (j=0;j<mode->mdct.kfft[k]->nfft;j++)
fprintf (file, "%d,%c", mode->mdct.kfft[k]->bitrev[j],(j+16)%15==0?'\n':' ');
fprintf (file, "};\n");
fprintf(file, "#endif\n");
fprintf(file, "\n");
}
/* FFT States */
for (k=0;k<=mode->mdct.maxshift;k++)
{
fprintf(file, "#ifndef FFT_STATE%d_%d_%d\n", mode->Fs, mdctSize, k);
fprintf(file, "#define FFT_STATE%d_%d_%d\n", mode->Fs, mdctSize, k);
fprintf (file, "static const kiss_fft_state fft_state%d_%d_%d = {\n",
mode->Fs, mdctSize, k);
fprintf (file, "%d, /* nfft */\n", mode->mdct.kfft[k]->nfft);
fprintf (file, WORD16 ", /* scale */\n", mode->mdct.kfft[k]->scale);
#ifdef FIXED_POINT
fprintf (file, "%d, /* scale_shift */\n", mode->mdct.kfft[k]->scale_shift);
#endif
fprintf (file, "%d, /* shift */\n", mode->mdct.kfft[k]->shift);
fprintf (file, "{");
for (j=0;j<2*MAXFACTORS;j++)
fprintf (file, "%d, ", mode->mdct.kfft[k]->factors[j]);
fprintf (file, "}, /* factors */\n");
fprintf (file, "fft_bitrev%d, /* bitrev */\n", mode->mdct.kfft[k]->nfft);
fprintf (file, "fft_twiddles%d_%d, /* bitrev */\n", mode->Fs, mdctSize);
fprintf (file, "#ifdef OVERRIDE_FFT\n");
fprintf (file, "(arch_fft_state *)&cfg_arch_%d,\n", mode->mdct.kfft[k]->nfft);
fprintf (file, "#else\n");
fprintf (file, "NULL,\n");
fprintf(file, "#endif\n");
fprintf (file, "};\n");
fprintf(file, "#endif\n");
fprintf(file, "\n");
}
fprintf(file, "#endif\n");
fprintf(file, "\n");
/* MDCT twiddles */
mdct_twiddles_size = mode->mdct.n-(mode->mdct.n/2>>mode->mdct.maxshift);
fprintf(file, "#ifndef MDCT_TWIDDLES%d\n", mdctSize);
fprintf(file, "#define MDCT_TWIDDLES%d\n", mdctSize);
fprintf (file, "static const opus_val16 mdct_twiddles%d[%d] = {\n",
mdctSize, mdct_twiddles_size);
for (j=0;j<mdct_twiddles_size;j++)
fprintf (file, WORD16 ",%c", mode->mdct.trig[j],(j+6)%5==0?'\n':' ');
fprintf (file, "};\n");
fprintf(file, "#endif\n");
fprintf(file, "\n");
/* Print the actual mode data */
fprintf(file, "static const CELTMode mode%d_%d_%d = {\n", mode->Fs, mdctSize, mode->overlap);
fprintf(file, INT32 ", /* Fs */\n", mode->Fs);
fprintf(file, "%d, /* overlap */\n", mode->overlap);
fprintf(file, "%d, /* nbEBands */\n", mode->nbEBands);
fprintf(file, "%d, /* effEBands */\n", mode->effEBands);
fprintf(file, "{");
for (j=0;j<4;j++)
fprintf(file, WORD16 ", ", mode->preemph[j]);
fprintf(file, "}, /* preemph */\n");
if (standard)
fprintf(file, "eband5ms, /* eBands */\n");
else
fprintf(file, "eBands%d_%d, /* eBands */\n", mode->Fs, mdctSize);
fprintf(file, "%d, /* maxLM */\n", mode->maxLM);
fprintf(file, "%d, /* nbShortMdcts */\n", mode->nbShortMdcts);
fprintf(file, "%d, /* shortMdctSize */\n", mode->shortMdctSize);
fprintf(file, "%d, /* nbAllocVectors */\n", mode->nbAllocVectors);
if (standard)
fprintf(file, "band_allocation, /* allocVectors */\n");
else
fprintf(file, "allocVectors%d_%d, /* allocVectors */\n", mode->Fs, mdctSize);
fprintf(file, "logN%d, /* logN */\n", framerate);
fprintf(file, "window%d, /* window */\n", mode->overlap);
fprintf(file, "{%d, %d, {", mode->mdct.n, mode->mdct.maxshift);
for (k=0;k<=mode->mdct.maxshift;k++)
fprintf(file, "&fft_state%d_%d_%d, ", mode->Fs, mdctSize, k);
fprintf (file, "}, mdct_twiddles%d}, /* mdct */\n", mdctSize);
fprintf(file, "{%d, cache_index%d, cache_bits%d, cache_caps%d}, /* cache */\n",
mode->cache.size, mode->Fs/mdctSize, mode->Fs/mdctSize, mode->Fs/mdctSize);
fprintf(file, "};\n");
}
fprintf(file, "\n");
fprintf(file, "/* List of all the available modes */\n");
fprintf(file, "#define TOTAL_MODES %d\n", nb_modes);
fprintf(file, "static const CELTMode * const static_mode_list[TOTAL_MODES] = {\n");
for (i=0;i<nb_modes;i++)
{
CELTMode *mode = modes[i];
int mdctSize;
mdctSize = mode->shortMdctSize*mode->nbShortMdcts;
fprintf(file, "&mode%d_%d_%d,\n", mode->Fs, mdctSize, mode->overlap);
}
fprintf(file, "};\n");
}
void dump_header(FILE *file, CELTMode **modes, int nb_modes)
{
int i;
int channels = 0;
int frame_size = 0;
int overlap = 0;
fprintf (file, "/* This header file is generated automatically*/\n");
for (i=0;i<nb_modes;i++)
{
CELTMode *mode = modes[i];
if (frame_size==0)
frame_size = mode->shortMdctSize*mode->nbShortMdcts;
else if (frame_size != mode->shortMdctSize*mode->nbShortMdcts)
frame_size = -1;
if (overlap==0)
overlap = mode->overlap;
else if (overlap != mode->overlap)
overlap = -1;
}
if (channels>0)
{
fprintf (file, "#define CHANNELS(mode) %d\n", channels);
if (channels==1)
fprintf (file, "#define DISABLE_STEREO\n");
}
if (frame_size>0)
{
fprintf (file, "#define FRAMESIZE(mode) %d\n", frame_size);
}
if (overlap>0)
{
fprintf (file, "#define OVERLAP(mode) %d\n", overlap);
}
}
#ifdef FIXED_POINT
#define BASENAME "static_modes_fixed"
#else
#define BASENAME "static_modes_float"
#endif
int main(int argc, char **argv)
{
int i, nb;
FILE *file;
CELTMode **m;
if (argc%2 != 1 || argc<3)
{
fprintf (stderr, "Usage: %s rate frame_size [rate frame_size] [rate frame_size]...\n",argv[0]);
return 1;
}
nb = (argc-1)/2;
m = malloc(nb*sizeof(CELTMode*));
for (i=0;i<nb;i++)
{
int Fs, frame;
Fs = atoi(argv[2*i+1]);
frame = atoi(argv[2*i+2]);
m[i] = opus_custom_mode_create(Fs, frame, NULL);
if (m[i]==NULL)
{
fprintf(stderr,"Error creating mode with Fs=%s, frame_size=%s\n",
argv[2*i+1],argv[2*i+2]);
return EXIT_FAILURE;
}
}
file = fopen(BASENAME ".h", "w");
#ifdef OVERRIDE_FFT
dump_modes_arch_init(m, nb);
#endif
dump_modes(file, m, nb);
fclose(file);
#ifdef OVERRIDE_FFT
dump_modes_arch_finalize();
#endif
for (i=0;i<nb;i++)
opus_custom_mode_destroy(m[i]);
free(m);
return 0;
}

View file

@ -0,0 +1,45 @@
/* Copyright (c) 2015 Xiph.Org Foundation
Written by Viswanath Puttagunta */
/*
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 DUMP_MODE_ARCH_H
#define DUMP_MODE_ARCH_H
void dump_modes_arch_init();
void dump_mode_arch(CELTMode *mode);
void dump_modes_arch_finalize();
#if !defined(FIXED_POINT)
#define ARM_NE10_ARCH_FILE_NAME "static_modes_float_arm_ne10.h"
#else
#define ARM_NE10_ARCH_FILE_NAME "static_modes_fixed_arm_ne10.h"
#endif
#if defined(HAVE_ARM_NE10)
#define OVERRIDE_FFT (1)
#endif
#endif

View file

@ -0,0 +1,152 @@
/* Copyright (c) 2015 Xiph.Org Foundation
Written by Viswanath Puttagunta */
/*
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 <stdio.h>
#include <stdlib.h>
#include "modes.h"
#include "dump_modes_arch.h"
#include <NE10_dsp.h>
#if !defined(FIXED_POINT)
# define NE10_FFT_CFG_TYPE_T ne10_fft_cfg_float32_t
# define NE10_FFT_CPX_TYPE_T_STR "ne10_fft_cpx_float32_t"
# define NE10_FFT_STATE_TYPE_T_STR "ne10_fft_state_float32_t"
#else
# define NE10_FFT_CFG_TYPE_T ne10_fft_cfg_int32_t
# define NE10_FFT_CPX_TYPE_T_STR "ne10_fft_cpx_int32_t"
# define NE10_FFT_STATE_TYPE_T_STR "ne10_fft_state_int32_t"
#endif
static FILE *file;
void dump_modes_arch_init(CELTMode **modes, int nb_modes)
{
int i;
file = fopen(ARM_NE10_ARCH_FILE_NAME, "w");
fprintf(file, "/* The contents of this file was automatically generated by\n");
fprintf(file, " * dump_mode_arm_ne10.c with arguments:");
for (i=0;i<nb_modes;i++)
{
CELTMode *mode = modes[i];
fprintf(file, " %d %d",mode->Fs,mode->shortMdctSize*mode->nbShortMdcts);
}
fprintf(file, "\n * It contains static definitions for some pre-defined modes. */\n");
fprintf(file, "#include <NE10_types.h>\n\n");
}
void dump_modes_arch_finalize()
{
fclose(file);
}
void dump_mode_arch(CELTMode *mode)
{
int k, j;
int mdctSize;
mdctSize = mode->shortMdctSize*mode->nbShortMdcts;
fprintf(file, "#ifndef NE10_FFT_PARAMS%d_%d\n", mode->Fs, mdctSize);
fprintf(file, "#define NE10_FFT_PARAMS%d_%d\n", mode->Fs, mdctSize);
/* cfg->factors */
for(k=0;k<=mode->mdct.maxshift;k++) {
NE10_FFT_CFG_TYPE_T cfg;
cfg = (NE10_FFT_CFG_TYPE_T)mode->mdct.kfft[k]->arch_fft->priv;
if (!cfg)
continue;
fprintf(file, "static const ne10_int32_t ne10_factors_%d[%d] = {\n",
mode->mdct.kfft[k]->nfft, (NE10_MAXFACTORS * 2));
for(j=0;j<(NE10_MAXFACTORS * 2);j++) {
fprintf(file, "%d,%c", cfg->factors[j],(j+16)%15==0?'\n':' ');
}
fprintf (file, "};\n");
}
/* cfg->twiddles */
for(k=0;k<=mode->mdct.maxshift;k++) {
NE10_FFT_CFG_TYPE_T cfg;
cfg = (NE10_FFT_CFG_TYPE_T)mode->mdct.kfft[k]->arch_fft->priv;
if (!cfg)
continue;
fprintf(file, "static const %s ne10_twiddles_%d[%d] = {\n",
NE10_FFT_CPX_TYPE_T_STR, mode->mdct.kfft[k]->nfft,
mode->mdct.kfft[k]->nfft);
for(j=0;j<mode->mdct.kfft[k]->nfft;j++) {
#if !defined(FIXED_POINT)
fprintf(file, "{%#0.8gf,%#0.8gf},%c",
cfg->twiddles[j].r, cfg->twiddles[j].i,(j+4)%3==0?'\n':' ');
#else
fprintf(file, "{%d,%d},%c",
cfg->twiddles[j].r, cfg->twiddles[j].i,(j+4)%3==0?'\n':' ');
#endif
}
fprintf (file, "};\n");
}
for(k=0;k<=mode->mdct.maxshift;k++) {
NE10_FFT_CFG_TYPE_T cfg;
cfg = (NE10_FFT_CFG_TYPE_T)mode->mdct.kfft[k]->arch_fft->priv;
if (!cfg) {
fprintf(file, "/* Ne10 does not support scaled FFT for length = %d */\n",
mode->mdct.kfft[k]->nfft);
fprintf(file, "static const arch_fft_state cfg_arch_%d = {\n", mode->mdct.kfft[k]->nfft);
fprintf(file, "0,\n");
fprintf(file, "NULL\n");
fprintf(file, "};\n");
continue;
}
fprintf(file, "static const %s %s_%d = {\n", NE10_FFT_STATE_TYPE_T_STR,
NE10_FFT_STATE_TYPE_T_STR, mode->mdct.kfft[k]->nfft);
fprintf(file, "%d,\n", cfg->nfft);
fprintf(file, "(ne10_int32_t *)ne10_factors_%d,\n", mode->mdct.kfft[k]->nfft);
fprintf(file, "(%s *)ne10_twiddles_%d,\n",
NE10_FFT_CPX_TYPE_T_STR, mode->mdct.kfft[k]->nfft);
fprintf(file, "NULL,\n"); /* buffer */
fprintf(file, "(%s *)&ne10_twiddles_%d[%d],\n",
NE10_FFT_CPX_TYPE_T_STR, mode->mdct.kfft[k]->nfft, cfg->nfft);
#if !defined(FIXED_POINT)
fprintf(file, "/* is_forward_scaled = true */\n");
fprintf(file, "(ne10_int32_t) 1,\n");
fprintf(file, "/* is_backward_scaled = false */\n");
fprintf(file, "(ne10_int32_t) 0,\n");
#endif
fprintf(file, "};\n");
fprintf(file, "static const arch_fft_state cfg_arch_%d = {\n",
mode->mdct.kfft[k]->nfft);
fprintf(file, "1,\n");
fprintf(file, "(void *)&%s_%d,\n",
NE10_FFT_STATE_TYPE_T_STR, mode->mdct.kfft[k]->nfft);
fprintf(file, "};\n\n");
}
fprintf(file, "#endif /* end NE10_FFT_PARAMS%d_%d */\n", mode->Fs, mdctSize);
}

View file

@ -116,7 +116,7 @@ opus_uint32 ec_tell_frac(ec_ctx *_this){
#ifdef USE_SMALL_DIV_TABLE #ifdef USE_SMALL_DIV_TABLE
/* Result of 2^32/(2*i+1), except for i=0. */ /* Result of 2^32/(2*i+1), except for i=0. */
const opus_uint32 SMALL_DIV_TABLE[129] ICONST_ATTR = { const opus_uint32 SMALL_DIV_TABLE[129] = {
0xFFFFFFFF, 0x55555555, 0x33333333, 0x24924924, 0xFFFFFFFF, 0x55555555, 0x33333333, 0x24924924,
0x1C71C71C, 0x1745D174, 0x13B13B13, 0x11111111, 0x1C71C71C, 0x1745D174, 0x13B13B13, 0x11111111,
0x0F0F0F0F, 0x0D79435E, 0x0C30C30C, 0x0B21642C, 0x0F0F0F0F, 0x0D79435E, 0x0C30C30C, 0x0B21642C,

View file

@ -122,7 +122,7 @@ opus_uint32 ec_tell_frac(ec_ctx *_this);
/* Tested exhaustively for all n and for 1<=d<=256 */ /* Tested exhaustively for all n and for 1<=d<=256 */
static OPUS_INLINE opus_uint32 celt_udiv(opus_uint32 n, opus_uint32 d) { static OPUS_INLINE opus_uint32 celt_udiv(opus_uint32 n, opus_uint32 d) {
celt_assert(d>0); celt_sig_assert(d>0);
#ifdef USE_SMALL_DIV_TABLE #ifdef USE_SMALL_DIV_TABLE
if (d>256) if (d>256)
return n/d; return n/d;
@ -138,7 +138,7 @@ static OPUS_INLINE opus_uint32 celt_udiv(opus_uint32 n, opus_uint32 d) {
} }
static OPUS_INLINE opus_int32 celt_sudiv(opus_int32 n, opus_int32 d) { static OPUS_INLINE opus_int32 celt_sudiv(opus_int32 n, opus_int32 d) {
celt_assert(d>0); celt_sig_assert(d>0);
#ifdef USE_SMALL_DIV_TABLE #ifdef USE_SMALL_DIV_TABLE
if (n<0) if (n<0)
return -(opus_int32)celt_udiv(-n, d); return -(opus_int32)celt_udiv(-n, d);

View file

@ -85,7 +85,7 @@ int ec_dec_icdf(ec_dec *_this,const unsigned char *_icdf,unsigned _ftb);
The bits must have been encoded with ec_enc_uint(). The bits must have been encoded with ec_enc_uint().
No call to ec_dec_update() is necessary after this call. 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). _ft: The number of integers that can be decoded (one more than the max).
This must be at least one, and no more than 2**32-1. This must be at least 2, and no more than 2**32-1.
Return: The decoded bits.*/ Return: The decoded bits.*/
opus_uint32 ec_dec_uint(ec_dec *_this,opus_uint32 _ft); opus_uint32 ec_dec_uint(ec_dec *_this,opus_uint32 _ft);

View file

@ -98,7 +98,7 @@ static void ec_enc_carry_out(ec_enc *_this,int _c){
else _this->ext++; else _this->ext++;
} }
static void ec_enc_normalize(ec_enc *_this){ static OPUS_INLINE void ec_enc_normalize(ec_enc *_this){
/*If the range is too small, output some bits and rescale it.*/ /*If the range is too small, output some bits and rescale it.*/
while(_this->rng<=EC_CODE_BOT){ while(_this->rng<=EC_CODE_BOT){
ec_enc_carry_out(_this,(int)(_this->val>>EC_CODE_SHIFT)); ec_enc_carry_out(_this,(int)(_this->val>>EC_CODE_SHIFT));

View file

@ -67,7 +67,7 @@ void ec_enc_icdf(ec_enc *_this,int _s,const unsigned char *_icdf,unsigned _ftb);
/*Encodes a raw unsigned integer in the stream. /*Encodes a raw unsigned integer in the stream.
_fl: The integer to encode. _fl: The integer to encode.
_ft: The number of integers that can be encoded (one more than the max). _ft: The number of integers that can be encoded (one more than the max).
This must be at least one, and no more than 2**32-1.*/ 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); void ec_enc_uint(ec_enc *_this,opus_uint32 _fl,opus_uint32 _ft);
/*Encodes a sequence of raw bits in the stream. /*Encodes a sequence of raw bits in the stream.

View file

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

View file

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

View file

@ -0,0 +1,791 @@
/* 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_16SU(a,b) ((opus_val32)(opus_val16)(a)*(opus_val32)(opus_uint16)(b))
#define MULT32_32_Q31(a,b) ADD32(ADD32(SHL32(MULT16_16(SHR32((a),16),SHR((b),16)),1), SHR32(MULT16_16SU(SHR32((a),16),((b)&0x0000ffff)),15)), SHR32(MULT16_16SU(SHR32((b),16),((a)&0x0000ffff)),15))
/** 16x32 multiplication, followed by a 16-bit shift right. Results fits in 32 bits */
#define MULT16_32_Q16(a,b) ADD32(MULT16_16((a),SHR32((b),16)), SHR32(MULT16_16SU((a),((b)&0x0000ffff)),16))
#define MULT16_32_P16(a,b) MULT16_32_PX(a,b,16)
#define QCONST16(x,bits) ((opus_val16)(.5+(x)*(((opus_val32)1)<<(bits))))
#define QCONST32(x,bits) ((opus_val32)(.5+(x)*(((opus_val32)1)<<(bits))))
#define VERIFY_SHORT(x) ((x)<=32767&&(x)>=-32768)
#define VERIFY_INT(x) ((x)<=2147483647LL&&(x)>=-2147483648LL)
#define VERIFY_UINT(x) ((x)<=(2147483647LLU<<1))
#define SHR(a,b) SHR32(a,b)
#define PSHR(a,b) PSHR32(a,b)
/** 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)))
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)
{
int res;
if (!VERIFY_SHORT(a) || !VERIFY_SHORT(shift))
{
fprintf (stderr, "SHL16: inputs are not short: %d %d in %s: line %d\n", a, shift, file, line);
#ifdef FIXED_DEBUG_ASSERT
celt_assert(0);
#endif
}
res = a<<shift;
if (!VERIFY_SHORT(res))
{
fprintf (stderr, "SHL16: output is not short: %d in %s: line %d\n", res, file, line);
#ifdef FIXED_DEBUG_ASSERT
celt_assert(0);
#endif
}
celt_mips++;
return res;
}
static 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", a, shift, file, line);
#ifdef FIXED_DEBUG_ASSERT
celt_assert(0);
#endif
}
res = a<<shift;
if (!VERIFY_INT(res))
{
fprintf (stderr, "SHL32: output is not int: %lld<<%d = %lld in %s: line %d\n", a, shift, res, file, line);
#ifdef FIXED_DEBUG_ASSERT
celt_assert(0);
#endif
}
celt_mips+=2;
return res;
}
#define PSHR32(a,shift) (celt_mips--,SHR32(ADD32((a),(((opus_val32)(1)<<((shift))>>1))),shift))
#define VSHR32(a, shift) (((shift)>0) ? SHR32(a, shift) : SHL32(a, -(shift)))
#define ROUND16(x,a) (celt_mips--,EXTRACT16(PSHR32((x),(a))))
#define 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", a, b, file, line);
#ifdef FIXED_DEBUG_ASSERT
celt_assert(0);
#endif
}
res = a+b;
if (!VERIFY_UINT(res))
{
fprintf (stderr, "UADD32: output is not uint32: %llu in %s: line %d\n", res, file, line);
#ifdef FIXED_DEBUG_ASSERT
celt_assert(0);
#endif
}
celt_mips+=2;
return res;
}
#undef USUB32
#define USUB32(a, b) USUB32_(a, b, __FILE__, __LINE__)
static 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", a, b, file, line);
#ifdef FIXED_DEBUG_ASSERT
celt_assert(0);
#endif
}
if (a<b)
{
fprintf (stderr, "USUB32: inputs underflow: %llu < %llu in %s: line %d\n", a, b, file, line);
#ifdef FIXED_DEBUG_ASSERT
celt_assert(0);
#endif
}
res = a-b;
if (!VERIFY_UINT(res))
{
fprintf (stderr, "USUB32: output is not uint32: %llu - %llu = %llu in %s: line %d\n", a, b, res, file, line);
#ifdef FIXED_DEBUG_ASSERT
celt_assert(0);
#endif
}
celt_mips+=2;
return res;
}
/* result fits in 16 bits */
static 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;
}
#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_val32)(1)<<(15+Q)))
{
fprintf (stderr, "MULT16_32_Q%d: second operand too large: %d %d in %s: line %d\n", Q, (int)a, (int)b, file, line);
#ifdef FIXED_DEBUG_ASSERT
celt_assert(0);
#endif
}
res = (((opus_int64)a)*(opus_int64)b) >> Q;
if (!VERIFY_INT(res))
{
fprintf (stderr, "MULT16_32_Q%d: output is not int: %d*%d=%d in %s: line %d\n", Q, (int)a, (int)b,(int)res, file, line);
#ifdef FIXED_DEBUG_ASSERT
celt_assert(0);
#endif
}
if (Q==15)
celt_mips+=3;
else
celt_mips+=4;
return res;
}
#define MULT16_32_PX(a, b, Q) MULT16_32_PX_(a, b, Q, __FILE__, __LINE__)
static 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)<<(15+Q)))
{
fprintf (stderr, "MULT16_32_Q%d: second operand too large: %d %d in %s: line %d\n\n", Q, (int)a, (int)b,file, line);
#ifdef FIXED_DEBUG_ASSERT
celt_assert(0);
#endif
}
res = ((((opus_int64)a)*(opus_int64)b) + (((opus_val32)(1)<<Q)>>1))>> Q;
if (!VERIFY_INT(res))
{
fprintf (stderr, "MULT16_32_P%d: output is not int: %d*%d=%d in %s: line %d\n\n", Q, (int)a, (int)b,(int)res, file, line);
#ifdef FIXED_DEBUG_ASSERT
celt_assert(0);
#endif
}
if (Q==15)
celt_mips+=4;
else
celt_mips+=5;
return res;
}
#define MULT16_32_Q15(a,b) MULT16_32_QX(a,b,15)
#define MAC16_32_Q15(c,a,b) (celt_mips-=2,ADD32((c),MULT16_32_Q15((a),(b))))
#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", celt_mips);} while (0);
#endif

View file

@ -37,16 +37,32 @@
#define MULT16_16SU(a,b) ((opus_val32)(opus_val16)(a)*(opus_val32)(opus_uint16)(b)) #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 */ /** 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)) #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 */ /** 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)) #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 */ /** 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)) #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 31-bit shift right. Results fits in 32 bits */ /** 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)) #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
/** Compile-time conversion of float constant to 16-bit value */ /** Compile-time conversion of float constant to 16-bit value */
#define QCONST16(x,bits) ((opus_val16)(.5+(x)*(((opus_val32)1)<<(bits)))) #define QCONST16(x,bits) ((opus_val16)(.5+(x)*(((opus_val32)1)<<(bits))))
@ -88,6 +104,9 @@
/** Shift by a and round-to-neareast 32-bit value. Result is a 16-bit value */ /** Shift by a and round-to-neareast 32-bit value. Result is a 16-bit value */
#define ROUND16(x,a) (EXTRACT16(PSHR32((x),(a)))) #define ROUND16(x,a) (EXTRACT16(PSHR32((x),(a))))
/** Shift by a and round-to-neareast 32-bit value. Result is a saturated 16-bit value */
#define SROUND16(x,a) EXTRACT16(SATURATE(PSHR32(x,a), 32767));
/** Divide by two */ /** Divide by two */
#define HALF16(x) (SHR16(x,1)) #define HALF16(x) (SHR16(x,1))
#define HALF32(x) (SHR32(x,1)) #define HALF32(x) (SHR32(x,1))
@ -101,6 +120,14 @@
/** Subtract two 32-bit values */ /** Subtract two 32-bit values */
#define SUB32(a,b) ((opus_val32)(a)-(opus_val32)(b)) #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)))
/** 16x16 multiplication where the result fits in 16 bits */ /** 16x16 multiplication where the result fits in 16 bits */
#define MULT16_16_16(a,b) ((((opus_val16)(a))*((opus_val16)(b)))) #define MULT16_16_16(a,b) ((((opus_val16)(a))*((opus_val16)(b))))

View file

@ -61,7 +61,13 @@
** the config.h file. ** the config.h file.
*/ */
#if (HAVE_LRINTF) /* 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(HAVE_LRINTF)
/* These defines enable functionality introduced with the 1999 ISO C /* These defines enable functionality introduced with the 1999 ISO C
** standard. They must be defined before the inclusion of math.h to ** standard. They must be defined before the inclusion of math.h to
@ -90,21 +96,21 @@
#include <math.h> #include <math.h>
#define float2int(x) lrint(x) #define float2int(x) lrint(x)
#elif (defined(_MSC_VER) && _MSC_VER >= 1400) && (defined (WIN64) || defined (_WIN64)) #elif (defined(_MSC_VER) && _MSC_VER >= 1400) && (defined(_M_X64) || (defined(_M_IX86_FP) && _M_IX86_FP >= 1))
#include <xmmintrin.h> #include <xmmintrin.h>
__inline long int float2int(float value) static __inline long int float2int(float value)
{ {
return _mm_cvtss_si32(_mm_load_ss(&value)); return _mm_cvtss_si32(_mm_load_ss(&value));
} }
#elif (defined(_MSC_VER) && _MSC_VER >= 1400) && (defined (WIN32) || defined (_WIN32)) #elif (defined(_MSC_VER) && _MSC_VER >= 1400) && defined (_M_IX86)
#include <math.h> #include <math.h>
/* Win32 doesn't seem to have these functions. /* Win32 doesn't seem to have these functions.
** Therefore implement OPUS_INLINE versions of these functions here. ** Therefore implement OPUS_INLINE versions of these functions here.
*/ */
__inline long int static __inline long int
float2int (float flt) float2int (float flt)
{ int intgr; { int intgr;

View file

@ -82,8 +82,8 @@ static void kf_bfly2(
C_SUB( Fout2[0] , Fout[0] , t ); C_SUB( Fout2[0] , Fout[0] , t );
C_ADDTO( Fout[0] , t ); C_ADDTO( Fout[0] , t );
t.r = S_MUL(Fout2[1].r+Fout2[1].i, tw); t.r = S_MUL(ADD32_ovflw(Fout2[1].r, Fout2[1].i), tw);
t.i = S_MUL(Fout2[1].i-Fout2[1].r, tw); t.i = S_MUL(SUB32_ovflw(Fout2[1].i, Fout2[1].r), tw);
C_SUB( Fout2[1] , Fout[1] , t ); C_SUB( Fout2[1] , Fout[1] , t );
C_ADDTO( Fout[1] , t ); C_ADDTO( Fout[1] , t );
@ -92,8 +92,8 @@ static void kf_bfly2(
C_SUB( Fout2[2] , Fout[2] , t ); C_SUB( Fout2[2] , Fout[2] , t );
C_ADDTO( Fout[2] , t ); C_ADDTO( Fout[2] , t );
t.r = S_MUL(Fout2[3].i-Fout2[3].r, tw); t.r = S_MUL(SUB32_ovflw(Fout2[3].i, Fout2[3].r), tw);
t.i = S_MUL(-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_SUB( Fout2[3] , Fout[3] , t );
C_ADDTO( Fout[3] , t ); C_ADDTO( Fout[3] , t );
Fout += 8; Fout += 8;
@ -126,10 +126,10 @@ static void kf_bfly4(
C_ADDTO( *Fout , scratch1 ); C_ADDTO( *Fout , scratch1 );
C_SUB( scratch1 , Fout[1] , Fout[3] ); C_SUB( scratch1 , Fout[1] , Fout[3] );
Fout[1].r = scratch0.r + scratch1.i; Fout[1].r = ADD32_ovflw(scratch0.r, scratch1.i);
Fout[1].i = scratch0.i - scratch1.r; Fout[1].i = SUB32_ovflw(scratch0.i, scratch1.r);
Fout[3].r = scratch0.r - scratch1.i; Fout[3].r = SUB32_ovflw(scratch0.r, scratch1.i);
Fout[3].i = scratch0.i + scratch1.r; Fout[3].i = ADD32_ovflw(scratch0.i, scratch1.r);
Fout+=4; Fout+=4;
} }
} else { } else {
@ -160,10 +160,10 @@ static void kf_bfly4(
tw3 += fstride*3; tw3 += fstride*3;
C_ADDTO( *Fout , scratch[3] ); C_ADDTO( *Fout , scratch[3] );
Fout[m].r = scratch[5].r + scratch[4].i; Fout[m].r = ADD32_ovflw(scratch[5].r, scratch[4].i);
Fout[m].i = scratch[5].i - scratch[4].r; Fout[m].i = SUB32_ovflw(scratch[5].i, scratch[4].r);
Fout[m3].r = scratch[5].r - scratch[4].i; Fout[m3].r = SUB32_ovflw(scratch[5].r, scratch[4].i);
Fout[m3].i = scratch[5].i + scratch[4].r; Fout[m3].i = ADD32_ovflw(scratch[5].i, scratch[4].r);
++Fout; ++Fout;
} }
} }
@ -191,7 +191,7 @@ static void kf_bfly3(
kiss_fft_cpx * Fout_beg = Fout; kiss_fft_cpx * Fout_beg = Fout;
#ifdef FIXED_POINT #ifdef FIXED_POINT
epi3.r = -16384; /*epi3.r = -16384;*/ /* Unused */
epi3.i = -28378; epi3.i = -28378;
#else #else
epi3 = st->twiddles[fstride*m]; epi3 = st->twiddles[fstride*m];
@ -212,18 +212,18 @@ static void kf_bfly3(
tw1 += fstride; tw1 += fstride;
tw2 += fstride*2; tw2 += fstride*2;
Fout[m].r = Fout->r - HALF_OF(scratch[3].r); Fout[m].r = SUB32_ovflw(Fout->r, HALF_OF(scratch[3].r));
Fout[m].i = Fout->i - HALF_OF(scratch[3].i); Fout[m].i = SUB32_ovflw(Fout->i, HALF_OF(scratch[3].i));
C_MULBYSCALAR( scratch[0] , epi3.i ); C_MULBYSCALAR( scratch[0] , epi3.i );
C_ADDTO(*Fout,scratch[3]); C_ADDTO(*Fout,scratch[3]);
Fout[m2].r = Fout[m].r + scratch[0].i; Fout[m2].r = ADD32_ovflw(Fout[m].r, scratch[0].i);
Fout[m2].i = Fout[m].i - scratch[0].r; Fout[m2].i = SUB32_ovflw(Fout[m].i, scratch[0].r);
Fout[m].r -= scratch[0].i; Fout[m].r = SUB32_ovflw(Fout[m].r, scratch[0].i);
Fout[m].i += scratch[0].r; Fout[m].i = ADD32_ovflw(Fout[m].i, scratch[0].r);
++Fout; ++Fout;
} while(--k); } while(--k);
@ -282,22 +282,22 @@ static void kf_bfly5(
C_ADD( scratch[8],scratch[2],scratch[3]); C_ADD( scratch[8],scratch[2],scratch[3]);
C_SUB( scratch[9],scratch[2],scratch[3]); C_SUB( scratch[9],scratch[2],scratch[3]);
Fout0->r += scratch[7].r + scratch[8].r; Fout0->r = ADD32_ovflw(Fout0->r, ADD32_ovflw(scratch[7].r, scratch[8].r));
Fout0->i += scratch[7].i + scratch[8].i; Fout0->i = ADD32_ovflw(Fout0->i, ADD32_ovflw(scratch[7].i, scratch[8].i));
scratch[5].r = scratch[0].r + S_MUL(scratch[7].r,ya.r) + S_MUL(scratch[8].r,yb.r); scratch[5].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 = scratch[0].i + S_MUL(scratch[7].i,ya.r) + S_MUL(scratch[8].i,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 = S_MUL(scratch[10].i,ya.i) + S_MUL(scratch[9].i,yb.i); scratch[6].r = ADD32_ovflw(S_MUL(scratch[10].i,ya.i), S_MUL(scratch[9].i,yb.i));
scratch[6].i = -S_MUL(scratch[10].r,ya.i) - S_MUL(scratch[9].r,yb.i); 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_SUB(*Fout1,scratch[5],scratch[6]);
C_ADD(*Fout4,scratch[5],scratch[6]); C_ADD(*Fout4,scratch[5],scratch[6]);
scratch[11].r = scratch[0].r + S_MUL(scratch[7].r,yb.r) + S_MUL(scratch[8].r,ya.r); scratch[11].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 = scratch[0].i + S_MUL(scratch[7].i,yb.r) + S_MUL(scratch[8].i,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 = - S_MUL(scratch[10].i,yb.i) + S_MUL(scratch[9].i,ya.i); scratch[12].r = SUB32_ovflw(S_MUL(scratch[9].i,ya.i), S_MUL(scratch[10].i,yb.i));
scratch[12].i = S_MUL(scratch[10].r,yb.i) - S_MUL(scratch[9].r,ya.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_ADD(*Fout2,scratch[11],scratch[12]);
C_SUB(*Fout3,scratch[11],scratch[12]); C_SUB(*Fout3,scratch[11],scratch[12]);
@ -423,13 +423,19 @@ static void compute_twiddles(kiss_twiddle_cpx *twiddles, int nfft)
#endif #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. * Allocates all necessary storage space for the fft and ifft.
* The return value is a contiguous block of memory. As such, * The return value is a contiguous block of memory. As such,
* It can be freed with free(). * It can be freed with free().
* */ * */
kiss_fft_state *opus_fft_alloc_twiddles(int nfft,void * mem,size_t * lenmem, const kiss_fft_state *base) kiss_fft_state *opus_fft_alloc_twiddles(int nfft,void * mem,size_t * lenmem,
const kiss_fft_state *base, int arch)
{ {
kiss_fft_state *st=NULL; kiss_fft_state *st=NULL;
size_t memneeded = sizeof(struct kiss_fft_state); /* twiddle factors*/ size_t memneeded = sizeof(struct kiss_fft_state); /* twiddle factors*/
@ -478,22 +484,31 @@ kiss_fft_state *opus_fft_alloc_twiddles(int nfft,void * mem,size_t * lenmem, co
if (st->bitrev==NULL) if (st->bitrev==NULL)
goto fail; goto fail;
compute_bitrev_table(0, bitrev, 1,1, st->factors,st); 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; return st;
fail: fail:
opus_fft_free(st); opus_fft_free(st, arch);
return NULL; return NULL;
} }
kiss_fft_state *opus_fft_alloc(int nfft,void * mem,size_t * lenmem ) kiss_fft_state *opus_fft_alloc(int nfft,void * mem,size_t * lenmem, int arch)
{ {
return opus_fft_alloc_twiddles(nfft, mem, lenmem, NULL); return opus_fft_alloc_twiddles(nfft, mem, lenmem, NULL, arch);
} }
void opus_fft_free(const kiss_fft_state *cfg) 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) if (cfg)
{ {
opus_fft_free_arch((kiss_fft_state *)cfg, arch);
opus_free((opus_int16*)cfg->bitrev); opus_free((opus_int16*)cfg->bitrev);
if (cfg->shift < 0) if (cfg->shift < 0)
opus_free((kiss_twiddle_cpx*)cfg->twiddles); opus_free((kiss_twiddle_cpx*)cfg->twiddles);
@ -551,8 +566,7 @@ void opus_fft_impl(const kiss_fft_state *st,kiss_fft_cpx *fout)
} }
} }
#if 0 void opus_fft_c(const kiss_fft_state *st,const kiss_fft_cpx *fin,kiss_fft_cpx *fout)
void opus_fft(const kiss_fft_state *st,const kiss_fft_cpx *fin,kiss_fft_cpx *fout)
{ {
int i; int i;
opus_val16 scale; opus_val16 scale;
@ -573,11 +587,9 @@ void opus_fft(const kiss_fft_state *st,const kiss_fft_cpx *fin,kiss_fft_cpx *fou
} }
opus_fft_impl(st, fout); opus_fft_impl(st, fout);
} }
#endif
#ifdef TEST_UNIT_DFT_C void opus_ifft_c(const kiss_fft_state *st,const kiss_fft_cpx *fin,kiss_fft_cpx *fout)
void opus_ifft(const kiss_fft_state *st,const kiss_fft_cpx *fin,kiss_fft_cpx *fout)
{ {
int i; int i;
celt_assert2 (fin != fout, "In-place FFT not supported"); celt_assert2 (fin != fout, "In-place FFT not supported");
@ -590,4 +602,3 @@ void opus_ifft(const kiss_fft_state *st,const kiss_fft_cpx *fin,kiss_fft_cpx *fo
for (i=0;i<st->nfft;i++) for (i=0;i<st->nfft;i++)
fout[i].i = -fout[i].i; fout[i].i = -fout[i].i;
} }
#endif

View file

@ -32,6 +32,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <math.h> #include <math.h>
#include "arch.h" #include "arch.h"
#include "cpu_support.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@ -77,6 +78,11 @@ typedef struct {
4*4*4*2 4*4*4*2
*/ */
typedef struct arch_fft_state{
int is_supported;
void *priv;
} arch_fft_state;
typedef struct kiss_fft_state{ typedef struct kiss_fft_state{
int nfft; int nfft;
opus_val16 scale; opus_val16 scale;
@ -87,8 +93,13 @@ typedef struct kiss_fft_state{
opus_int16 factors[2*MAXFACTORS]; opus_int16 factors[2*MAXFACTORS];
const opus_int16 *bitrev; const opus_int16 *bitrev;
const kiss_twiddle_cpx *twiddles; const kiss_twiddle_cpx *twiddles;
arch_fft_state *arch_fft;
} kiss_fft_state; } kiss_fft_state;
#if defined(HAVE_ARM_NE10)
#include "arm/fft_arm.h"
#endif
/*typedef struct kiss_fft_state* kiss_fft_cfg;*/ /*typedef struct kiss_fft_state* kiss_fft_cfg;*/
/** /**
@ -114,9 +125,9 @@ typedef struct kiss_fft_state{
* buffer size in *lenmem. * buffer size in *lenmem.
* */ * */
kiss_fft_state *opus_fft_alloc_twiddles(int nfft,void * mem,size_t * lenmem, const kiss_fft_state *base); kiss_fft_state *opus_fft_alloc_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); kiss_fft_state *opus_fft_alloc(int nfft,void * mem,size_t * lenmem, int arch);
/** /**
* opus_fft(cfg,in_out_buf) * opus_fft(cfg,in_out_buf)
@ -128,13 +139,59 @@ kiss_fft_state *opus_fft_alloc(int nfft,void * mem,size_t * lenmem);
* Note that each element is complex and can be accessed like * Note that each element is complex and can be accessed like
f[k].r and f[k].i f[k].r and f[k].i
* */ * */
void opus_fft(const kiss_fft_state *cfg,const kiss_fft_cpx *fin,kiss_fft_cpx *fout); void opus_fft_c(const kiss_fft_state *cfg,const kiss_fft_cpx *fin,kiss_fft_cpx *fout);
void opus_ifft(const kiss_fft_state *cfg,const kiss_fft_cpx *fin,kiss_fft_cpx *fout); void opus_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); void opus_fft_impl(const kiss_fft_state *st,kiss_fft_cpx *fout);
void opus_ifft_impl(const kiss_fft_state *st,kiss_fft_cpx *fout); void opus_ifft_impl(const kiss_fft_state *st,kiss_fft_cpx *fout);
void opus_fft_free(const kiss_fft_state *cfg); 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) */
#ifdef __cplusplus #ifdef __cplusplus
} }

View file

@ -38,7 +38,8 @@
#include "mathops.h" #include "mathops.h"
/*Compute floor(sqrt(_val)) with exact arithmetic. /*Compute floor(sqrt(_val)) with exact arithmetic.
This has been tested on all possible 32-bit inputs.*/ _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 isqrt32(opus_uint32 _val){
unsigned b; unsigned b;
unsigned g; unsigned g;
@ -164,7 +165,7 @@ opus_val16 celt_cos_norm(opus_val32 x)
{ {
return _celt_cos_pi_2(EXTRACT16(x)); return _celt_cos_pi_2(EXTRACT16(x));
} else { } else {
return NEG32(_celt_cos_pi_2(EXTRACT16(65536-x))); return NEG16(_celt_cos_pi_2(EXTRACT16(65536-x)));
} }
} else { } else {
if (x&0x0000ffff) if (x&0x0000ffff)
@ -182,7 +183,7 @@ opus_val32 celt_rcp(opus_val32 x)
int i; int i;
opus_val16 n; opus_val16 n;
opus_val16 r; opus_val16 r;
celt_assert2(x>0, "celt_rcp() only defined for positive values"); celt_sig_assert(x>0);
i = celt_ilog2(x); i = celt_ilog2(x);
/* n is Q15 with range [0,1). */ /* n is Q15 with range [0,1). */
n = VSHR32(x,i-15)-32768; n = VSHR32(x,i-15)-32768;

View file

@ -38,11 +38,48 @@
#include "entcode.h" #include "entcode.h"
#include "os_support.h" #include "os_support.h"
#define PI 3.141592653f
#ifndef ABS
#define ABS(a)(((a) < 0) ? - (a) :(a))
#endif
/* Multiplies two 16-bit fractional values. Bit-exactness of this macro is important */ /* 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) #define FRAC_MUL16(a,b) ((16384+((opus_int32)(opus_int16)(a)*(opus_int16)(b)))>>15)
unsigned isqrt32(opus_uint32 _val); 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 #ifndef OVERRIDE_CELT_MAXABS16
static OPUS_INLINE opus_val32 celt_maxabs16(const opus_val16 *x, int len) static OPUS_INLINE opus_val32 celt_maxabs16(const opus_val16 *x, int len)
{ {
@ -80,7 +117,6 @@ static OPUS_INLINE opus_val32 celt_maxabs32(const opus_val32 *x, int len)
#ifndef FIXED_POINT #ifndef FIXED_POINT
#define PI 3.141592653f
#define celt_sqrt(x) ((float)sqrt(x)) #define celt_sqrt(x) ((float)sqrt(x))
#define celt_rsqrt(x) (1.f/celt_sqrt(x)) #define celt_rsqrt(x) (1.f/celt_sqrt(x))
#define celt_rsqrt_norm(x) (celt_rsqrt(x)) #define celt_rsqrt_norm(x) (celt_rsqrt(x))
@ -147,7 +183,7 @@ static OPUS_INLINE float celt_exp2(float x)
/** Integer log in base2. Undefined for zero and negative numbers */ /** Integer log in base2. Undefined for zero and negative numbers */
static OPUS_INLINE opus_int16 celt_ilog2(opus_int32 x) static OPUS_INLINE opus_int16 celt_ilog2(opus_int32 x)
{ {
celt_assert2(x>0, "celt_ilog2() only defined for strictly positive numbers"); celt_sig_assert(x>0);
return EC_ILOG(x)-1; return EC_ILOG(x)-1;
} }
#endif #endif

View file

@ -60,7 +60,7 @@
#ifdef CUSTOM_MODES #ifdef CUSTOM_MODES
int clt_mdct_init(mdct_lookup *l,int N, int maxshift) int clt_mdct_init(mdct_lookup *l,int N, int maxshift, int arch)
{ {
int i; int i;
kiss_twiddle_scalar *trig; kiss_twiddle_scalar *trig;
@ -71,9 +71,9 @@ int clt_mdct_init(mdct_lookup *l,int N, int maxshift)
for (i=0;i<=maxshift;i++) for (i=0;i<=maxshift;i++)
{ {
if (i==0) if (i==0)
l->kfft[i] = opus_fft_alloc(N>>2>>i, 0, 0); l->kfft[i] = opus_fft_alloc(N>>2>>i, 0, 0, arch);
else else
l->kfft[i] = opus_fft_alloc_twiddles(N>>2>>i, 0, 0, l->kfft[0]); l->kfft[i] = opus_fft_alloc_twiddles(N>>2>>i, 0, 0, l->kfft[0], arch);
#ifndef ENABLE_TI_DSPLIB55 #ifndef ENABLE_TI_DSPLIB55
if (l->kfft[i]==NULL) if (l->kfft[i]==NULL)
return 0; return 0;
@ -104,21 +104,20 @@ int clt_mdct_init(mdct_lookup *l,int N, int maxshift)
return 1; return 1;
} }
void clt_mdct_clear(mdct_lookup *l) void clt_mdct_clear(mdct_lookup *l, int arch)
{ {
int i; int i;
for (i=0;i<=l->maxshift;i++) for (i=0;i<=l->maxshift;i++)
opus_fft_free(l->kfft[i]); opus_fft_free(l->kfft[i], arch);
opus_free((kiss_twiddle_scalar*)l->trig); opus_free((kiss_twiddle_scalar*)l->trig);
} }
#endif /* CUSTOM_MODES */ #endif /* CUSTOM_MODES */
#if 0
/* Forward MDCT trashes the input array */ /* Forward MDCT trashes the input array */
#ifndef OVERRIDE_clt_mdct_forward #ifndef OVERRIDE_clt_mdct_forward
void clt_mdct_forward(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_scalar * OPUS_RESTRICT out, void clt_mdct_forward_c(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_scalar * OPUS_RESTRICT out,
const opus_val16 *window, int overlap, int shift, int stride) const opus_val16 *window, int overlap, int shift, int stride, int arch)
{ {
int i; int i;
int N, N2, N4; int N, N2, N4;
@ -133,6 +132,7 @@ void clt_mdct_forward(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_scalar
int scale_shift = st->scale_shift-1; int scale_shift = st->scale_shift-1;
#endif #endif
SAVE_STACK; SAVE_STACK;
(void)arch;
scale = st->scale; scale = st->scale;
N = l->n; N = l->n;
@ -237,15 +237,15 @@ void clt_mdct_forward(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_scalar
RESTORE_STACK; RESTORE_STACK;
} }
#endif /* OVERRIDE_clt_mdct_forward */ #endif /* OVERRIDE_clt_mdct_forward */
#endif
#ifndef OVERRIDE_clt_mdct_backward #ifndef OVERRIDE_clt_mdct_backward
void clt_mdct_backward(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_scalar * OPUS_RESTRICT out, void clt_mdct_backward_c(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_scalar * OPUS_RESTRICT out,
const opus_val16 * OPUS_RESTRICT window, int overlap, int shift, int stride) const opus_val16 * OPUS_RESTRICT window, int overlap, int shift, int stride, int arch)
{ {
int i; int i;
int N, N2, N4; int N, N2, N4;
const kiss_twiddle_scalar *trig; const kiss_twiddle_scalar *trig;
(void) arch;
N = l->n; N = l->n;
trig = l->trig; trig = l->trig;
@ -270,8 +270,8 @@ void clt_mdct_backward(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_scala
int rev; int rev;
kiss_fft_scalar yr, yi; kiss_fft_scalar yr, yi;
rev = *bitrev++; rev = *bitrev++;
yr = S_MUL(*xp2, t[i]) + S_MUL(*xp1, t[N4+i]); yr = ADD32_ovflw(S_MUL(*xp2, t[i]), S_MUL(*xp1, t[N4+i]));
yi = S_MUL(*xp1, t[i]) - S_MUL(*xp2, t[N4+i]); yi = SUB32_ovflw(S_MUL(*xp1, t[i]), S_MUL(*xp2, t[N4+i]));
/* We swap real and imag because we use an FFT instead of an IFFT. */ /* We swap real and imag because we use an FFT instead of an IFFT. */
yp[2*rev+1] = yr; yp[2*rev+1] = yr;
yp[2*rev] = yi; yp[2*rev] = yi;
@ -301,8 +301,8 @@ void clt_mdct_backward(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_scala
t0 = t[i]; t0 = t[i];
t1 = t[N4+i]; t1 = t[N4+i];
/* We'd scale up by 2 here, but instead it's done when mixing the windows */ /* We'd scale up by 2 here, but instead it's done when mixing the windows */
yr = S_MUL(re,t0) + S_MUL(im,t1); yr = ADD32_ovflw(S_MUL(re,t0), S_MUL(im,t1));
yi = S_MUL(re,t1) - S_MUL(im,t0); yi = SUB32_ovflw(S_MUL(re,t1), S_MUL(im,t0));
/* We swap real and imag because we're using an FFT instead of an IFFT. */ /* We swap real and imag because we're using an FFT instead of an IFFT. */
re = yp1[1]; re = yp1[1];
im = yp1[0]; im = yp1[0];
@ -312,8 +312,8 @@ void clt_mdct_backward(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_scala
t0 = t[(N4-i-1)]; t0 = t[(N4-i-1)];
t1 = t[(N2-i-1)]; t1 = t[(N2-i-1)];
/* We'd scale up by 2 here, but instead it's done when mixing the windows */ /* We'd scale up by 2 here, but instead it's done when mixing the windows */
yr = S_MUL(re,t0) + S_MUL(im,t1); yr = ADD32_ovflw(S_MUL(re,t0), S_MUL(im,t1));
yi = S_MUL(re,t1) - S_MUL(im,t0); yi = SUB32_ovflw(S_MUL(re,t1), S_MUL(im,t0));
yp1[0] = yr; yp1[0] = yr;
yp0[1] = yi; yp0[1] = yi;
yp0 += 2; yp0 += 2;
@ -333,8 +333,8 @@ void clt_mdct_backward(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_scala
kiss_fft_scalar x1, x2; kiss_fft_scalar x1, x2;
x1 = *xp1; x1 = *xp1;
x2 = *yp1; x2 = *yp1;
*yp1++ = MULT16_32_Q15(*wp2, x2) - MULT16_32_Q15(*wp1, x1); *yp1++ = SUB32_ovflw(MULT16_32_Q15(*wp2, x2), MULT16_32_Q15(*wp1, x1));
*xp1-- = MULT16_32_Q15(*wp1, x2) + MULT16_32_Q15(*wp2, x1); *xp1-- = ADD32_ovflw(MULT16_32_Q15(*wp1, x2), MULT16_32_Q15(*wp2, x1));
wp1++; wp1++;
wp2--; wp2--;
} }

View file

@ -53,18 +53,60 @@ typedef struct {
const kiss_twiddle_scalar * OPUS_RESTRICT trig; const kiss_twiddle_scalar * OPUS_RESTRICT trig;
} mdct_lookup; } mdct_lookup;
int clt_mdct_init(mdct_lookup *l,int N, int maxshift); #if defined(HAVE_ARM_NE10)
void clt_mdct_clear(mdct_lookup *l); #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 */ /** Compute a forward MDCT and scale by 4/N, trashes the input array */
void clt_mdct_forward(const mdct_lookup *l, kiss_fft_scalar *in, void clt_mdct_forward_c(const mdct_lookup *l, kiss_fft_scalar *in,
kiss_fft_scalar * OPUS_RESTRICT out, kiss_fft_scalar * OPUS_RESTRICT out,
const opus_val16 *window, int overlap, int shift, int stride); const opus_val16 *window, int overlap,
int shift, int stride, int arch);
/** Compute a backward MDCT (no scaling) and performs weighted overlap-add /** Compute a backward MDCT (no scaling) and performs weighted overlap-add
(scales implicitly by 1/2) */ (scales implicitly by 1/2) */
void clt_mdct_backward(const mdct_lookup *l, kiss_fft_scalar *in, void clt_mdct_backward_c(const mdct_lookup *l, kiss_fft_scalar *in,
kiss_fft_scalar * OPUS_RESTRICT out, kiss_fft_scalar * OPUS_RESTRICT out,
const opus_val16 * OPUS_RESTRICT window, int overlap, int shift, int stride); const opus_val16 * 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 opus_val16 *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 opus_val16 *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 #endif

View file

@ -0,0 +1,151 @@
/* 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.
*/
#ifndef __CELT_MIPSR1_H__
#define __CELT_MIPSR1_H__
#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"
#define 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 opus_val16 *window, int overlap, int arch)
{
int i;
opus_val32 x0, x1, x2, x3, x4;
(void)arch;
/* printf ("%d %d %f %f\n", T0, T1, g0, g1); */
opus_val16 g00, g01, g02, g10, g11, g12;
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)}};
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;
}
g00 = MULT16_16_P15(g0, gains[tapset0][0]);
g01 = MULT16_16_P15(g0, gains[tapset0][1]);
g02 = MULT16_16_P15(g0, gains[tapset0][2]);
g10 = MULT16_16_P15(g1, gains[tapset1][0]);
g11 = MULT16_16_P15(g1, gains[tapset1][1]);
g12 = MULT16_16_P15(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++)
{
opus_val16 f;
opus_val32 res;
f = MULT16_16_Q15(window[i],window[i]);
x0= x[i-T1+2];
asm volatile("MULT $ac1, %0, %1" : : "r" ((int)MULT16_16_Q15((Q15ONE-f),g00)), "r" ((int)x[i-T0]));
asm volatile("MADD $ac1, %0, %1" : : "r" ((int)MULT16_16_Q15((Q15ONE-f),g01)), "r" ((int)ADD32(x[i-T0-1],x[i-T0+1])));
asm volatile("MADD $ac1, %0, %1" : : "r" ((int)MULT16_16_Q15((Q15ONE-f),g02)), "r" ((int)ADD32(x[i-T0-2],x[i-T0+2])));
asm volatile("MADD $ac1, %0, %1" : : "r" ((int)MULT16_16_Q15(f,g10)), "r" ((int)x2));
asm volatile("MADD $ac1, %0, %1" : : "r" ((int)MULT16_16_Q15(f,g11)), "r" ((int)ADD32(x3,x1)));
asm volatile("MADD $ac1, %0, %1" : : "r" ((int)MULT16_16_Q15(f,g12)), "r" ((int)ADD32(x4,x0)));
asm volatile("EXTR.W %0,$ac1, %1" : "=r" (res): "i" (15));
y[i] = x[i] + res;
x4=x3;
x3=x2;
x2=x1;
x1=x0;
}
x4 = x[i-T1-2];
x3 = x[i-T1-1];
x2 = x[i-T1];
x1 = x[i-T1+1];
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;
}
for (i=overlap;i<N;i++)
{
opus_val32 res;
x0=x[i-T1+2];
asm volatile("MULT $ac1, %0, %1" : : "r" ((int)g10), "r" ((int)x2));
asm volatile("MADD $ac1, %0, %1" : : "r" ((int)g11), "r" ((int)ADD32(x3,x1)));
asm volatile("MADD $ac1, %0, %1" : : "r" ((int)g12), "r" ((int)ADD32(x4,x0)));
asm volatile("EXTR.W %0,$ac1, %1" : "=r" (res): "i" (15));
y[i] = x[i] + res;
x4=x3;
x3=x2;
x2=x1;
x1=x0;
}
}
#endif /* __CELT_MIPSR1_H__ */

View file

@ -0,0 +1,126 @@
/* 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 CELT_FIXED_GENERIC_MIPSR1_H
#define CELT_FIXED_GENERIC_MIPSR1_H
#undef MULT16_32_Q15_ADD
static inline int MULT16_32_Q15_ADD(int a, int b, int c, int d) {
int m;
asm volatile("MULT $ac1, %0, %1" : : "r" ((int)a), "r" ((int)b));
asm volatile("madd $ac1, %0, %1" : : "r" ((int)c), "r" ((int)d));
asm volatile("EXTR.W %0,$ac1, %1" : "=r" (m): "i" (15));
return m;
}
#undef MULT16_32_Q15_SUB
static inline int MULT16_32_Q15_SUB(int a, int b, int c, int d) {
int m;
asm volatile("MULT $ac1, %0, %1" : : "r" ((int)a), "r" ((int)b));
asm volatile("msub $ac1, %0, %1" : : "r" ((int)c), "r" ((int)d));
asm volatile("EXTR.W %0,$ac1, %1" : "=r" (m): "i" (15));
return m;
}
#undef MULT16_16_Q15_ADD
static inline int MULT16_16_Q15_ADD(int a, int b, int c, int d) {
int m;
asm volatile("MULT $ac1, %0, %1" : : "r" ((int)a), "r" ((int)b));
asm volatile("madd $ac1, %0, %1" : : "r" ((int)c), "r" ((int)d));
asm volatile("EXTR.W %0,$ac1, %1" : "=r" (m): "i" (15));
return m;
}
#undef MULT16_16_Q15_SUB
static inline int MULT16_16_Q15_SUB(int a, int b, int c, int d) {
int m;
asm volatile("MULT $ac1, %0, %1" : : "r" ((int)a), "r" ((int)b));
asm volatile("msub $ac1, %0, %1" : : "r" ((int)c), "r" ((int)d));
asm volatile("EXTR.W %0,$ac1, %1" : "=r" (m): "i" (15));
return m;
}
#undef MULT16_32_Q16
static inline int MULT16_32_Q16(int a, int b)
{
int c;
asm volatile("MULT $ac1,%0, %1" : : "r" (a), "r" (b));
asm volatile("EXTR.W %0,$ac1, %1" : "=r" (c): "i" (16));
return c;
}
#undef MULT16_32_P16
static inline int MULT16_32_P16(int a, int b)
{
int c;
asm volatile("MULT $ac1, %0, %1" : : "r" (a), "r" (b));
asm volatile("EXTR_R.W %0,$ac1, %1" : "=r" (c): "i" (16));
return c;
}
#undef MULT16_32_Q15
static inline int MULT16_32_Q15(int a, int b)
{
int c;
asm volatile("MULT $ac1, %0, %1" : : "r" (a), "r" (b));
asm volatile("EXTR.W %0,$ac1, %1" : "=r" (c): "i" (15));
return c;
}
#undef MULT32_32_Q31
static inline int MULT32_32_Q31(int a, int b)
{
int r;
asm volatile("MULT $ac1, %0, %1" : : "r" (a), "r" (b));
asm volatile("EXTR.W %0,$ac1, %1" : "=r" (r): "i" (31));
return r;
}
#undef PSHR32
static inline int PSHR32(int a, int shift)
{
int r;
asm volatile ("SHRAV_R.W %0, %1, %2" :"=r" (r): "r" (a), "r" (shift));
return r;
}
#undef MULT16_16_P15
static inline int MULT16_16_P15(int a, int b)
{
int r;
asm volatile ("mul %0, %1, %2" :"=r" (r): "r" (a), "r" (b));
asm volatile ("SHRA_R.W %0, %1, %2" : "+r" (r): "0" (r), "i"(15));
return r;
}
#endif /* CELT_FIXED_GENERIC_MIPSR1_H */

View file

@ -0,0 +1,167 @@
/*Copyright (c) 2013, Xiph.Org Foundation and contributors.
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_MIPSR1_H
#define KISS_FFT_MIPSR1_H
#if !defined(KISS_FFT_GUTS_H)
#error "This file should only be included from _kiss_fft_guts.h"
#endif
#ifdef FIXED_POINT
#define S_MUL_ADD(a, b, c, d) (S_MUL(a,b)+S_MUL(c,d))
#define S_MUL_SUB(a, b, c, d) (S_MUL(a,b)-S_MUL(c,d))
#undef S_MUL_ADD
static inline int S_MUL_ADD(int a, int b, int c, int d) {
int m;
asm volatile("MULT $ac1, %0, %1" : : "r" ((int)a), "r" ((int)b));
asm volatile("madd $ac1, %0, %1" : : "r" ((int)c), "r" ((int)d));
asm volatile("EXTR.W %0,$ac1, %1" : "=r" (m): "i" (15));
return m;
}
#undef S_MUL_SUB
static inline int S_MUL_SUB(int a, int b, int c, int d) {
int m;
asm volatile("MULT $ac1, %0, %1" : : "r" ((int)a), "r" ((int)b));
asm volatile("msub $ac1, %0, %1" : : "r" ((int)c), "r" ((int)d));
asm volatile("EXTR.W %0,$ac1, %1" : "=r" (m): "i" (15));
return m;
}
#undef C_MUL
# define C_MUL(m,a,b) (m=C_MUL_fun(a,b))
static inline kiss_fft_cpx C_MUL_fun(kiss_fft_cpx a, kiss_twiddle_cpx b) {
kiss_fft_cpx m;
asm volatile("MULT $ac1, %0, %1" : : "r" ((int)a.r), "r" ((int)b.r));
asm volatile("msub $ac1, %0, %1" : : "r" ((int)a.i), "r" ((int)b.i));
asm volatile("EXTR.W %0,$ac1, %1" : "=r" (m.r): "i" (15));
asm volatile("MULT $ac1, %0, %1" : : "r" ((int)a.r), "r" ((int)b.i));
asm volatile("madd $ac1, %0, %1" : : "r" ((int)a.i), "r" ((int)b.r));
asm volatile("EXTR.W %0,$ac1, %1" : "=r" (m.i): "i" (15));
return m;
}
#undef C_MULC
# define C_MULC(m,a,b) (m=C_MULC_fun(a,b))
static inline kiss_fft_cpx C_MULC_fun(kiss_fft_cpx a, kiss_twiddle_cpx b) {
kiss_fft_cpx m;
asm volatile("MULT $ac1, %0, %1" : : "r" ((int)a.r), "r" ((int)b.r));
asm volatile("madd $ac1, %0, %1" : : "r" ((int)a.i), "r" ((int)b.i));
asm volatile("EXTR.W %0,$ac1, %1" : "=r" (m.r): "i" (15));
asm volatile("MULT $ac1, %0, %1" : : "r" ((int)a.i), "r" ((int)b.r));
asm volatile("msub $ac1, %0, %1" : : "r" ((int)a.r), "r" ((int)b.i));
asm volatile("EXTR.W %0,$ac1, %1" : "=r" (m.i): "i" (15));
return m;
}
#endif /* FIXED_POINT */
#define 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 = 10126;
ya.i = -31164;
yb.r = -26510;
yb.i = -19261;
#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 += scratch[7].r + scratch[8].r;
Fout0->i += scratch[7].i + scratch[8].i;
scratch[5].r = scratch[0].r + S_MUL_ADD(scratch[7].r,ya.r,scratch[8].r,yb.r);
scratch[5].i = scratch[0].i + S_MUL_ADD(scratch[7].i,ya.r,scratch[8].i,yb.r);
scratch[6].r = S_MUL_ADD(scratch[10].i,ya.i,scratch[9].i,yb.i);
scratch[6].i = -S_MUL_ADD(scratch[10].r,ya.i,scratch[9].r,yb.i);
C_SUB(*Fout1,scratch[5],scratch[6]);
C_ADD(*Fout4,scratch[5],scratch[6]);
scratch[11].r = scratch[0].r + S_MUL_ADD(scratch[7].r,yb.r,scratch[8].r,ya.r);
scratch[11].i = scratch[0].i + S_MUL_ADD(scratch[7].i,yb.r,scratch[8].i,ya.r);
scratch[12].r = S_MUL_SUB(scratch[9].i,ya.i,scratch[10].i,yb.i);
scratch[12].i = S_MUL_SUB(scratch[10].r,yb.i,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 /* KISS_FFT_MIPSR1_H */

View file

@ -0,0 +1,288 @@
/* 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_MIPSR1_H__
#define __MDCT_MIPSR1_H__
#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"
/* Forward MDCT trashes the input array */
#define OVERRIDE_clt_mdct_forward
void clt_mdct_forward(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_scalar * OPUS_RESTRICT out,
const opus_val16 *window, int overlap, int shift, int stride, int 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;
opus_val16 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
(void)arch;
SAVE_STACK;
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 opus_val16 * OPUS_RESTRICT wp1 = window+(overlap>>1);
const opus_val16 * 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_ADD(*wp2, xp1[N2],*wp1,*xp2);
*yp++ = S_MUL_SUB(*wp1, *xp1,*wp2, xp2[-N2]);
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_SUB(*wp2, *xp2, *wp1, xp1[-N2]);
*yp++ = S_MUL_ADD(*wp2, *xp1, *wp1, xp2[N2]);
xp1+=2;
xp2-=2;
wp1+=2;
wp2-=2;
}
}
/* Pre-rotation */
{
kiss_fft_scalar * OPUS_RESTRICT yp = f;
const kiss_twiddle_scalar *t = &trig[0];
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_SUB(re,t0,im,t1);
yi = S_MUL_ADD(im,t0,re,t1);
yc.r = yr;
yc.i = yi;
yc.r = PSHR32(MULT16_32_Q16(scale, yc.r), scale_shift);
yc.i = PSHR32(MULT16_32_Q16(scale, yc.i), scale_shift);
f2[st->bitrev[i]] = yc;
}
}
/* N/4 complex FFT, does not downscale anymore */
opus_fft_impl(st, f2);
/* 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;
yr = S_MUL_SUB(fp->i,t[N4+i] , fp->r,t[i]);
yi = S_MUL_ADD(fp->r,t[N4+i] ,fp->i,t[i]);
*yp1 = yr;
*yp2 = yi;
fp++;
yp1 += 2*stride;
yp2 -= 2*stride;
}
}
RESTORE_STACK;
}
#define OVERRIDE_clt_mdct_backward
void clt_mdct_backward(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_scalar * OPUS_RESTRICT out,
const opus_val16 * OPUS_RESTRICT window, int overlap, int shift, int stride, int arch)
{
int i;
int N, N2, N4;
const kiss_twiddle_scalar *trig;
(void)arch;
N = l->n;
trig = l->trig;
for (i=0;i<shift;i++)
{
N >>= 1;
trig += N;
}
N2 = N>>1;
N4 = N>>2;
/* 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;
rev = *bitrev++;
yr = S_MUL_ADD(*xp2, t[i] , *xp1, t[N4+i]);
yi = S_MUL_SUB(*xp1, t[i] , *xp2, 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)));
/* Post-rotate and de-shuffle from both ends of the buffer at once to make
it in-place. */
{
kiss_fft_scalar * OPUS_RESTRICT yp0 = out+(overlap>>1);
kiss_fft_scalar * OPUS_RESTRICT 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 = S_MUL_ADD(re,t0 , im,t1);
yi = S_MUL_SUB(re,t1 , im,t0);
/* 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 = S_MUL_ADD(re,t0,im,t1);
yi = S_MUL_SUB(re,t1,im,t0);
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 opus_val16 * OPUS_RESTRICT wp1 = window;
const opus_val16 * OPUS_RESTRICT wp2 = window+overlap-1;
for(i = 0; i < overlap/2; i++)
{
kiss_fft_scalar x1, x2;
x1 = *xp1;
x2 = *yp1;
*yp1++ = MULT16_32_Q15(*wp2, x2) - MULT16_32_Q15(*wp1, x1);
*xp1-- = MULT16_32_Q15(*wp1, x2) + MULT16_32_Q15(*wp2, x1);
wp1++;
wp2--;
}
}
}
#endif /* __MDCT_MIPSR1_H__ */

View file

@ -0,0 +1,161 @@
/* 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_MIPSR1_H
#define PITCH_MIPSR1_H
#define OVERRIDE_DUAL_INNER_PROD
static inline void dual_inner_prod(const opus_val16 *x, const opus_val16 *y01, const opus_val16 *y02,
int N, opus_val32 *xy1, opus_val32 *xy2, int arch)
{
int j;
opus_val32 xy01=0;
opus_val32 xy02=0;
(void)arch;
asm volatile("MULT $ac1, $0, $0");
asm volatile("MULT $ac2, $0, $0");
/* Compute the norm of X+Y and X-Y as |X|^2 + |Y|^2 +/- sum(xy) */
for (j=0;j<N;j++)
{
asm volatile("MADD $ac1, %0, %1" : : "r" ((int)x[j]), "r" ((int)y01[j]));
asm volatile("MADD $ac2, %0, %1" : : "r" ((int)x[j]), "r" ((int)y02[j]));
++j;
asm volatile("MADD $ac1, %0, %1" : : "r" ((int)x[j]), "r" ((int)y01[j]));
asm volatile("MADD $ac2, %0, %1" : : "r" ((int)x[j]), "r" ((int)y02[j]));
}
asm volatile ("mflo %0, $ac1": "=r"(xy01));
asm volatile ("mflo %0, $ac2": "=r"(xy02));
*xy1 = xy01;
*xy2 = xy02;
}
static inline void xcorr_kernel_mips(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;
opus_int64 sum_0, sum_1, sum_2, sum_3;
sum_0 = (opus_int64)sum[0];
sum_1 = (opus_int64)sum[1];
sum_2 = (opus_int64)sum[2];
sum_3 = (opus_int64)sum[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 = __builtin_mips_madd( sum_0, tmp, y_0);
sum_1 = __builtin_mips_madd( sum_1, tmp, y_1);
sum_2 = __builtin_mips_madd( sum_2, tmp, y_2);
sum_3 = __builtin_mips_madd( sum_3, tmp, y_3);
tmp=*x++;
y_0=*y++;
sum_0 = __builtin_mips_madd( sum_0, tmp, y_1 );
sum_1 = __builtin_mips_madd( sum_1, tmp, y_2 );
sum_2 = __builtin_mips_madd( sum_2, tmp, y_3);
sum_3 = __builtin_mips_madd( sum_3, tmp, y_0);
tmp=*x++;
y_1=*y++;
sum_0 = __builtin_mips_madd( sum_0, tmp, y_2 );
sum_1 = __builtin_mips_madd( sum_1, tmp, y_3 );
sum_2 = __builtin_mips_madd( sum_2, tmp, y_0);
sum_3 = __builtin_mips_madd( sum_3, tmp, y_1);
tmp=*x++;
y_2=*y++;
sum_0 = __builtin_mips_madd( sum_0, tmp, y_3 );
sum_1 = __builtin_mips_madd( sum_1, tmp, y_0 );
sum_2 = __builtin_mips_madd( sum_2, tmp, y_1);
sum_3 = __builtin_mips_madd( sum_3, tmp, y_2);
}
if (j++<len)
{
opus_val16 tmp = *x++;
y_3=*y++;
sum_0 = __builtin_mips_madd( sum_0, tmp, y_0 );
sum_1 = __builtin_mips_madd( sum_1, tmp, y_1 );
sum_2 = __builtin_mips_madd( sum_2, tmp, y_2);
sum_3 = __builtin_mips_madd( sum_3, tmp, y_3);
}
if (j++<len)
{
opus_val16 tmp=*x++;
y_0=*y++;
sum_0 = __builtin_mips_madd( sum_0, tmp, y_1 );
sum_1 = __builtin_mips_madd( sum_1, tmp, y_2 );
sum_2 = __builtin_mips_madd( sum_2, tmp, y_3);
sum_3 = __builtin_mips_madd( sum_3, tmp, y_0);
}
if (j<len)
{
opus_val16 tmp=*x++;
y_1=*y++;
sum_0 = __builtin_mips_madd( sum_0, tmp, y_2 );
sum_1 = __builtin_mips_madd( sum_1, tmp, y_3 );
sum_2 = __builtin_mips_madd( sum_2, tmp, y_0);
sum_3 = __builtin_mips_madd( sum_3, tmp, y_1);
}
sum[0] = (opus_val32)sum_0;
sum[1] = (opus_val32)sum_1;
sum[2] = (opus_val32)sum_2;
sum[3] = (opus_val32)sum_3;
}
#define OVERRIDE_XCORR_KERNEL
#define xcorr_kernel(x, y, sum, len, arch) \
((void)(arch), xcorr_kernel_mips(x, y, sum, len))
#endif /* PITCH_MIPSR1_H */

View file

@ -0,0 +1,122 @@
/* 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 __VQ_MIPSR1_H__
#define __VQ_MIPSR1_H__
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "mathops.h"
#include "arch.h"
static void renormalise_vector_mips(celt_norm *X, int N, opus_val16 gain, int arch);
#define 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);
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));
}
}
#define OVERRIDE_renormalise_vector
#define renormalise_vector(X, N, gain, arch) \
(renormalise_vector_mips(X, N, gain, arch))
void renormalise_vector_mips(celt_norm *X, int N, opus_val16 gain, int arch)
{
int i;
#ifdef FIXED_POINT
int k;
#endif
opus_val32 E = EPSILON;
opus_val16 g;
opus_val32 t;
celt_norm *xptr = X;
int X0, X1;
(void)arch;
asm volatile("mult $ac1, $0, $0");
asm volatile("MTLO %0, $ac1" : :"r" (E));
/*if(N %4)
printf("error");*/
for (i=0;i<N-2;i+=2)
{
X0 = (int)*xptr++;
asm volatile("MADD $ac1, %0, %1" : : "r" (X0), "r" (X0));
X1 = (int)*xptr++;
asm volatile("MADD $ac1, %0, %1" : : "r" (X1), "r" (X1));
}
for (;i<N;i++)
{
X0 = (int)*xptr++;
asm volatile("MADD $ac1, %0, %1" : : "r" (X0), "r" (X0));
}
asm volatile("MFLO %0, $ac1" : "=r" (E));
#ifdef FIXED_POINT
k = celt_ilog2(E)>>1;
#endif
t = VSHR32(E, 2*(k-7));
g = MULT16_16_P15(celt_rsqrt_norm(t),gain);
xptr = X;
for (i=0;i<N;i++)
{
*xptr = EXTRACT16(PSHR32(MULT16_16(g, *xptr), k+1));
xptr++;
}
/*return celt_sqrt(E);*/
}
#endif /* __VQ_MIPSR1_H__ */

View file

@ -37,6 +37,7 @@
#include "os_support.h" #include "os_support.h"
#include "stack_alloc.h" #include "stack_alloc.h"
#include "quant_bands.h" #include "quant_bands.h"
#include "cpu_support.h"
static const opus_int16 eband5ms[] = { 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 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 */
@ -229,6 +230,7 @@ CELTMode *opus_custom_mode_create(opus_int32 Fs, int frame_size, int *error)
opus_val16 *window; opus_val16 *window;
opus_int16 *logN; opus_int16 *logN;
int LM; int LM;
int arch = opus_select_arch();
ALLOC_STACK; ALLOC_STACK;
#if !defined(VAR_ARRAYS) && !defined(USE_ALLOCA) #if !defined(VAR_ARRAYS) && !defined(USE_ALLOCA)
if (global_stack==NULL) if (global_stack==NULL)
@ -389,7 +391,7 @@ CELTMode *opus_custom_mode_create(opus_int32 Fs, int frame_size, int *error)
compute_pulse_cache(mode, mode->maxLM); compute_pulse_cache(mode, mode->maxLM);
if (clt_mdct_init(&mode->mdct, 2*mode->shortMdctSize*mode->nbShortMdcts, if (clt_mdct_init(&mode->mdct, 2*mode->shortMdctSize*mode->nbShortMdcts,
mode->maxLM) == 0) mode->maxLM, arch) == 0)
goto failure; goto failure;
if (error) if (error)
@ -408,6 +410,8 @@ failure:
#ifdef CUSTOM_MODES #ifdef CUSTOM_MODES
void opus_custom_mode_destroy(CELTMode *mode) void opus_custom_mode_destroy(CELTMode *mode)
{ {
int arch = opus_select_arch();
if (mode == NULL) if (mode == NULL)
return; return;
#ifndef CUSTOM_MODES_ONLY #ifndef CUSTOM_MODES_ONLY
@ -423,7 +427,7 @@ void opus_custom_mode_destroy(CELTMode *mode)
} }
#endif /* CUSTOM_MODES_ONLY */ #endif /* CUSTOM_MODES_ONLY */
opus_free((opus_int16*)mode->eBands); opus_free((opus_int16*)mode->eBands);
opus_free((opus_int16*)mode->allocVectors); opus_free((unsigned char*)mode->allocVectors);
opus_free((opus_val16*)mode->window); opus_free((opus_val16*)mode->window);
opus_free((opus_int16*)mode->logN); opus_free((opus_int16*)mode->logN);
@ -431,7 +435,7 @@ void opus_custom_mode_destroy(CELTMode *mode)
opus_free((opus_int16*)mode->cache.index); opus_free((opus_int16*)mode->cache.index);
opus_free((unsigned char*)mode->cache.bits); opus_free((unsigned char*)mode->cache.bits);
opus_free((unsigned char*)mode->cache.caps); opus_free((unsigned char*)mode->cache.caps);
clt_mdct_clear(&mode->mdct); clt_mdct_clear(&mode->mdct, arch);
opus_free((CELTMode *)mode); opus_free((CELTMode *)mode);
} }

View file

@ -0,0 +1,210 @@
/* Copyright (c) 2007-2008 CSIRO
Copyright (c) 2007-2009 Xiph.Org Foundation
Written by Jean-Marc Valin */
/*
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "opus_custom.h"
#include "arch.h"
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#define MAX_PACKET 1275
int main(int argc, char *argv[])
{
int err;
char *inFile, *outFile;
FILE *fin, *fout;
OpusCustomMode *mode=NULL;
OpusCustomEncoder *enc;
OpusCustomDecoder *dec;
int len;
opus_int32 frame_size, channels, rate;
int bytes_per_packet;
unsigned char data[MAX_PACKET];
int complexity;
#if !(defined (FIXED_POINT) && !defined(CUSTOM_MODES)) && defined(RESYNTH)
int i;
double rmsd = 0;
#endif
int count = 0;
opus_int32 skip;
opus_int16 *in, *out;
if (argc != 9 && argc != 8 && argc != 7)
{
fprintf (stderr, "Usage: test_opus_custom <rate> <channels> <frame size> "
" <bytes per packet> [<complexity> [packet loss rate]] "
"<input> <output>\n");
return 1;
}
rate = (opus_int32)atol(argv[1]);
channels = atoi(argv[2]);
frame_size = atoi(argv[3]);
mode = opus_custom_mode_create(rate, frame_size, NULL);
if (mode == NULL)
{
fprintf(stderr, "failed to create a mode\n");
return 1;
}
bytes_per_packet = atoi(argv[4]);
if (bytes_per_packet < 0 || bytes_per_packet > MAX_PACKET)
{
fprintf (stderr, "bytes per packet must be between 0 and %d\n",
MAX_PACKET);
return 1;
}
inFile = argv[argc-2];
fin = fopen(inFile, "rb");
if (!fin)
{
fprintf (stderr, "Could not open input file %s\n", argv[argc-2]);
return 1;
}
outFile = argv[argc-1];
fout = fopen(outFile, "wb+");
if (!fout)
{
fprintf (stderr, "Could not open output file %s\n", argv[argc-1]);
fclose(fin);
return 1;
}
enc = opus_custom_encoder_create(mode, channels, &err);
if (err != 0)
{
fprintf(stderr, "Failed to create the encoder: %s\n", opus_strerror(err));
fclose(fin);
fclose(fout);
return 1;
}
dec = opus_custom_decoder_create(mode, channels, &err);
if (err != 0)
{
fprintf(stderr, "Failed to create the decoder: %s\n", opus_strerror(err));
fclose(fin);
fclose(fout);
return 1;
}
opus_custom_decoder_ctl(dec, OPUS_GET_LOOKAHEAD(&skip));
if (argc>7)
{
complexity=atoi(argv[5]);
opus_custom_encoder_ctl(enc,OPUS_SET_COMPLEXITY(complexity));
}
in = (opus_int16*)malloc(frame_size*channels*sizeof(opus_int16));
out = (opus_int16*)malloc(frame_size*channels*sizeof(opus_int16));
while (!feof(fin))
{
int ret;
err = fread(in, sizeof(short), frame_size*channels, fin);
if (feof(fin))
break;
len = opus_custom_encode(enc, in, frame_size, data, bytes_per_packet);
if (len <= 0)
fprintf (stderr, "opus_custom_encode() failed: %s\n", opus_strerror(len));
/* This is for simulating bit errors */
#if 0
int errors = 0;
int eid = 0;
/* This simulates random bit error */
for (i=0;i<len*8;i++)
{
if (rand()%atoi(argv[8])==0)
{
if (i<64)
{
errors++;
eid = i;
}
data[i/8] ^= 1<<(7-(i%8));
}
}
if (errors == 1)
data[eid/8] ^= 1<<(7-(eid%8));
else if (errors%2 == 1)
data[rand()%8] ^= 1<<rand()%8;
#endif
#if 1 /* Set to zero to use the encoder's output instead */
/* This is to simulate packet loss */
if (argc==9 && rand()%1000<atoi(argv[argc-3]))
/*if (errors && (errors%2==0))*/
ret = opus_custom_decode(dec, NULL, len, out, frame_size);
else
ret = opus_custom_decode(dec, data, len, out, frame_size);
if (ret < 0)
fprintf(stderr, "opus_custom_decode() failed: %s\n", opus_strerror(ret));
#else
for (i=0;i<ret*channels;i++)
out[i] = in[i];
#endif
#if !(defined (FIXED_POINT) && !defined(CUSTOM_MODES)) && defined(RESYNTH)
for (i=0;i<ret*channels;i++)
{
rmsd += (in[i]-out[i])*1.0*(in[i]-out[i]);
/*out[i] -= in[i];*/
}
#endif
count++;
fwrite(out+skip*channels, sizeof(short), (ret-skip)*channels, fout);
skip = 0;
}
PRINT_MIPS(stderr);
opus_custom_encoder_destroy(enc);
opus_custom_decoder_destroy(dec);
fclose(fin);
fclose(fout);
opus_custom_mode_destroy(mode);
free(in);
free(out);
#if !(defined (FIXED_POINT) && !defined(CUSTOM_MODES)) && defined(RESYNTH)
if (rmsd > 0)
{
rmsd = sqrt(rmsd/(1.0*frame_size*channels*count));
fprintf (stderr, "Error: encoder doesn't match decoder\n");
fprintf (stderr, "RMS mismatch is %f\n", rmsd);
return 1;
} else {
fprintf (stderr, "Encoder matches decoder!!\n");
}
#endif
return 0;
}

View file

@ -67,18 +67,18 @@ static OPUS_INLINE void opus_free (void *ptr)
} }
#endif #endif
/** Copy n bytes of memory from src to dst. The 0* term provides compile-time type checking */ /** Copy n elements from src to dst. The 0* term provides compile-time type checking */
#ifndef OVERRIDE_OPUS_COPY #ifndef OVERRIDE_OPUS_COPY
#define OPUS_COPY(dst, src, n) (memcpy((dst), (src), (n)*sizeof(*(dst)) + 0*((dst)-(src)) )) #define OPUS_COPY(dst, src, n) (memcpy((dst), (src), (n)*sizeof(*(dst)) + 0*((dst)-(src)) ))
#endif #endif
/** Copy n bytes of memory from src to dst, allowing overlapping regions. The 0* term /** Copy n elements from src to dst, allowing overlapping regions. The 0* term
provides compile-time type checking */ provides compile-time type checking */
#ifndef OVERRIDE_OPUS_MOVE #ifndef OVERRIDE_OPUS_MOVE
#define OPUS_MOVE(dst, src, n) (memmove((dst), (src), (n)*sizeof(*(dst)) + 0*((dst)-(src)) )) #define OPUS_MOVE(dst, src, n) (memmove((dst), (src), (n)*sizeof(*(dst)) + 0*((dst)-(src)) ))
#endif #endif
/** Set n elements of dst to zero, starting at address s */ /** Set n elements of dst to zero */
#ifndef OVERRIDE_OPUS_CLEAR #ifndef OVERRIDE_OPUS_CLEAR
#define OPUS_CLEAR(dst, n) (memset((dst), 0, (n)*sizeof(*(dst)))) #define OPUS_CLEAR(dst, n) (memset((dst), 0, (n)*sizeof(*(dst))))
#endif #endif

View file

@ -102,11 +102,9 @@ static void find_best_pitch(opus_val32 *xcorr, opus_val16 *y, int len,
} }
} }
static void celt_fir5(const opus_val16 *x, static void celt_fir5(opus_val16 *x,
const opus_val16 *num, const opus_val16 *num,
opus_val16 *y, int N)
int N,
opus_val16 *mem)
{ {
int i; int i;
opus_val16 num0, num1, num2, num3, num4; opus_val16 num0, num1, num2, num3, num4;
@ -116,11 +114,11 @@ static void celt_fir5(const opus_val16 *x,
num2=num[2]; num2=num[2];
num3=num[3]; num3=num[3];
num4=num[4]; num4=num[4];
mem0=mem[0]; mem0=0;
mem1=mem[1]; mem1=0;
mem2=mem[2]; mem2=0;
mem3=mem[3]; mem3=0;
mem4=mem[4]; mem4=0;
for (i=0;i<N;i++) for (i=0;i<N;i++)
{ {
opus_val32 sum = SHL32(EXTEND32(x[i]), SIG_SHIFT); opus_val32 sum = SHL32(EXTEND32(x[i]), SIG_SHIFT);
@ -134,13 +132,8 @@ static void celt_fir5(const opus_val16 *x,
mem2 = mem1; mem2 = mem1;
mem1 = mem0; mem1 = mem0;
mem0 = x[i]; mem0 = x[i];
y[i] = ROUND16(sum, SIG_SHIFT); x[i] = ROUND16(sum, SIG_SHIFT);
} }
mem[0]=mem0;
mem[1]=mem1;
mem[2]=mem2;
mem[3]=mem3;
mem[4]=mem4;
} }
@ -150,7 +143,7 @@ void pitch_downsample(celt_sig * OPUS_RESTRICT x[], opus_val16 * OPUS_RESTRICT x
int i; int i;
opus_val32 ac[5]; opus_val32 ac[5];
opus_val16 tmp=Q15ONE; opus_val16 tmp=Q15ONE;
opus_val16 lpc[4], mem[5]={0,0,0,0,0}; opus_val16 lpc[4];
opus_val16 lpc2[5]; opus_val16 lpc2[5];
opus_val16 c1 = QCONST16(.8f,15); opus_val16 c1 = QCONST16(.8f,15);
#ifdef FIXED_POINT #ifdef FIXED_POINT
@ -211,28 +204,33 @@ void pitch_downsample(celt_sig * OPUS_RESTRICT x[], opus_val16 * OPUS_RESTRICT x
lpc2[2] = lpc[2] + MULT16_16_Q15(c1,lpc[1]); lpc2[2] = lpc[2] + MULT16_16_Q15(c1,lpc[1]);
lpc2[3] = lpc[3] + MULT16_16_Q15(c1,lpc[2]); lpc2[3] = lpc[3] + MULT16_16_Q15(c1,lpc[2]);
lpc2[4] = MULT16_16_Q15(c1,lpc[3]); lpc2[4] = MULT16_16_Q15(c1,lpc[3]);
celt_fir5(x_lp, lpc2, x_lp, len>>1, mem); celt_fir5(x_lp, lpc2, len>>1);
} }
#if 0 /* This is a simple version of the pitch correlation that should work /* Pure C implementation. */
well on DSPs like Blackfin and TI C5x/C6x */
#ifdef FIXED_POINT #ifdef FIXED_POINT
opus_val32 opus_val32
#else #else
void void
#endif #endif
celt_pitch_xcorr(opus_val16 *x, opus_val16 *y, opus_val32 *xcorr, int len, int max_pitch) 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; int i, j;
#ifdef FIXED_POINT #ifdef FIXED_POINT
opus_val32 maxcorr=1; opus_val32 maxcorr=1;
#endif
#if !defined(OVERRIDE_PITCH_XCORR)
(void)arch;
#endif #endif
for (i=0;i<max_pitch;i++) for (i=0;i<max_pitch;i++)
{ {
opus_val32 sum = 0; opus_val32 sum = 0;
for (j=0;j<len;j++) for (j=0;j<len;j++)
sum = MAC16_16(sum, x[j],y[i+j]); sum = MAC16_16(sum, _x[j], _y[i+j]);
xcorr[i] = sum; xcorr[i] = sum;
#ifdef FIXED_POINT #ifdef FIXED_POINT
maxcorr = MAX32(maxcorr, sum); maxcorr = MAX32(maxcorr, sum);
@ -241,17 +239,8 @@ celt_pitch_xcorr(opus_val16 *x, opus_val16 *y, opus_val32 *xcorr, int len, int m
#ifdef FIXED_POINT #ifdef FIXED_POINT
return maxcorr; return maxcorr;
#endif #endif
}
#else /* Unrolled version of the pitch correlation -- runs faster on x86 and ARM */ #else /* Unrolled version of the pitch correlation -- runs faster on x86 and ARM */
#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 i; int i;
/*The EDSP version requires that max_pitch is at least 1, and that _x is /*The EDSP version requires that max_pitch is at least 1, and that _x is
32-bit aligned. 32-bit aligned.
@ -260,11 +249,11 @@ celt_pitch_xcorr_c(const opus_val16 *_x, const opus_val16 *_y, opus_val32 *xcorr
opus_val32 maxcorr=1; opus_val32 maxcorr=1;
#endif #endif
celt_assert(max_pitch>0); celt_assert(max_pitch>0);
celt_assert((((unsigned char *)_x-(unsigned char *)NULL)&3)==0); celt_sig_assert((((unsigned char *)_x-(unsigned char *)NULL)&3)==0);
for (i=0;i<max_pitch-3;i+=4) for (i=0;i<max_pitch-3;i+=4)
{ {
opus_val32 sum[4]={0,0,0,0}; opus_val32 sum[4]={0,0,0,0};
xcorr_kernel(_x, _y+i, sum, len); xcorr_kernel(_x, _y+i, sum, len, arch);
xcorr[i]=sum[0]; xcorr[i]=sum[0];
xcorr[i+1]=sum[1]; xcorr[i+1]=sum[1];
xcorr[i+2]=sum[2]; xcorr[i+2]=sum[2];
@ -280,7 +269,7 @@ celt_pitch_xcorr_c(const opus_val16 *_x, const opus_val16 *_y, opus_val32 *xcorr
for (;i<max_pitch;i++) for (;i<max_pitch;i++)
{ {
opus_val32 sum; opus_val32 sum;
sum = celt_inner_prod(_x, _y+i, len); sum = celt_inner_prod(_x, _y+i, len, arch);
xcorr[i] = sum; xcorr[i] = sum;
#ifdef FIXED_POINT #ifdef FIXED_POINT
maxcorr = MAX32(maxcorr, sum); maxcorr = MAX32(maxcorr, sum);
@ -289,9 +278,9 @@ celt_pitch_xcorr_c(const opus_val16 *_x, const opus_val16 *_y, opus_val32 *xcorr
#ifdef FIXED_POINT #ifdef FIXED_POINT
return maxcorr; return maxcorr;
#endif #endif
#endif
} }
#endif
void pitch_search(const opus_val16 * OPUS_RESTRICT x_lp, opus_val16 * OPUS_RESTRICT y, 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 len, int max_pitch, int *pitch, int arch)
{ {
@ -369,7 +358,7 @@ void pitch_search(const opus_val16 * OPUS_RESTRICT x_lp, opus_val16 * OPUS_RESTR
for (j=0;j<len>>1;j++) for (j=0;j<len>>1;j++)
sum += SHR32(MULT16_16(x_lp[j],y[i+j]), shift); sum += SHR32(MULT16_16(x_lp[j],y[i+j]), shift);
#else #else
sum = celt_inner_prod(x_lp, y+i, len>>1); sum = celt_inner_prod(x_lp, y+i, len>>1, arch);
#endif #endif
xcorr[i] = MAX32(-1, sum); xcorr[i] = MAX32(-1, sum);
#ifdef FIXED_POINT #ifdef FIXED_POINT
@ -403,10 +392,44 @@ void pitch_search(const opus_val16 * OPUS_RESTRICT x_lp, opus_val16 * OPUS_RESTR
RESTORE_STACK; RESTORE_STACK;
} }
#if 0 #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(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}; 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, opus_val16 remove_doubling(opus_val16 *x, int maxperiod, int minperiod,
int N, int *T0_, int prev_period, opus_val16 prev_gain) int N, int *T0_, int prev_period, opus_val16 prev_gain, int arch)
{ {
int k, i, T, T0; int k, i, T, T0;
opus_val16 g, g0; opus_val16 g, g0;
@ -431,7 +454,7 @@ opus_val16 remove_doubling(opus_val16 *x, int maxperiod, int minperiod,
T = T0 = *T0_; T = T0 = *T0_;
ALLOC(yy_lookup, maxperiod+1, opus_val32); ALLOC(yy_lookup, maxperiod+1, opus_val32);
dual_inner_prod(x, x, x-T0, N, &xx, &xy); dual_inner_prod(x, x, x-T0, N, &xx, &xy, arch);
yy_lookup[0] = xx; yy_lookup[0] = xx;
yy=xx; yy=xx;
for (i=1;i<=maxperiod;i++) for (i=1;i<=maxperiod;i++)
@ -442,18 +465,7 @@ opus_val16 remove_doubling(opus_val16 *x, int maxperiod, int minperiod,
yy = yy_lookup[T0]; yy = yy_lookup[T0];
best_xy = xy; best_xy = xy;
best_yy = yy; best_yy = yy;
#ifdef FIXED_POINT g = g0 = compute_pitch_gain(xy, xx, yy);
{
opus_val32 x2y2;
int sh, t;
x2y2 = 1+HALF32(MULT32_32_Q31(xx,yy));
sh = celt_ilog2(x2y2)>>1;
t = VSHR32(x2y2, 2*(sh-7));
g = g0 = VSHR32(MULT16_32_Q15(celt_rsqrt_norm(t), xy),sh+1);
}
#else
g = g0 = xy/celt_sqrt(1+xx*yy);
#endif
/* Look for any pitch at T/k */ /* Look for any pitch at T/k */
for (k=2;k<=15;k++) for (k=2;k<=15;k++)
{ {
@ -475,25 +487,14 @@ opus_val16 remove_doubling(opus_val16 *x, int maxperiod, int minperiod,
{ {
T1b = celt_udiv(2*second_check[k]*T0+k, 2*k); T1b = celt_udiv(2*second_check[k]*T0+k, 2*k);
} }
dual_inner_prod(x, &x[-T1], &x[-T1b], N, &xy, &xy2); dual_inner_prod(x, &x[-T1], &x[-T1b], N, &xy, &xy2, arch);
xy += xy2; xy = HALF32(xy + xy2);
yy = yy_lookup[T1] + yy_lookup[T1b]; yy = HALF32(yy_lookup[T1] + yy_lookup[T1b]);
#ifdef FIXED_POINT g1 = compute_pitch_gain(xy, xx, yy);
{
opus_val32 x2y2;
int sh, t;
x2y2 = 1+MULT32_32_Q31(xx,yy);
sh = celt_ilog2(x2y2)>>1;
t = VSHR32(x2y2, 2*(sh-7));
g1 = VSHR32(MULT16_32_Q15(celt_rsqrt_norm(t), xy),sh+1);
}
#else
g1 = xy/celt_sqrt(1+2.f*xx*1.f*yy);
#endif
if (abs(T1-prev_period)<=1) if (abs(T1-prev_period)<=1)
cont = prev_gain; cont = prev_gain;
else if (abs(T1-prev_period)<=2 && 5*k*k < T0) else if (abs(T1-prev_period)<=2 && 5*k*k < T0)
cont = HALF32(prev_gain); cont = HALF16(prev_gain);
else else
cont = 0; cont = 0;
thresh = MAX16(QCONST16(.3f,15), MULT16_16_Q15(QCONST16(.7f,15),g0)-cont); thresh = MAX16(QCONST16(.3f,15), MULT16_16_Q15(QCONST16(.7f,15),g0)-cont);
@ -518,7 +519,7 @@ opus_val16 remove_doubling(opus_val16 *x, int maxperiod, int minperiod,
pg = SHR32(frac_div32(best_xy,best_yy+1),16); pg = SHR32(frac_div32(best_xy,best_yy+1),16);
for (k=0;k<3;k++) for (k=0;k<3;k++)
xcorr[k] = celt_inner_prod(x, x-(T+k-1), N); 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])) if ((xcorr[2]-xcorr[0]) > MULT16_32_Q15(QCONST16(.7f,15),xcorr[1]-xcorr[0]))
offset = 1; offset = 1;
else if ((xcorr[0]-xcorr[2]) > MULT16_32_Q15(QCONST16(.7f,15),xcorr[1]-xcorr[2])) else if ((xcorr[0]-xcorr[2]) > MULT16_32_Q15(QCONST16(.7f,15),xcorr[1]-xcorr[2]))
@ -534,4 +535,3 @@ opus_val16 remove_doubling(opus_val16 *x, int maxperiod, int minperiod,
RESTORE_STACK; RESTORE_STACK;
return pg; return pg;
} }
#endif

View file

@ -37,7 +37,8 @@
#include "modes.h" #include "modes.h"
#include "cpu_support.h" #include "cpu_support.h"
#if defined(__SSE__) && !defined(FIXED_POINT) #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" #include "x86/pitch_sse.h"
#endif #endif
@ -45,8 +46,8 @@
#include "mips/pitch_mipsr1.h" #include "mips/pitch_mipsr1.h"
#endif #endif
#if defined(OPUS_ARM_ASM) && defined(FIXED_POINT) #if (defined(OPUS_ARM_ASM) || defined(OPUS_ARM_MAY_HAVE_NEON_INTR))
//# include "arm/pitch_arm.h" # include "arm/pitch_arm.h"
#endif #endif
void pitch_downsample(celt_sig * OPUS_RESTRICT x[], opus_val16 * OPUS_RESTRICT x_lp, void pitch_downsample(celt_sig * OPUS_RESTRICT x[], opus_val16 * OPUS_RESTRICT x_lp,
@ -56,12 +57,12 @@ void pitch_search(const opus_val16 * OPUS_RESTRICT x_lp, opus_val16 * OPUS_RESTR
int len, int max_pitch, int *pitch, int arch); int len, int max_pitch, int *pitch, int arch);
opus_val16 remove_doubling(opus_val16 *x, int maxperiod, int minperiod, opus_val16 remove_doubling(opus_val16 *x, int maxperiod, int minperiod,
int N, int *T0, int prev_period, opus_val16 prev_gain); 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 /* OPT: This is the kernel you really want to optimize. It gets used a lot
by the prefilter and by the PLC. */ by the prefilter and by the PLC. */
#ifndef OVERRIDE_XCORR_KERNEL static OPUS_INLINE void xcorr_kernel_c(const opus_val16 * x, const opus_val16 * y, opus_val32 sum[4], int len)
static OPUS_INLINE void xcorr_kernel(const opus_val16 * x, const opus_val16 * y, opus_val32 sum[4], int len)
{ {
int j; int j;
opus_val16 y_0, y_1, y_2, y_3; opus_val16 y_0, y_1, y_2, y_3;
@ -126,10 +127,14 @@ static OPUS_INLINE void xcorr_kernel(const opus_val16 * x, const opus_val16 * y,
sum[3] = MAC16_16(sum[3],tmp,y_1); 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 */ #endif /* OVERRIDE_XCORR_KERNEL */
#ifndef OVERRIDE_DUAL_INNER_PROD
static OPUS_INLINE void dual_inner_prod(const opus_val16 *x, const opus_val16 *y01, const opus_val16 *y02, 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 N, opus_val32 *xy1, opus_val32 *xy2)
{ {
int i; int i;
@ -143,11 +148,16 @@ static OPUS_INLINE void dual_inner_prod(const opus_val16 *x, const opus_val16 *y
*xy1 = xy01; *xy1 = xy01;
*xy2 = xy02; *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 #endif
#ifndef OVERRIDE_CELT_INNER_PROD /*We make sure a C version is always available for cases where the overhead of
static OPUS_INLINE opus_val32 celt_inner_prod(const opus_val16 *x, const opus_val16 *y, vectorization and passing around an arch flag aren't worth it.*/
int N) static OPUS_INLINE opus_val32 celt_inner_prod_c(const opus_val16 *x,
const opus_val16 *y, int N)
{ {
int i; int i;
opus_val32 xy=0; opus_val32 xy=0;
@ -155,35 +165,28 @@ static OPUS_INLINE opus_val32 celt_inner_prod(const opus_val16 *x, const opus_va
xy = MAC16_16(xy, x[i], y[i]); xy = MAC16_16(xy, x[i], y[i]);
return xy; 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 #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 #ifdef FIXED_POINT
opus_val32 opus_val32
#else #else
void void
#endif #endif
celt_pitch_xcorr_c(const opus_val16 *_x, const opus_val16 *_y, celt_pitch_xcorr_c(const opus_val16 *_x, const opus_val16 *_y,
opus_val32 *xcorr, int len, int max_pitch); opus_val32 *xcorr, int len, int max_pitch, int arch);
#if !defined(OVERRIDE_PITCH_XCORR) #ifndef OVERRIDE_PITCH_XCORR
/*Is run-time CPU detection enabled on this platform?*/ # define celt_pitch_xcorr celt_pitch_xcorr_c
# if defined(OPUS_HAVE_RTCD)
extern
# if defined(FIXED_POINT)
opus_val32
# else
void
# endif
(*const CELT_PITCH_XCORR_IMPL[OPUS_ARCHMASK+1])(const opus_val16 *,
const opus_val16 *, opus_val32 *, int, int);
# define celt_pitch_xcorr(_x, _y, xcorr, len, max_pitch, arch) \
((*CELT_PITCH_XCORR_IMPL[(arch)&OPUS_ARCHMASK])(_x, _y, \
xcorr, len, max_pitch))
# else
# define celt_pitch_xcorr(_x, _y, xcorr, len, max_pitch, arch) \
((void)(arch),celt_pitch_xcorr_c(_x, _y, xcorr, len, max_pitch))
# endif
#endif #endif
#endif #endif

View file

@ -292,7 +292,7 @@ void quant_coarse_energy(const CELTMode *m, int start, int end, int effEnd,
#endif #endif
} }
if (lfe) if (lfe)
max_decay=3; max_decay = QCONST16(3.f,DB_SHIFT);
enc_start_state = *enc; enc_start_state = *enc;
ALLOC(oldEBands_intra, C*m->nbEBands, opus_val16); ALLOC(oldEBands_intra, C*m->nbEBands, opus_val16);
@ -418,6 +418,7 @@ void quant_energy_finalise(const CELTMode *m, int start, int end, opus_val16 *ol
offset = (q2-.5f)*(1<<(14-fine_quant[i]-1))*(1.f/16384); offset = (q2-.5f)*(1<<(14-fine_quant[i]-1))*(1.f/16384);
#endif #endif
oldEBands[i+c*m->nbEBands] += offset; oldEBands[i+c*m->nbEBands] += offset;
error[i+c*m->nbEBands] -= offset;
bits_left--; bits_left--;
} while (++c < C); } while (++c < C);
} }
@ -456,7 +457,7 @@ void unquant_coarse_energy(const CELTMode *m, int start, int end, opus_val16 *ol
/* It would be better to express this invariant as a /* It would be better to express this invariant as a
test on C at function entry, but that isn't enough test on C at function entry, but that isn't enough
to make the static analyzer happy. */ to make the static analyzer happy. */
celt_assert(c<2); celt_sig_assert(c<2);
tell = ec_tell(dec); tell = ec_tell(dec);
if(budget-tell>=15) if(budget-tell>=15)
{ {
@ -547,9 +548,15 @@ void amp2Log2(const CELTMode *m, int effEnd, int end,
c=0; c=0;
do { do {
for (i=0;i<effEnd;i++) for (i=0;i<effEnd;i++)
{
bandLogE[i+c*m->nbEBands] = bandLogE[i+c*m->nbEBands] =
celt_log2(SHL32(bandE[i+c*m->nbEBands],2)) celt_log2(bandE[i+c*m->nbEBands])
- SHL16((opus_val16)eMeans[i],6); - SHL16((opus_val16)eMeans[i],6);
#ifdef FIXED_POINT
/* Compensate for bandE[] being Q12 but celt_log2() taking a Q14 input. */
bandLogE[i+c*m->nbEBands] += QCONST16(2.f, DB_SHIFT);
#endif
}
for (i=effEnd;i<end;i++) for (i=effEnd;i<end;i++)
bandLogE[c*m->nbEBands+i] = -QCONST16(14.f,DB_SHIFT); bandLogE[c*m->nbEBands+i] = -QCONST16(14.f,DB_SHIFT);
} while (++c < C); } while (++c < C);

View file

@ -131,7 +131,7 @@ void compute_pulse_cache(CELTMode *m, int LM)
for (i=0;i<nbEntries;i++) for (i=0;i<nbEntries;i++)
{ {
unsigned char *ptr = bits+entryI[i]; unsigned char *ptr = bits+entryI[i];
opus_int16 tmp[MAX_PULSES+1]; opus_int16 tmp[CELT_MAX_PULSES+1];
get_required_bits(tmp, entryN[i], get_pulses(entryK[i]), BITRES); get_required_bits(tmp, entryN[i], get_pulses(entryK[i]), BITRES);
for (j=1;j<=entryK[i];j++) for (j=1;j<=entryK[i];j++)
ptr[j] = tmp[get_pulses(j)]-1; ptr[j] = tmp[get_pulses(j)]-1;
@ -296,7 +296,7 @@ static OPUS_INLINE int interp_bits2pulses(const CELTMode *m, int start, int end,
done = 0; done = 0;
for (j=end;j-->start;) for (j=end;j-->start;)
{ {
int tmp = bits1[j] + (lo*bits2[j]>>ALLOC_STEPS); int tmp = bits1[j] + ((opus_int32)lo*bits2[j]>>ALLOC_STEPS);
if (tmp < thresh[j] && !done) if (tmp < thresh[j] && !done)
{ {
if (tmp >= alloc_floor) if (tmp >= alloc_floor)
@ -348,12 +348,17 @@ static OPUS_INLINE int interp_bits2pulses(const CELTMode *m, int start, int end,
/*This if() block is the only part of the allocation function that /*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 is not a mandatory part of the bitstream: any bands we choose to
skip here must be explicitly signaled.*/ skip here must be explicitly signaled.*/
/*Choose a threshold with some hysteresis to keep bands from int depth_threshold;
fluctuating in and out.*/ /*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 #ifdef FUZZING
if ((rand()&0x1) == 0) if ((rand()&0x1) == 0)
#else #else
if (codedBands<=start+2 || (band_bits > ((j<prev?7:9)*band_width<<LM<<BITRES)>>4 && j<=signalBandwidth)) if (codedBands<=start+2 || (band_bits > (depth_threshold*band_width<<LM<<BITRES)>>4 && j<=signalBandwidth))
#endif #endif
{ {
ec_enc_bit_logp(ec, 1, 1); ec_enc_bit_logp(ec, 1, 1);
@ -524,7 +529,7 @@ static OPUS_INLINE int interp_bits2pulses(const CELTMode *m, int start, int end,
return codedBands; return codedBands;
} }
int compute_allocation(const CELTMode *m, int start, int end, const int *offsets, const int *cap, int alloc_trim, int *intensity, int *dual_stereo, 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) 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 lo, hi, len, j;

View file

@ -32,7 +32,7 @@
#define MAX_PSEUDO 40 #define MAX_PSEUDO 40
#define LOG_MAX_PSEUDO 6 #define LOG_MAX_PSEUDO 6
#define MAX_PULSES 128 #define CELT_MAX_PULSES 128
#define MAX_FINE_BITS 8 #define MAX_FINE_BITS 8
@ -95,7 +95,7 @@ static OPUS_INLINE int pulses2bits(const CELTMode *m, int band, int LM, int puls
@param pulses Number of pulses per band (returned) @param pulses Number of pulses per band (returned)
@return Total number of bits allocated @return Total number of bits allocated
*/ */
int compute_allocation(const CELTMode *m, int start, int end, const int *offsets, const int *cap, int alloc_trim, int *intensity, int *dual_stero, int clt_compute_allocation(const CELTMode *m, int start, int end, const int *offsets, const int *cap, int alloc_trim, int *intensity, int *dual_stero,
opus_int32 total, opus_int32 *balance, int *pulses, int *ebits, int *fine_priority, int C, int LM, ec_ctx *ec, int encode, int prev, int signalBandwidth); 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);
#endif #endif

View file

@ -4,9 +4,14 @@
#include "modes.h" #include "modes.h"
#include "rate.h" #include "rate.h"
#ifdef HAVE_ARM_NE10
#define OVERRIDE_FFT 1
#include "static_modes_fixed_arm_ne10.h"
#endif
#ifndef DEF_WINDOW120 #ifndef DEF_WINDOW120
#define DEF_WINDOW120 #define DEF_WINDOW120
static const opus_val16 window120[120] ICONST_ATTR = { static const opus_val16 window120[120] = {
2, 20, 55, 108, 178, 2, 20, 55, 108, 178,
266, 372, 494, 635, 792, 266, 372, 494, 635, 792,
966, 1157, 1365, 1590, 1831, 966, 1157, 1365, 1590, 1831,
@ -36,13 +41,13 @@ static const opus_val16 window120[120] ICONST_ATTR = {
#ifndef DEF_LOGN400 #ifndef DEF_LOGN400
#define DEF_LOGN400 #define DEF_LOGN400
static const opus_int16 logN400[21] ICONST_ATTR = { static const opus_int16 logN400[21] = {
0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 16, 16, 16, 21, 21, 24, 29, 34, 36, }; 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 16, 16, 16, 21, 21, 24, 29, 34, 36, };
#endif #endif
#ifndef DEF_PULSE_CACHE50 #ifndef DEF_PULSE_CACHE50
#define DEF_PULSE_CACHE50 #define DEF_PULSE_CACHE50
static const opus_int16 cache_index50[105] ICONST_ATTR = { static const opus_int16 cache_index50[105] = {
-1, -1, -1, -1, -1, -1, -1, -1, 0, 0, 0, 0, 41, 41, 41, -1, -1, -1, -1, -1, -1, -1, -1, 0, 0, 0, 0, 41, 41, 41,
82, 82, 123, 164, 200, 222, 0, 0, 0, 0, 0, 0, 0, 0, 41, 82, 82, 123, 164, 200, 222, 0, 0, 0, 0, 0, 0, 0, 0, 41,
41, 41, 41, 123, 123, 123, 164, 164, 240, 266, 283, 295, 41, 41, 41, 41, 41, 41, 123, 123, 123, 164, 164, 240, 266, 283, 295, 41, 41, 41,
@ -51,7 +56,7 @@ static const opus_int16 cache_index50[105] ICONST_ATTR = {
305, 305, 305, 318, 318, 343, 351, 358, 364, 240, 240, 240, 240, 240, 240, 305, 305, 305, 318, 318, 343, 351, 358, 364, 240, 240, 240, 240, 240, 240,
240, 240, 305, 305, 305, 305, 343, 343, 343, 351, 351, 370, 376, 382, 387, 240, 240, 305, 305, 305, 305, 343, 343, 343, 351, 351, 370, 376, 382, 387,
}; };
static const unsigned char cache_bits50[392] ICONST_ATTR = { static const unsigned char cache_bits50[392] = {
40, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 40, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 40, 15, 23, 28, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 40, 15, 23, 28,
@ -79,7 +84,7 @@ static const unsigned char cache_bits50[392] ICONST_ATTR = {
106, 151, 192, 231, 5, 59, 111, 158, 202, 243, 5, 55, 103, 147, 187, 106, 151, 192, 231, 5, 59, 111, 158, 202, 243, 5, 55, 103, 147, 187,
224, 5, 60, 113, 161, 206, 248, 4, 65, 122, 175, 224, 4, 67, 127, 224, 5, 60, 113, 161, 206, 248, 4, 65, 122, 175, 224, 4, 67, 127,
182, 234, }; 182, 234, };
static const unsigned char cache_caps50[168] ICONST_ATTR = { static const unsigned char cache_caps50[168] = {
224, 224, 224, 224, 224, 224, 224, 224, 160, 160, 160, 160, 185, 185, 185, 224, 224, 224, 224, 224, 224, 224, 224, 160, 160, 160, 160, 185, 185, 185,
178, 178, 168, 134, 61, 37, 224, 224, 224, 224, 224, 224, 224, 224, 240, 178, 178, 168, 134, 61, 37, 224, 224, 224, 224, 224, 224, 224, 224, 240,
240, 240, 240, 207, 207, 207, 198, 198, 183, 144, 66, 40, 160, 160, 160, 240, 240, 240, 207, 207, 207, 198, 198, 183, 144, 66, 40, 160, 160, 160,
@ -96,7 +101,7 @@ static const unsigned char cache_caps50[168] ICONST_ATTR = {
#ifndef FFT_TWIDDLES48000_960 #ifndef FFT_TWIDDLES48000_960
#define FFT_TWIDDLES48000_960 #define FFT_TWIDDLES48000_960
static const kiss_twiddle_cpx fft_twiddles48000_960[480] ICONST_ATTR = { static const kiss_twiddle_cpx fft_twiddles48000_960[480] = {
{32767, 0}, {32766, -429}, {32767, 0}, {32766, -429},
{32757, -858}, {32743, -1287}, {32757, -858}, {32743, -1287},
{32724, -1715}, {32698, -2143}, {32724, -1715}, {32698, -2143},
@ -424,7 +429,7 @@ static const opus_int16 fft_bitrev60[60] = {
#ifndef FFT_STATE48000_960_0 #ifndef FFT_STATE48000_960_0
#define FFT_STATE48000_960_0 #define FFT_STATE48000_960_0
static const kiss_fft_state fft_state48000_960_0 ICONST_ATTR = { static const kiss_fft_state fft_state48000_960_0 = {
480, /* nfft */ 480, /* nfft */
17476, /* scale */ 17476, /* scale */
8, /* scale_shift */ 8, /* scale_shift */
@ -432,12 +437,17 @@ static const kiss_fft_state fft_state48000_960_0 ICONST_ATTR = {
{5, 96, 3, 32, 4, 8, 2, 4, 4, 1, 0, 0, 0, 0, 0, 0, }, /* factors */ {5, 96, 3, 32, 4, 8, 2, 4, 4, 1, 0, 0, 0, 0, 0, 0, }, /* factors */
fft_bitrev480, /* bitrev */ fft_bitrev480, /* bitrev */
fft_twiddles48000_960, /* bitrev */ fft_twiddles48000_960, /* bitrev */
#ifdef OVERRIDE_FFT
(arch_fft_state *)&cfg_arch_480,
#else
NULL,
#endif
}; };
#endif #endif
#ifndef FFT_STATE48000_960_1 #ifndef FFT_STATE48000_960_1
#define FFT_STATE48000_960_1 #define FFT_STATE48000_960_1
static const kiss_fft_state fft_state48000_960_1 ICONST_ATTR = { static const kiss_fft_state fft_state48000_960_1 = {
240, /* nfft */ 240, /* nfft */
17476, /* scale */ 17476, /* scale */
7, /* scale_shift */ 7, /* scale_shift */
@ -445,12 +455,17 @@ static const kiss_fft_state fft_state48000_960_1 ICONST_ATTR = {
{5, 48, 3, 16, 4, 4, 4, 1, 0, 0, 0, 0, 0, 0, 0, 0, }, /* factors */ {5, 48, 3, 16, 4, 4, 4, 1, 0, 0, 0, 0, 0, 0, 0, 0, }, /* factors */
fft_bitrev240, /* bitrev */ fft_bitrev240, /* bitrev */
fft_twiddles48000_960, /* bitrev */ fft_twiddles48000_960, /* bitrev */
#ifdef OVERRIDE_FFT
(arch_fft_state *)&cfg_arch_240,
#else
NULL,
#endif
}; };
#endif #endif
#ifndef FFT_STATE48000_960_2 #ifndef FFT_STATE48000_960_2
#define FFT_STATE48000_960_2 #define FFT_STATE48000_960_2
static const kiss_fft_state fft_state48000_960_2 ICONST_ATTR = { static const kiss_fft_state fft_state48000_960_2 = {
120, /* nfft */ 120, /* nfft */
17476, /* scale */ 17476, /* scale */
6, /* scale_shift */ 6, /* scale_shift */
@ -458,12 +473,17 @@ static const kiss_fft_state fft_state48000_960_2 ICONST_ATTR = {
{5, 24, 3, 8, 2, 4, 4, 1, 0, 0, 0, 0, 0, 0, 0, 0, }, /* factors */ {5, 24, 3, 8, 2, 4, 4, 1, 0, 0, 0, 0, 0, 0, 0, 0, }, /* factors */
fft_bitrev120, /* bitrev */ fft_bitrev120, /* bitrev */
fft_twiddles48000_960, /* bitrev */ fft_twiddles48000_960, /* bitrev */
#ifdef OVERRIDE_FFT
(arch_fft_state *)&cfg_arch_120,
#else
NULL,
#endif
}; };
#endif #endif
#ifndef FFT_STATE48000_960_3 #ifndef FFT_STATE48000_960_3
#define FFT_STATE48000_960_3 #define FFT_STATE48000_960_3
static const kiss_fft_state fft_state48000_960_3 ICONST_ATTR = { static const kiss_fft_state fft_state48000_960_3 = {
60, /* nfft */ 60, /* nfft */
17476, /* scale */ 17476, /* scale */
5, /* scale_shift */ 5, /* scale_shift */
@ -471,6 +491,11 @@ static const kiss_fft_state fft_state48000_960_3 ICONST_ATTR = {
{5, 12, 3, 4, 4, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, /* factors */ {5, 12, 3, 4, 4, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, /* factors */
fft_bitrev60, /* bitrev */ fft_bitrev60, /* bitrev */
fft_twiddles48000_960, /* bitrev */ fft_twiddles48000_960, /* bitrev */
#ifdef OVERRIDE_FFT
(arch_fft_state *)&cfg_arch_60,
#else
NULL,
#endif
}; };
#endif #endif
@ -478,7 +503,7 @@ fft_twiddles48000_960, /* bitrev */
#ifndef MDCT_TWIDDLES960 #ifndef MDCT_TWIDDLES960
#define MDCT_TWIDDLES960 #define MDCT_TWIDDLES960
static const opus_val16 mdct_twiddles960[1800] ICONST_ATTR = { static const opus_val16 mdct_twiddles960[1800] = {
32767, 32767, 32767, 32766, 32765, 32767, 32767, 32767, 32766, 32765,
32763, 32761, 32759, 32756, 32753, 32763, 32761, 32759, 32756, 32753,
32750, 32746, 32742, 32738, 32733, 32750, 32746, 32742, 32738, 32733,
@ -842,7 +867,7 @@ static const opus_val16 mdct_twiddles960[1800] ICONST_ATTR = {
}; };
#endif #endif
static const CELTMode mode48000_960_120 ICONST_ATTR = { static const CELTMode mode48000_960_120 = {
48000, /* Fs */ 48000, /* Fs */
120, /* overlap */ 120, /* overlap */
21, /* nbEBands */ 21, /* nbEBands */

View file

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

View file

@ -0,0 +1,888 @@
/* The contents of this file was automatically generated by dump_modes.c
with arguments: 48000 960
It contains static definitions for some pre-defined modes. */
#include "modes.h"
#include "rate.h"
#ifdef HAVE_ARM_NE10
#define OVERRIDE_FFT 1
#include "static_modes_float_arm_ne10.h"
#endif
#ifndef DEF_WINDOW120
#define DEF_WINDOW120
static const opus_val16 window120[120] = {
6.7286966e-05f, 0.00060551348f, 0.0016815970f, 0.0032947962f, 0.0054439943f,
0.0081276923f, 0.011344001f, 0.015090633f, 0.019364886f, 0.024163635f,
0.029483315f, 0.035319905f, 0.041668911f, 0.048525347f, 0.055883718f,
0.063737999f, 0.072081616f, 0.080907428f, 0.090207705f, 0.099974111f,
0.11019769f, 0.12086883f, 0.13197729f, 0.14351214f, 0.15546177f,
0.16781389f, 0.18055550f, 0.19367290f, 0.20715171f, 0.22097682f,
0.23513243f, 0.24960208f, 0.26436860f, 0.27941419f, 0.29472040f,
0.31026818f, 0.32603788f, 0.34200931f, 0.35816177f, 0.37447407f,
0.39092462f, 0.40749142f, 0.42415215f, 0.44088423f, 0.45766484f,
0.47447104f, 0.49127978f, 0.50806798f, 0.52481261f, 0.54149077f,
0.55807973f, 0.57455701f, 0.59090049f, 0.60708841f, 0.62309951f,
0.63891306f, 0.65450896f, 0.66986776f, 0.68497077f, 0.69980010f,
0.71433873f, 0.72857055f, 0.74248043f, 0.75605424f, 0.76927895f,
0.78214257f, 0.79463430f, 0.80674445f, 0.81846456f, 0.82978733f,
0.84070669f, 0.85121779f, 0.86131698f, 0.87100183f, 0.88027111f,
0.88912479f, 0.89756398f, 0.90559094f, 0.91320904f, 0.92042270f,
0.92723738f, 0.93365955f, 0.93969656f, 0.94535671f, 0.95064907f,
0.95558353f, 0.96017067f, 0.96442171f, 0.96834849f, 0.97196334f,
0.97527906f, 0.97830883f, 0.98106616f, 0.98356480f, 0.98581869f,
0.98784191f, 0.98964856f, 0.99125274f, 0.99266849f, 0.99390969f,
0.99499004f, 0.99592297f, 0.99672162f, 0.99739874f, 0.99796667f,
0.99843728f, 0.99882195f, 0.99913147f, 0.99937606f, 0.99956527f,
0.99970802f, 0.99981248f, 0.99988613f, 0.99993565f, 0.99996697f,
0.99998518f, 0.99999457f, 0.99999859f, 0.99999982f, 1.0000000f,
};
#endif
#ifndef DEF_LOGN400
#define DEF_LOGN400
static const opus_int16 logN400[21] = {
0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 16, 16, 16, 21, 21, 24, 29, 34, 36, };
#endif
#ifndef DEF_PULSE_CACHE50
#define DEF_PULSE_CACHE50
static const opus_int16 cache_index50[105] = {
-1, -1, -1, -1, -1, -1, -1, -1, 0, 0, 0, 0, 41, 41, 41,
82, 82, 123, 164, 200, 222, 0, 0, 0, 0, 0, 0, 0, 0, 41,
41, 41, 41, 123, 123, 123, 164, 164, 240, 266, 283, 295, 41, 41, 41,
41, 41, 41, 41, 41, 123, 123, 123, 123, 240, 240, 240, 266, 266, 305,
318, 328, 336, 123, 123, 123, 123, 123, 123, 123, 123, 240, 240, 240, 240,
305, 305, 305, 318, 318, 343, 351, 358, 364, 240, 240, 240, 240, 240, 240,
240, 240, 305, 305, 305, 305, 343, 343, 343, 351, 351, 370, 376, 382, 387,
};
static const unsigned char cache_bits50[392] = {
40, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 40, 15, 23, 28,
31, 34, 36, 38, 39, 41, 42, 43, 44, 45, 46, 47, 47, 49, 50,
51, 52, 53, 54, 55, 55, 57, 58, 59, 60, 61, 62, 63, 63, 65,
66, 67, 68, 69, 70, 71, 71, 40, 20, 33, 41, 48, 53, 57, 61,
64, 66, 69, 71, 73, 75, 76, 78, 80, 82, 85, 87, 89, 91, 92,
94, 96, 98, 101, 103, 105, 107, 108, 110, 112, 114, 117, 119, 121, 123,
124, 126, 128, 40, 23, 39, 51, 60, 67, 73, 79, 83, 87, 91, 94,
97, 100, 102, 105, 107, 111, 115, 118, 121, 124, 126, 129, 131, 135, 139,
142, 145, 148, 150, 153, 155, 159, 163, 166, 169, 172, 174, 177, 179, 35,
28, 49, 65, 78, 89, 99, 107, 114, 120, 126, 132, 136, 141, 145, 149,
153, 159, 165, 171, 176, 180, 185, 189, 192, 199, 205, 211, 216, 220, 225,
229, 232, 239, 245, 251, 21, 33, 58, 79, 97, 112, 125, 137, 148, 157,
166, 174, 182, 189, 195, 201, 207, 217, 227, 235, 243, 251, 17, 35, 63,
86, 106, 123, 139, 152, 165, 177, 187, 197, 206, 214, 222, 230, 237, 250,
25, 31, 55, 75, 91, 105, 117, 128, 138, 146, 154, 161, 168, 174, 180,
185, 190, 200, 208, 215, 222, 229, 235, 240, 245, 255, 16, 36, 65, 89,
110, 128, 144, 159, 173, 185, 196, 207, 217, 226, 234, 242, 250, 11, 41,
74, 103, 128, 151, 172, 191, 209, 225, 241, 255, 9, 43, 79, 110, 138,
163, 186, 207, 227, 246, 12, 39, 71, 99, 123, 144, 164, 182, 198, 214,
228, 241, 253, 9, 44, 81, 113, 142, 168, 192, 214, 235, 255, 7, 49,
90, 127, 160, 191, 220, 247, 6, 51, 95, 134, 170, 203, 234, 7, 47,
87, 123, 155, 184, 212, 237, 6, 52, 97, 137, 174, 208, 240, 5, 57,
106, 151, 192, 231, 5, 59, 111, 158, 202, 243, 5, 55, 103, 147, 187,
224, 5, 60, 113, 161, 206, 248, 4, 65, 122, 175, 224, 4, 67, 127,
182, 234, };
static const unsigned char cache_caps50[168] = {
224, 224, 224, 224, 224, 224, 224, 224, 160, 160, 160, 160, 185, 185, 185,
178, 178, 168, 134, 61, 37, 224, 224, 224, 224, 224, 224, 224, 224, 240,
240, 240, 240, 207, 207, 207, 198, 198, 183, 144, 66, 40, 160, 160, 160,
160, 160, 160, 160, 160, 185, 185, 185, 185, 193, 193, 193, 183, 183, 172,
138, 64, 38, 240, 240, 240, 240, 240, 240, 240, 240, 207, 207, 207, 207,
204, 204, 204, 193, 193, 180, 143, 66, 40, 185, 185, 185, 185, 185, 185,
185, 185, 193, 193, 193, 193, 193, 193, 193, 183, 183, 172, 138, 65, 39,
207, 207, 207, 207, 207, 207, 207, 207, 204, 204, 204, 204, 201, 201, 201,
188, 188, 176, 141, 66, 40, 193, 193, 193, 193, 193, 193, 193, 193, 193,
193, 193, 193, 194, 194, 194, 184, 184, 173, 139, 65, 39, 204, 204, 204,
204, 204, 204, 204, 204, 201, 201, 201, 201, 198, 198, 198, 187, 187, 175,
140, 66, 40, };
#endif
#ifndef FFT_TWIDDLES48000_960
#define FFT_TWIDDLES48000_960
static const kiss_twiddle_cpx fft_twiddles48000_960[480] = {
{1.0000000f, -0.0000000f}, {0.99991433f, -0.013089596f},
{0.99965732f, -0.026176948f}, {0.99922904f, -0.039259816f},
{0.99862953f, -0.052335956f}, {0.99785892f, -0.065403129f},
{0.99691733f, -0.078459096f}, {0.99580493f, -0.091501619f},
{0.99452190f, -0.10452846f}, {0.99306846f, -0.11753740f},
{0.99144486f, -0.13052619f}, {0.98965139f, -0.14349262f},
{0.98768834f, -0.15643447f}, {0.98555606f, -0.16934950f},
{0.98325491f, -0.18223553f}, {0.98078528f, -0.19509032f},
{0.97814760f, -0.20791169f}, {0.97534232f, -0.22069744f},
{0.97236992f, -0.23344536f}, {0.96923091f, -0.24615329f},
{0.96592583f, -0.25881905f}, {0.96245524f, -0.27144045f},
{0.95881973f, -0.28401534f}, {0.95501994f, -0.29654157f},
{0.95105652f, -0.30901699f}, {0.94693013f, -0.32143947f},
{0.94264149f, -0.33380686f}, {0.93819134f, -0.34611706f},
{0.93358043f, -0.35836795f}, {0.92880955f, -0.37055744f},
{0.92387953f, -0.38268343f}, {0.91879121f, -0.39474386f},
{0.91354546f, -0.40673664f}, {0.90814317f, -0.41865974f},
{0.90258528f, -0.43051110f}, {0.89687274f, -0.44228869f},
{0.89100652f, -0.45399050f}, {0.88498764f, -0.46561452f},
{0.87881711f, -0.47715876f}, {0.87249601f, -0.48862124f},
{0.86602540f, -0.50000000f}, {0.85940641f, -0.51129309f},
{0.85264016f, -0.52249856f}, {0.84572782f, -0.53361452f},
{0.83867057f, -0.54463904f}, {0.83146961f, -0.55557023f},
{0.82412619f, -0.56640624f}, {0.81664156f, -0.57714519f},
{0.80901699f, -0.58778525f}, {0.80125381f, -0.59832460f},
{0.79335334f, -0.60876143f}, {0.78531693f, -0.61909395f},
{0.77714596f, -0.62932039f}, {0.76884183f, -0.63943900f},
{0.76040597f, -0.64944805f}, {0.75183981f, -0.65934582f},
{0.74314483f, -0.66913061f}, {0.73432251f, -0.67880075f},
{0.72537437f, -0.68835458f}, {0.71630194f, -0.69779046f},
{0.70710678f, -0.70710678f}, {0.69779046f, -0.71630194f},
{0.68835458f, -0.72537437f}, {0.67880075f, -0.73432251f},
{0.66913061f, -0.74314483f}, {0.65934582f, -0.75183981f},
{0.64944805f, -0.76040597f}, {0.63943900f, -0.76884183f},
{0.62932039f, -0.77714596f}, {0.61909395f, -0.78531693f},
{0.60876143f, -0.79335334f}, {0.59832460f, -0.80125381f},
{0.58778525f, -0.80901699f}, {0.57714519f, -0.81664156f},
{0.56640624f, -0.82412619f}, {0.55557023f, -0.83146961f},
{0.54463904f, -0.83867057f}, {0.53361452f, -0.84572782f},
{0.52249856f, -0.85264016f}, {0.51129309f, -0.85940641f},
{0.50000000f, -0.86602540f}, {0.48862124f, -0.87249601f},
{0.47715876f, -0.87881711f}, {0.46561452f, -0.88498764f},
{0.45399050f, -0.89100652f}, {0.44228869f, -0.89687274f},
{0.43051110f, -0.90258528f}, {0.41865974f, -0.90814317f},
{0.40673664f, -0.91354546f}, {0.39474386f, -0.91879121f},
{0.38268343f, -0.92387953f}, {0.37055744f, -0.92880955f},
{0.35836795f, -0.93358043f}, {0.34611706f, -0.93819134f},
{0.33380686f, -0.94264149f}, {0.32143947f, -0.94693013f},
{0.30901699f, -0.95105652f}, {0.29654157f, -0.95501994f},
{0.28401534f, -0.95881973f}, {0.27144045f, -0.96245524f},
{0.25881905f, -0.96592583f}, {0.24615329f, -0.96923091f},
{0.23344536f, -0.97236992f}, {0.22069744f, -0.97534232f},
{0.20791169f, -0.97814760f}, {0.19509032f, -0.98078528f},
{0.18223553f, -0.98325491f}, {0.16934950f, -0.98555606f},
{0.15643447f, -0.98768834f}, {0.14349262f, -0.98965139f},
{0.13052619f, -0.99144486f}, {0.11753740f, -0.99306846f},
{0.10452846f, -0.99452190f}, {0.091501619f, -0.99580493f},
{0.078459096f, -0.99691733f}, {0.065403129f, -0.99785892f},
{0.052335956f, -0.99862953f}, {0.039259816f, -0.99922904f},
{0.026176948f, -0.99965732f}, {0.013089596f, -0.99991433f},
{6.1230318e-17f, -1.0000000f}, {-0.013089596f, -0.99991433f},
{-0.026176948f, -0.99965732f}, {-0.039259816f, -0.99922904f},
{-0.052335956f, -0.99862953f}, {-0.065403129f, -0.99785892f},
{-0.078459096f, -0.99691733f}, {-0.091501619f, -0.99580493f},
{-0.10452846f, -0.99452190f}, {-0.11753740f, -0.99306846f},
{-0.13052619f, -0.99144486f}, {-0.14349262f, -0.98965139f},
{-0.15643447f, -0.98768834f}, {-0.16934950f, -0.98555606f},
{-0.18223553f, -0.98325491f}, {-0.19509032f, -0.98078528f},
{-0.20791169f, -0.97814760f}, {-0.22069744f, -0.97534232f},
{-0.23344536f, -0.97236992f}, {-0.24615329f, -0.96923091f},
{-0.25881905f, -0.96592583f}, {-0.27144045f, -0.96245524f},
{-0.28401534f, -0.95881973f}, {-0.29654157f, -0.95501994f},
{-0.30901699f, -0.95105652f}, {-0.32143947f, -0.94693013f},
{-0.33380686f, -0.94264149f}, {-0.34611706f, -0.93819134f},
{-0.35836795f, -0.93358043f}, {-0.37055744f, -0.92880955f},
{-0.38268343f, -0.92387953f}, {-0.39474386f, -0.91879121f},
{-0.40673664f, -0.91354546f}, {-0.41865974f, -0.90814317f},
{-0.43051110f, -0.90258528f}, {-0.44228869f, -0.89687274f},
{-0.45399050f, -0.89100652f}, {-0.46561452f, -0.88498764f},
{-0.47715876f, -0.87881711f}, {-0.48862124f, -0.87249601f},
{-0.50000000f, -0.86602540f}, {-0.51129309f, -0.85940641f},
{-0.52249856f, -0.85264016f}, {-0.53361452f, -0.84572782f},
{-0.54463904f, -0.83867057f}, {-0.55557023f, -0.83146961f},
{-0.56640624f, -0.82412619f}, {-0.57714519f, -0.81664156f},
{-0.58778525f, -0.80901699f}, {-0.59832460f, -0.80125381f},
{-0.60876143f, -0.79335334f}, {-0.61909395f, -0.78531693f},
{-0.62932039f, -0.77714596f}, {-0.63943900f, -0.76884183f},
{-0.64944805f, -0.76040597f}, {-0.65934582f, -0.75183981f},
{-0.66913061f, -0.74314483f}, {-0.67880075f, -0.73432251f},
{-0.68835458f, -0.72537437f}, {-0.69779046f, -0.71630194f},
{-0.70710678f, -0.70710678f}, {-0.71630194f, -0.69779046f},
{-0.72537437f, -0.68835458f}, {-0.73432251f, -0.67880075f},
{-0.74314483f, -0.66913061f}, {-0.75183981f, -0.65934582f},
{-0.76040597f, -0.64944805f}, {-0.76884183f, -0.63943900f},
{-0.77714596f, -0.62932039f}, {-0.78531693f, -0.61909395f},
{-0.79335334f, -0.60876143f}, {-0.80125381f, -0.59832460f},
{-0.80901699f, -0.58778525f}, {-0.81664156f, -0.57714519f},
{-0.82412619f, -0.56640624f}, {-0.83146961f, -0.55557023f},
{-0.83867057f, -0.54463904f}, {-0.84572782f, -0.53361452f},
{-0.85264016f, -0.52249856f}, {-0.85940641f, -0.51129309f},
{-0.86602540f, -0.50000000f}, {-0.87249601f, -0.48862124f},
{-0.87881711f, -0.47715876f}, {-0.88498764f, -0.46561452f},
{-0.89100652f, -0.45399050f}, {-0.89687274f, -0.44228869f},
{-0.90258528f, -0.43051110f}, {-0.90814317f, -0.41865974f},
{-0.91354546f, -0.40673664f}, {-0.91879121f, -0.39474386f},
{-0.92387953f, -0.38268343f}, {-0.92880955f, -0.37055744f},
{-0.93358043f, -0.35836795f}, {-0.93819134f, -0.34611706f},
{-0.94264149f, -0.33380686f}, {-0.94693013f, -0.32143947f},
{-0.95105652f, -0.30901699f}, {-0.95501994f, -0.29654157f},
{-0.95881973f, -0.28401534f}, {-0.96245524f, -0.27144045f},
{-0.96592583f, -0.25881905f}, {-0.96923091f, -0.24615329f},
{-0.97236992f, -0.23344536f}, {-0.97534232f, -0.22069744f},
{-0.97814760f, -0.20791169f}, {-0.98078528f, -0.19509032f},
{-0.98325491f, -0.18223553f}, {-0.98555606f, -0.16934950f},
{-0.98768834f, -0.15643447f}, {-0.98965139f, -0.14349262f},
{-0.99144486f, -0.13052619f}, {-0.99306846f, -0.11753740f},
{-0.99452190f, -0.10452846f}, {-0.99580493f, -0.091501619f},
{-0.99691733f, -0.078459096f}, {-0.99785892f, -0.065403129f},
{-0.99862953f, -0.052335956f}, {-0.99922904f, -0.039259816f},
{-0.99965732f, -0.026176948f}, {-0.99991433f, -0.013089596f},
{-1.0000000f, -1.2246064e-16f}, {-0.99991433f, 0.013089596f},
{-0.99965732f, 0.026176948f}, {-0.99922904f, 0.039259816f},
{-0.99862953f, 0.052335956f}, {-0.99785892f, 0.065403129f},
{-0.99691733f, 0.078459096f}, {-0.99580493f, 0.091501619f},
{-0.99452190f, 0.10452846f}, {-0.99306846f, 0.11753740f},
{-0.99144486f, 0.13052619f}, {-0.98965139f, 0.14349262f},
{-0.98768834f, 0.15643447f}, {-0.98555606f, 0.16934950f},
{-0.98325491f, 0.18223553f}, {-0.98078528f, 0.19509032f},
{-0.97814760f, 0.20791169f}, {-0.97534232f, 0.22069744f},
{-0.97236992f, 0.23344536f}, {-0.96923091f, 0.24615329f},
{-0.96592583f, 0.25881905f}, {-0.96245524f, 0.27144045f},
{-0.95881973f, 0.28401534f}, {-0.95501994f, 0.29654157f},
{-0.95105652f, 0.30901699f}, {-0.94693013f, 0.32143947f},
{-0.94264149f, 0.33380686f}, {-0.93819134f, 0.34611706f},
{-0.93358043f, 0.35836795f}, {-0.92880955f, 0.37055744f},
{-0.92387953f, 0.38268343f}, {-0.91879121f, 0.39474386f},
{-0.91354546f, 0.40673664f}, {-0.90814317f, 0.41865974f},
{-0.90258528f, 0.43051110f}, {-0.89687274f, 0.44228869f},
{-0.89100652f, 0.45399050f}, {-0.88498764f, 0.46561452f},
{-0.87881711f, 0.47715876f}, {-0.87249601f, 0.48862124f},
{-0.86602540f, 0.50000000f}, {-0.85940641f, 0.51129309f},
{-0.85264016f, 0.52249856f}, {-0.84572782f, 0.53361452f},
{-0.83867057f, 0.54463904f}, {-0.83146961f, 0.55557023f},
{-0.82412619f, 0.56640624f}, {-0.81664156f, 0.57714519f},
{-0.80901699f, 0.58778525f}, {-0.80125381f, 0.59832460f},
{-0.79335334f, 0.60876143f}, {-0.78531693f, 0.61909395f},
{-0.77714596f, 0.62932039f}, {-0.76884183f, 0.63943900f},
{-0.76040597f, 0.64944805f}, {-0.75183981f, 0.65934582f},
{-0.74314483f, 0.66913061f}, {-0.73432251f, 0.67880075f},
{-0.72537437f, 0.68835458f}, {-0.71630194f, 0.69779046f},
{-0.70710678f, 0.70710678f}, {-0.69779046f, 0.71630194f},
{-0.68835458f, 0.72537437f}, {-0.67880075f, 0.73432251f},
{-0.66913061f, 0.74314483f}, {-0.65934582f, 0.75183981f},
{-0.64944805f, 0.76040597f}, {-0.63943900f, 0.76884183f},
{-0.62932039f, 0.77714596f}, {-0.61909395f, 0.78531693f},
{-0.60876143f, 0.79335334f}, {-0.59832460f, 0.80125381f},
{-0.58778525f, 0.80901699f}, {-0.57714519f, 0.81664156f},
{-0.56640624f, 0.82412619f}, {-0.55557023f, 0.83146961f},
{-0.54463904f, 0.83867057f}, {-0.53361452f, 0.84572782f},
{-0.52249856f, 0.85264016f}, {-0.51129309f, 0.85940641f},
{-0.50000000f, 0.86602540f}, {-0.48862124f, 0.87249601f},
{-0.47715876f, 0.87881711f}, {-0.46561452f, 0.88498764f},
{-0.45399050f, 0.89100652f}, {-0.44228869f, 0.89687274f},
{-0.43051110f, 0.90258528f}, {-0.41865974f, 0.90814317f},
{-0.40673664f, 0.91354546f}, {-0.39474386f, 0.91879121f},
{-0.38268343f, 0.92387953f}, {-0.37055744f, 0.92880955f},
{-0.35836795f, 0.93358043f}, {-0.34611706f, 0.93819134f},
{-0.33380686f, 0.94264149f}, {-0.32143947f, 0.94693013f},
{-0.30901699f, 0.95105652f}, {-0.29654157f, 0.95501994f},
{-0.28401534f, 0.95881973f}, {-0.27144045f, 0.96245524f},
{-0.25881905f, 0.96592583f}, {-0.24615329f, 0.96923091f},
{-0.23344536f, 0.97236992f}, {-0.22069744f, 0.97534232f},
{-0.20791169f, 0.97814760f}, {-0.19509032f, 0.98078528f},
{-0.18223553f, 0.98325491f}, {-0.16934950f, 0.98555606f},
{-0.15643447f, 0.98768834f}, {-0.14349262f, 0.98965139f},
{-0.13052619f, 0.99144486f}, {-0.11753740f, 0.99306846f},
{-0.10452846f, 0.99452190f}, {-0.091501619f, 0.99580493f},
{-0.078459096f, 0.99691733f}, {-0.065403129f, 0.99785892f},
{-0.052335956f, 0.99862953f}, {-0.039259816f, 0.99922904f},
{-0.026176948f, 0.99965732f}, {-0.013089596f, 0.99991433f},
{-1.8369095e-16f, 1.0000000f}, {0.013089596f, 0.99991433f},
{0.026176948f, 0.99965732f}, {0.039259816f, 0.99922904f},
{0.052335956f, 0.99862953f}, {0.065403129f, 0.99785892f},
{0.078459096f, 0.99691733f}, {0.091501619f, 0.99580493f},
{0.10452846f, 0.99452190f}, {0.11753740f, 0.99306846f},
{0.13052619f, 0.99144486f}, {0.14349262f, 0.98965139f},
{0.15643447f, 0.98768834f}, {0.16934950f, 0.98555606f},
{0.18223553f, 0.98325491f}, {0.19509032f, 0.98078528f},
{0.20791169f, 0.97814760f}, {0.22069744f, 0.97534232f},
{0.23344536f, 0.97236992f}, {0.24615329f, 0.96923091f},
{0.25881905f, 0.96592583f}, {0.27144045f, 0.96245524f},
{0.28401534f, 0.95881973f}, {0.29654157f, 0.95501994f},
{0.30901699f, 0.95105652f}, {0.32143947f, 0.94693013f},
{0.33380686f, 0.94264149f}, {0.34611706f, 0.93819134f},
{0.35836795f, 0.93358043f}, {0.37055744f, 0.92880955f},
{0.38268343f, 0.92387953f}, {0.39474386f, 0.91879121f},
{0.40673664f, 0.91354546f}, {0.41865974f, 0.90814317f},
{0.43051110f, 0.90258528f}, {0.44228869f, 0.89687274f},
{0.45399050f, 0.89100652f}, {0.46561452f, 0.88498764f},
{0.47715876f, 0.87881711f}, {0.48862124f, 0.87249601f},
{0.50000000f, 0.86602540f}, {0.51129309f, 0.85940641f},
{0.52249856f, 0.85264016f}, {0.53361452f, 0.84572782f},
{0.54463904f, 0.83867057f}, {0.55557023f, 0.83146961f},
{0.56640624f, 0.82412619f}, {0.57714519f, 0.81664156f},
{0.58778525f, 0.80901699f}, {0.59832460f, 0.80125381f},
{0.60876143f, 0.79335334f}, {0.61909395f, 0.78531693f},
{0.62932039f, 0.77714596f}, {0.63943900f, 0.76884183f},
{0.64944805f, 0.76040597f}, {0.65934582f, 0.75183981f},
{0.66913061f, 0.74314483f}, {0.67880075f, 0.73432251f},
{0.68835458f, 0.72537437f}, {0.69779046f, 0.71630194f},
{0.70710678f, 0.70710678f}, {0.71630194f, 0.69779046f},
{0.72537437f, 0.68835458f}, {0.73432251f, 0.67880075f},
{0.74314483f, 0.66913061f}, {0.75183981f, 0.65934582f},
{0.76040597f, 0.64944805f}, {0.76884183f, 0.63943900f},
{0.77714596f, 0.62932039f}, {0.78531693f, 0.61909395f},
{0.79335334f, 0.60876143f}, {0.80125381f, 0.59832460f},
{0.80901699f, 0.58778525f}, {0.81664156f, 0.57714519f},
{0.82412619f, 0.56640624f}, {0.83146961f, 0.55557023f},
{0.83867057f, 0.54463904f}, {0.84572782f, 0.53361452f},
{0.85264016f, 0.52249856f}, {0.85940641f, 0.51129309f},
{0.86602540f, 0.50000000f}, {0.87249601f, 0.48862124f},
{0.87881711f, 0.47715876f}, {0.88498764f, 0.46561452f},
{0.89100652f, 0.45399050f}, {0.89687274f, 0.44228869f},
{0.90258528f, 0.43051110f}, {0.90814317f, 0.41865974f},
{0.91354546f, 0.40673664f}, {0.91879121f, 0.39474386f},
{0.92387953f, 0.38268343f}, {0.92880955f, 0.37055744f},
{0.93358043f, 0.35836795f}, {0.93819134f, 0.34611706f},
{0.94264149f, 0.33380686f}, {0.94693013f, 0.32143947f},
{0.95105652f, 0.30901699f}, {0.95501994f, 0.29654157f},
{0.95881973f, 0.28401534f}, {0.96245524f, 0.27144045f},
{0.96592583f, 0.25881905f}, {0.96923091f, 0.24615329f},
{0.97236992f, 0.23344536f}, {0.97534232f, 0.22069744f},
{0.97814760f, 0.20791169f}, {0.98078528f, 0.19509032f},
{0.98325491f, 0.18223553f}, {0.98555606f, 0.16934950f},
{0.98768834f, 0.15643447f}, {0.98965139f, 0.14349262f},
{0.99144486f, 0.13052619f}, {0.99306846f, 0.11753740f},
{0.99452190f, 0.10452846f}, {0.99580493f, 0.091501619f},
{0.99691733f, 0.078459096f}, {0.99785892f, 0.065403129f},
{0.99862953f, 0.052335956f}, {0.99922904f, 0.039259816f},
{0.99965732f, 0.026176948f}, {0.99991433f, 0.013089596f},
};
#ifndef FFT_BITREV480
#define FFT_BITREV480
static const opus_int16 fft_bitrev480[480] = {
0, 96, 192, 288, 384, 32, 128, 224, 320, 416, 64, 160, 256, 352, 448,
8, 104, 200, 296, 392, 40, 136, 232, 328, 424, 72, 168, 264, 360, 456,
16, 112, 208, 304, 400, 48, 144, 240, 336, 432, 80, 176, 272, 368, 464,
24, 120, 216, 312, 408, 56, 152, 248, 344, 440, 88, 184, 280, 376, 472,
4, 100, 196, 292, 388, 36, 132, 228, 324, 420, 68, 164, 260, 356, 452,
12, 108, 204, 300, 396, 44, 140, 236, 332, 428, 76, 172, 268, 364, 460,
20, 116, 212, 308, 404, 52, 148, 244, 340, 436, 84, 180, 276, 372, 468,
28, 124, 220, 316, 412, 60, 156, 252, 348, 444, 92, 188, 284, 380, 476,
1, 97, 193, 289, 385, 33, 129, 225, 321, 417, 65, 161, 257, 353, 449,
9, 105, 201, 297, 393, 41, 137, 233, 329, 425, 73, 169, 265, 361, 457,
17, 113, 209, 305, 401, 49, 145, 241, 337, 433, 81, 177, 273, 369, 465,
25, 121, 217, 313, 409, 57, 153, 249, 345, 441, 89, 185, 281, 377, 473,
5, 101, 197, 293, 389, 37, 133, 229, 325, 421, 69, 165, 261, 357, 453,
13, 109, 205, 301, 397, 45, 141, 237, 333, 429, 77, 173, 269, 365, 461,
21, 117, 213, 309, 405, 53, 149, 245, 341, 437, 85, 181, 277, 373, 469,
29, 125, 221, 317, 413, 61, 157, 253, 349, 445, 93, 189, 285, 381, 477,
2, 98, 194, 290, 386, 34, 130, 226, 322, 418, 66, 162, 258, 354, 450,
10, 106, 202, 298, 394, 42, 138, 234, 330, 426, 74, 170, 266, 362, 458,
18, 114, 210, 306, 402, 50, 146, 242, 338, 434, 82, 178, 274, 370, 466,
26, 122, 218, 314, 410, 58, 154, 250, 346, 442, 90, 186, 282, 378, 474,
6, 102, 198, 294, 390, 38, 134, 230, 326, 422, 70, 166, 262, 358, 454,
14, 110, 206, 302, 398, 46, 142, 238, 334, 430, 78, 174, 270, 366, 462,
22, 118, 214, 310, 406, 54, 150, 246, 342, 438, 86, 182, 278, 374, 470,
30, 126, 222, 318, 414, 62, 158, 254, 350, 446, 94, 190, 286, 382, 478,
3, 99, 195, 291, 387, 35, 131, 227, 323, 419, 67, 163, 259, 355, 451,
11, 107, 203, 299, 395, 43, 139, 235, 331, 427, 75, 171, 267, 363, 459,
19, 115, 211, 307, 403, 51, 147, 243, 339, 435, 83, 179, 275, 371, 467,
27, 123, 219, 315, 411, 59, 155, 251, 347, 443, 91, 187, 283, 379, 475,
7, 103, 199, 295, 391, 39, 135, 231, 327, 423, 71, 167, 263, 359, 455,
15, 111, 207, 303, 399, 47, 143, 239, 335, 431, 79, 175, 271, 367, 463,
23, 119, 215, 311, 407, 55, 151, 247, 343, 439, 87, 183, 279, 375, 471,
31, 127, 223, 319, 415, 63, 159, 255, 351, 447, 95, 191, 287, 383, 479,
};
#endif
#ifndef FFT_BITREV240
#define FFT_BITREV240
static const opus_int16 fft_bitrev240[240] = {
0, 48, 96, 144, 192, 16, 64, 112, 160, 208, 32, 80, 128, 176, 224,
4, 52, 100, 148, 196, 20, 68, 116, 164, 212, 36, 84, 132, 180, 228,
8, 56, 104, 152, 200, 24, 72, 120, 168, 216, 40, 88, 136, 184, 232,
12, 60, 108, 156, 204, 28, 76, 124, 172, 220, 44, 92, 140, 188, 236,
1, 49, 97, 145, 193, 17, 65, 113, 161, 209, 33, 81, 129, 177, 225,
5, 53, 101, 149, 197, 21, 69, 117, 165, 213, 37, 85, 133, 181, 229,
9, 57, 105, 153, 201, 25, 73, 121, 169, 217, 41, 89, 137, 185, 233,
13, 61, 109, 157, 205, 29, 77, 125, 173, 221, 45, 93, 141, 189, 237,
2, 50, 98, 146, 194, 18, 66, 114, 162, 210, 34, 82, 130, 178, 226,
6, 54, 102, 150, 198, 22, 70, 118, 166, 214, 38, 86, 134, 182, 230,
10, 58, 106, 154, 202, 26, 74, 122, 170, 218, 42, 90, 138, 186, 234,
14, 62, 110, 158, 206, 30, 78, 126, 174, 222, 46, 94, 142, 190, 238,
3, 51, 99, 147, 195, 19, 67, 115, 163, 211, 35, 83, 131, 179, 227,
7, 55, 103, 151, 199, 23, 71, 119, 167, 215, 39, 87, 135, 183, 231,
11, 59, 107, 155, 203, 27, 75, 123, 171, 219, 43, 91, 139, 187, 235,
15, 63, 111, 159, 207, 31, 79, 127, 175, 223, 47, 95, 143, 191, 239,
};
#endif
#ifndef FFT_BITREV120
#define FFT_BITREV120
static const opus_int16 fft_bitrev120[120] = {
0, 24, 48, 72, 96, 8, 32, 56, 80, 104, 16, 40, 64, 88, 112,
4, 28, 52, 76, 100, 12, 36, 60, 84, 108, 20, 44, 68, 92, 116,
1, 25, 49, 73, 97, 9, 33, 57, 81, 105, 17, 41, 65, 89, 113,
5, 29, 53, 77, 101, 13, 37, 61, 85, 109, 21, 45, 69, 93, 117,
2, 26, 50, 74, 98, 10, 34, 58, 82, 106, 18, 42, 66, 90, 114,
6, 30, 54, 78, 102, 14, 38, 62, 86, 110, 22, 46, 70, 94, 118,
3, 27, 51, 75, 99, 11, 35, 59, 83, 107, 19, 43, 67, 91, 115,
7, 31, 55, 79, 103, 15, 39, 63, 87, 111, 23, 47, 71, 95, 119,
};
#endif
#ifndef FFT_BITREV60
#define FFT_BITREV60
static const opus_int16 fft_bitrev60[60] = {
0, 12, 24, 36, 48, 4, 16, 28, 40, 52, 8, 20, 32, 44, 56,
1, 13, 25, 37, 49, 5, 17, 29, 41, 53, 9, 21, 33, 45, 57,
2, 14, 26, 38, 50, 6, 18, 30, 42, 54, 10, 22, 34, 46, 58,
3, 15, 27, 39, 51, 7, 19, 31, 43, 55, 11, 23, 35, 47, 59,
};
#endif
#ifndef FFT_STATE48000_960_0
#define FFT_STATE48000_960_0
static const kiss_fft_state fft_state48000_960_0 = {
480, /* nfft */
0.002083333f, /* scale */
-1, /* shift */
{5, 96, 3, 32, 4, 8, 2, 4, 4, 1, 0, 0, 0, 0, 0, 0, }, /* factors */
fft_bitrev480, /* bitrev */
fft_twiddles48000_960, /* bitrev */
#ifdef OVERRIDE_FFT
(arch_fft_state *)&cfg_arch_480,
#else
NULL,
#endif
};
#endif
#ifndef FFT_STATE48000_960_1
#define FFT_STATE48000_960_1
static const kiss_fft_state fft_state48000_960_1 = {
240, /* nfft */
0.004166667f, /* scale */
1, /* shift */
{5, 48, 3, 16, 4, 4, 4, 1, 0, 0, 0, 0, 0, 0, 0, 0, }, /* factors */
fft_bitrev240, /* bitrev */
fft_twiddles48000_960, /* bitrev */
#ifdef OVERRIDE_FFT
(arch_fft_state *)&cfg_arch_240,
#else
NULL,
#endif
};
#endif
#ifndef FFT_STATE48000_960_2
#define FFT_STATE48000_960_2
static const kiss_fft_state fft_state48000_960_2 = {
120, /* nfft */
0.008333333f, /* scale */
2, /* shift */
{5, 24, 3, 8, 2, 4, 4, 1, 0, 0, 0, 0, 0, 0, 0, 0, }, /* factors */
fft_bitrev120, /* bitrev */
fft_twiddles48000_960, /* bitrev */
#ifdef OVERRIDE_FFT
(arch_fft_state *)&cfg_arch_120,
#else
NULL,
#endif
};
#endif
#ifndef FFT_STATE48000_960_3
#define FFT_STATE48000_960_3
static const kiss_fft_state fft_state48000_960_3 = {
60, /* nfft */
0.016666667f, /* scale */
3, /* shift */
{5, 12, 3, 4, 4, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, /* factors */
fft_bitrev60, /* bitrev */
fft_twiddles48000_960, /* bitrev */
#ifdef OVERRIDE_FFT
(arch_fft_state *)&cfg_arch_60,
#else
NULL,
#endif
};
#endif
#endif
#ifndef MDCT_TWIDDLES960
#define MDCT_TWIDDLES960
static const opus_val16 mdct_twiddles960[1800] = {
0.99999994f, 0.99999321f, 0.99997580f, 0.99994773f, 0.99990886f,
0.99985933f, 0.99979913f, 0.99972820f, 0.99964654f, 0.99955416f,
0.99945110f, 0.99933738f, 0.99921292f, 0.99907774f, 0.99893188f,
0.99877530f, 0.99860805f, 0.99843007f, 0.99824142f, 0.99804211f,
0.99783206f, 0.99761140f, 0.99737996f, 0.99713790f, 0.99688518f,
0.99662173f, 0.99634761f, 0.99606287f, 0.99576741f, 0.99546129f,
0.99514455f, 0.99481714f, 0.99447906f, 0.99413031f, 0.99377096f,
0.99340093f, 0.99302030f, 0.99262899f, 0.99222708f, 0.99181455f,
0.99139136f, 0.99095762f, 0.99051321f, 0.99005818f, 0.98959261f,
0.98911643f, 0.98862964f, 0.98813224f, 0.98762429f, 0.98710573f,
0.98657662f, 0.98603696f, 0.98548669f, 0.98492593f, 0.98435456f,
0.98377270f, 0.98318028f, 0.98257732f, 0.98196387f, 0.98133987f,
0.98070538f, 0.98006040f, 0.97940493f, 0.97873890f, 0.97806245f,
0.97737551f, 0.97667813f, 0.97597027f, 0.97525197f, 0.97452319f,
0.97378403f, 0.97303438f, 0.97227436f, 0.97150391f, 0.97072303f,
0.96993178f, 0.96913016f, 0.96831810f, 0.96749574f, 0.96666300f,
0.96581990f, 0.96496642f, 0.96410263f, 0.96322852f, 0.96234411f,
0.96144938f, 0.96054435f, 0.95962906f, 0.95870346f, 0.95776761f,
0.95682150f, 0.95586514f, 0.95489854f, 0.95392174f, 0.95293468f,
0.95193744f, 0.95093000f, 0.94991243f, 0.94888461f, 0.94784665f,
0.94679856f, 0.94574034f, 0.94467193f, 0.94359344f, 0.94250488f,
0.94140619f, 0.94029742f, 0.93917859f, 0.93804967f, 0.93691075f,
0.93576175f, 0.93460274f, 0.93343377f, 0.93225473f, 0.93106574f,
0.92986679f, 0.92865789f, 0.92743903f, 0.92621022f, 0.92497152f,
0.92372292f, 0.92246443f, 0.92119598f, 0.91991776f, 0.91862965f,
0.91733170f, 0.91602397f, 0.91470635f, 0.91337901f, 0.91204184f,
0.91069490f, 0.90933824f, 0.90797186f, 0.90659571f, 0.90520984f,
0.90381432f, 0.90240908f, 0.90099424f, 0.89956969f, 0.89813554f,
0.89669174f, 0.89523834f, 0.89377540f, 0.89230281f, 0.89082074f,
0.88932908f, 0.88782793f, 0.88631725f, 0.88479710f, 0.88326746f,
0.88172835f, 0.88017982f, 0.87862182f, 0.87705445f, 0.87547767f,
0.87389153f, 0.87229604f, 0.87069118f, 0.86907703f, 0.86745358f,
0.86582077f, 0.86417878f, 0.86252749f, 0.86086690f, 0.85919720f,
0.85751826f, 0.85583007f, 0.85413277f, 0.85242635f, 0.85071075f,
0.84898609f, 0.84725231f, 0.84550947f, 0.84375757f, 0.84199661f,
0.84022665f, 0.83844769f, 0.83665979f, 0.83486289f, 0.83305705f,
0.83124226f, 0.82941860f, 0.82758605f, 0.82574469f, 0.82389444f,
0.82203537f, 0.82016748f, 0.81829083f, 0.81640542f, 0.81451124f,
0.81260836f, 0.81069672f, 0.80877650f, 0.80684757f, 0.80490994f,
0.80296379f, 0.80100900f, 0.79904562f, 0.79707366f, 0.79509324f,
0.79310423f, 0.79110676f, 0.78910083f, 0.78708643f, 0.78506362f,
0.78303236f, 0.78099275f, 0.77894479f, 0.77688843f, 0.77482378f,
0.77275085f, 0.77066964f, 0.76858020f, 0.76648247f, 0.76437658f,
0.76226246f, 0.76014024f, 0.75800985f, 0.75587130f, 0.75372469f,
0.75157005f, 0.74940729f, 0.74723655f, 0.74505776f, 0.74287105f,
0.74067634f, 0.73847371f, 0.73626316f, 0.73404479f, 0.73181850f,
0.72958434f, 0.72734243f, 0.72509271f, 0.72283524f, 0.72057003f,
0.71829706f, 0.71601641f, 0.71372813f, 0.71143216f, 0.70912862f,
0.70681745f, 0.70449871f, 0.70217246f, 0.69983864f, 0.69749737f,
0.69514859f, 0.69279242f, 0.69042879f, 0.68805778f, 0.68567938f,
0.68329364f, 0.68090063f, 0.67850029f, 0.67609268f, 0.67367786f,
0.67125577f, 0.66882652f, 0.66639012f, 0.66394657f, 0.66149592f,
0.65903819f, 0.65657341f, 0.65410155f, 0.65162271f, 0.64913690f,
0.64664418f, 0.64414448f, 0.64163786f, 0.63912445f, 0.63660413f,
0.63407701f, 0.63154310f, 0.62900239f, 0.62645501f, 0.62390089f,
0.62134010f, 0.61877263f, 0.61619854f, 0.61361790f, 0.61103064f,
0.60843682f, 0.60583651f, 0.60322970f, 0.60061646f, 0.59799677f,
0.59537065f, 0.59273821f, 0.59009939f, 0.58745426f, 0.58480281f,
0.58214509f, 0.57948118f, 0.57681108f, 0.57413477f, 0.57145232f,
0.56876373f, 0.56606907f, 0.56336832f, 0.56066155f, 0.55794877f,
0.55523002f, 0.55250537f, 0.54977477f, 0.54703826f, 0.54429591f,
0.54154772f, 0.53879374f, 0.53603399f, 0.53326851f, 0.53049731f,
0.52772039f, 0.52493787f, 0.52214974f, 0.51935595f, 0.51655668f,
0.51375180f, 0.51094145f, 0.50812566f, 0.50530440f, 0.50247771f,
0.49964568f, 0.49680826f, 0.49396557f, 0.49111754f, 0.48826426f,
0.48540577f, 0.48254207f, 0.47967321f, 0.47679919f, 0.47392011f,
0.47103590f, 0.46814668f, 0.46525243f, 0.46235323f, 0.45944905f,
0.45653993f, 0.45362595f, 0.45070711f, 0.44778344f, 0.44485497f,
0.44192174f, 0.43898380f, 0.43604112f, 0.43309379f, 0.43014181f,
0.42718524f, 0.42422408f, 0.42125839f, 0.41828820f, 0.41531351f,
0.41233435f, 0.40935081f, 0.40636289f, 0.40337059f, 0.40037400f,
0.39737311f, 0.39436796f, 0.39135858f, 0.38834500f, 0.38532731f,
0.38230544f, 0.37927949f, 0.37624949f, 0.37321547f, 0.37017745f,
0.36713544f, 0.36408952f, 0.36103970f, 0.35798600f, 0.35492846f,
0.35186714f, 0.34880206f, 0.34573323f, 0.34266070f, 0.33958447f,
0.33650464f, 0.33342120f, 0.33033419f, 0.32724363f, 0.32414958f,
0.32105204f, 0.31795108f, 0.31484672f, 0.31173897f, 0.30862790f,
0.30551350f, 0.30239585f, 0.29927495f, 0.29615086f, 0.29302359f,
0.28989318f, 0.28675964f, 0.28362307f, 0.28048345f, 0.27734083f,
0.27419522f, 0.27104670f, 0.26789525f, 0.26474094f, 0.26158381f,
0.25842386f, 0.25526115f, 0.25209570f, 0.24892756f, 0.24575676f,
0.24258332f, 0.23940729f, 0.23622867f, 0.23304754f, 0.22986393f,
0.22667783f, 0.22348931f, 0.22029841f, 0.21710514f, 0.21390954f,
0.21071166f, 0.20751151f, 0.20430915f, 0.20110460f, 0.19789790f,
0.19468907f, 0.19147816f, 0.18826519f, 0.18505022f, 0.18183327f,
0.17861435f, 0.17539354f, 0.17217083f, 0.16894630f, 0.16571994f,
0.16249183f, 0.15926196f, 0.15603039f, 0.15279715f, 0.14956227f,
0.14632578f, 0.14308774f, 0.13984816f, 0.13660708f, 0.13336454f,
0.13012058f, 0.12687522f, 0.12362850f, 0.12038045f, 0.11713112f,
0.11388054f, 0.11062872f, 0.10737573f, 0.10412160f, 0.10086634f,
0.097609997f, 0.094352618f, 0.091094226f, 0.087834857f, 0.084574550f,
0.081313334f, 0.078051247f, 0.074788325f, 0.071524605f, 0.068260118f,
0.064994894f, 0.061728980f, 0.058462404f, 0.055195201f, 0.051927410f,
0.048659060f, 0.045390189f, 0.042120833f, 0.038851023f, 0.035580799f,
0.032310195f, 0.029039243f, 0.025767982f, 0.022496443f, 0.019224664f,
0.015952680f, 0.012680525f, 0.0094082337f, 0.0061358409f, 0.0028633832f,
-0.00040910527f, -0.0036815894f, -0.0069540343f, -0.010226404f, -0.013498665f,
-0.016770782f, -0.020042717f, -0.023314439f, -0.026585912f, -0.029857099f,
-0.033127967f, -0.036398482f, -0.039668605f, -0.042938303f, -0.046207540f,
-0.049476285f, -0.052744497f, -0.056012146f, -0.059279196f, -0.062545612f,
-0.065811358f, -0.069076397f, -0.072340697f, -0.075604223f, -0.078866936f,
-0.082128808f, -0.085389800f, -0.088649876f, -0.091909006f, -0.095167145f,
-0.098424271f, -0.10168034f, -0.10493532f, -0.10818918f, -0.11144188f,
-0.11469338f, -0.11794366f, -0.12119267f, -0.12444039f, -0.12768677f,
-0.13093179f, -0.13417540f, -0.13741758f, -0.14065829f, -0.14389749f,
-0.14713514f, -0.15037122f, -0.15360570f, -0.15683852f, -0.16006967f,
-0.16329910f, -0.16652679f, -0.16975269f, -0.17297678f, -0.17619900f,
-0.17941935f, -0.18263777f, -0.18585424f, -0.18906870f, -0.19228116f,
-0.19549155f, -0.19869985f, -0.20190603f, -0.20511003f, -0.20831184f,
-0.21151142f, -0.21470875f, -0.21790376f, -0.22109644f, -0.22428675f,
-0.22747467f, -0.23066014f, -0.23384315f, -0.23702365f, -0.24020162f,
-0.24337701f, -0.24654980f, -0.24971995f, -0.25288740f, -0.25605217f,
-0.25921419f, -0.26237345f, -0.26552987f, -0.26868346f, -0.27183419f,
-0.27498198f, -0.27812684f, -0.28126872f, -0.28440759f, -0.28754342f,
-0.29067615f, -0.29380578f, -0.29693225f, -0.30005556f, -0.30317566f,
-0.30629250f, -0.30940607f, -0.31251630f, -0.31562322f, -0.31872672f,
-0.32182685f, -0.32492352f, -0.32801670f, -0.33110636f, -0.33419248f,
-0.33727503f, -0.34035397f, -0.34342924f, -0.34650084f, -0.34956875f,
-0.35263291f, -0.35569328f, -0.35874987f, -0.36180258f, -0.36485144f,
-0.36789638f, -0.37093741f, -0.37397444f, -0.37700745f, -0.38003644f,
-0.38306138f, -0.38608220f, -0.38909888f, -0.39211139f, -0.39511973f,
-0.39812380f, -0.40112361f, -0.40411916f, -0.40711036f, -0.41009718f,
-0.41307965f, -0.41605768f, -0.41903123f, -0.42200032f, -0.42496487f,
-0.42792490f, -0.43088034f, -0.43383113f, -0.43677729f, -0.43971881f,
-0.44265559f, -0.44558764f, -0.44851488f, -0.45143735f, -0.45435500f,
-0.45726776f, -0.46017563f, -0.46307856f, -0.46597654f, -0.46886954f,
-0.47175750f, -0.47464043f, -0.47751826f, -0.48039100f, -0.48325855f,
-0.48612097f, -0.48897815f, -0.49183011f, -0.49467680f, -0.49751821f,
-0.50035429f, -0.50318497f, -0.50601029f, -0.50883019f, -0.51164466f,
-0.51445359f, -0.51725709f, -0.52005500f, -0.52284735f, -0.52563411f,
-0.52841520f, -0.53119069f, -0.53396046f, -0.53672451f, -0.53948283f,
-0.54223537f, -0.54498214f, -0.54772300f, -0.55045801f, -0.55318713f,
-0.55591035f, -0.55862761f, -0.56133890f, -0.56404412f, -0.56674337f,
-0.56943649f, -0.57212353f, -0.57480448f, -0.57747924f, -0.58014780f,
-0.58281022f, -0.58546633f, -0.58811617f, -0.59075975f, -0.59339696f,
-0.59602785f, -0.59865236f, -0.60127044f, -0.60388207f, -0.60648727f,
-0.60908598f, -0.61167812f, -0.61426371f, -0.61684275f, -0.61941516f,
-0.62198097f, -0.62454009f, -0.62709254f, -0.62963831f, -0.63217729f,
-0.63470948f, -0.63723493f, -0.63975352f, -0.64226526f, -0.64477009f,
-0.64726806f, -0.64975911f, -0.65224314f, -0.65472025f, -0.65719032f,
-0.65965337f, -0.66210932f, -0.66455823f, -0.66700000f, -0.66943461f,
-0.67186207f, -0.67428231f, -0.67669535f, -0.67910111f, -0.68149966f,
-0.68389088f, -0.68627477f, -0.68865126f, -0.69102043f, -0.69338220f,
-0.69573659f, -0.69808346f, -0.70042288f, -0.70275480f, -0.70507920f,
-0.70739603f, -0.70970529f, -0.71200693f, -0.71430099f, -0.71658736f,
-0.71886611f, -0.72113711f, -0.72340041f, -0.72565591f, -0.72790372f,
-0.73014367f, -0.73237586f, -0.73460019f, -0.73681659f, -0.73902518f,
-0.74122584f, -0.74341851f, -0.74560326f, -0.74778003f, -0.74994880f,
-0.75210953f, -0.75426215f, -0.75640678f, -0.75854325f, -0.76067162f,
-0.76279181f, -0.76490390f, -0.76700771f, -0.76910341f, -0.77119076f,
-0.77326995f, -0.77534080f, -0.77740335f, -0.77945763f, -0.78150350f,
-0.78354102f, -0.78557014f, -0.78759086f, -0.78960317f, -0.79160696f,
-0.79360235f, -0.79558921f, -0.79756755f, -0.79953730f, -0.80149853f,
-0.80345118f, -0.80539525f, -0.80733067f, -0.80925739f, -0.81117553f,
-0.81308490f, -0.81498563f, -0.81687760f, -0.81876087f, -0.82063532f,
-0.82250100f, -0.82435787f, -0.82620591f, -0.82804507f, -0.82987541f,
-0.83169687f, -0.83350939f, -0.83531296f, -0.83710766f, -0.83889335f,
-0.84067005f, -0.84243774f, -0.84419644f, -0.84594607f, -0.84768665f,
-0.84941816f, -0.85114056f, -0.85285389f, -0.85455805f, -0.85625303f,
-0.85793889f, -0.85961550f, -0.86128294f, -0.86294121f, -0.86459017f,
-0.86622989f, -0.86786032f, -0.86948150f, -0.87109333f, -0.87269586f,
-0.87428904f, -0.87587279f, -0.87744725f, -0.87901229f, -0.88056785f,
-0.88211405f, -0.88365078f, -0.88517809f, -0.88669586f, -0.88820416f,
-0.88970292f, -0.89119220f, -0.89267188f, -0.89414203f, -0.89560264f,
-0.89705360f, -0.89849502f, -0.89992678f, -0.90134889f, -0.90276134f,
-0.90416414f, -0.90555727f, -0.90694070f, -0.90831441f, -0.90967834f,
-0.91103262f, -0.91237706f, -0.91371179f, -0.91503674f, -0.91635185f,
-0.91765714f, -0.91895264f, -0.92023826f, -0.92151409f, -0.92277998f,
-0.92403603f, -0.92528218f, -0.92651838f, -0.92774469f, -0.92896110f,
-0.93016750f, -0.93136400f, -0.93255049f, -0.93372697f, -0.93489349f,
-0.93604994f, -0.93719643f, -0.93833286f, -0.93945926f, -0.94057560f,
-0.94168180f, -0.94277799f, -0.94386405f, -0.94494003f, -0.94600588f,
-0.94706154f, -0.94810712f, -0.94914252f, -0.95016778f, -0.95118284f,
-0.95218778f, -0.95318246f, -0.95416695f, -0.95514119f, -0.95610523f,
-0.95705903f, -0.95800257f, -0.95893586f, -0.95985889f, -0.96077162f,
-0.96167403f, -0.96256620f, -0.96344805f, -0.96431959f, -0.96518075f,
-0.96603161f, -0.96687216f, -0.96770233f, -0.96852213f, -0.96933156f,
-0.97013056f, -0.97091925f, -0.97169751f, -0.97246534f, -0.97322279f,
-0.97396982f, -0.97470641f, -0.97543252f, -0.97614825f, -0.97685349f,
-0.97754824f, -0.97823256f, -0.97890645f, -0.97956979f, -0.98022264f,
-0.98086500f, -0.98149687f, -0.98211825f, -0.98272908f, -0.98332942f,
-0.98391914f, -0.98449844f, -0.98506713f, -0.98562527f, -0.98617285f,
-0.98670989f, -0.98723638f, -0.98775226f, -0.98825759f, -0.98875231f,
-0.98923647f, -0.98971003f, -0.99017298f, -0.99062532f, -0.99106705f,
-0.99149817f, -0.99191868f, -0.99232858f, -0.99272782f, -0.99311644f,
-0.99349445f, -0.99386179f, -0.99421853f, -0.99456459f, -0.99489999f,
-0.99522477f, -0.99553883f, -0.99584228f, -0.99613506f, -0.99641716f,
-0.99668860f, -0.99694937f, -0.99719942f, -0.99743885f, -0.99766755f,
-0.99788558f, -0.99809295f, -0.99828959f, -0.99847561f, -0.99865085f,
-0.99881548f, -0.99896932f, -0.99911255f, -0.99924499f, -0.99936682f,
-0.99947786f, -0.99957830f, -0.99966794f, -0.99974692f, -0.99981517f,
-0.99987274f, -0.99991959f, -0.99995571f, -0.99998116f, -0.99999589f,
0.99999964f, 0.99997288f, 0.99990326f, 0.99979085f, 0.99963558f,
0.99943751f, 0.99919659f, 0.99891287f, 0.99858636f, 0.99821711f,
0.99780506f, 0.99735034f, 0.99685282f, 0.99631262f, 0.99572974f,
0.99510419f, 0.99443603f, 0.99372530f, 0.99297196f, 0.99217612f,
0.99133772f, 0.99045694f, 0.98953366f, 0.98856801f, 0.98756003f,
0.98650974f, 0.98541719f, 0.98428243f, 0.98310548f, 0.98188645f,
0.98062533f, 0.97932225f, 0.97797716f, 0.97659022f, 0.97516143f,
0.97369087f, 0.97217858f, 0.97062469f, 0.96902919f, 0.96739221f,
0.96571374f, 0.96399397f, 0.96223283f, 0.96043050f, 0.95858705f,
0.95670253f, 0.95477700f, 0.95281059f, 0.95080340f, 0.94875544f,
0.94666684f, 0.94453770f, 0.94236809f, 0.94015813f, 0.93790787f,
0.93561745f, 0.93328691f, 0.93091643f, 0.92850608f, 0.92605597f,
0.92356616f, 0.92103678f, 0.91846794f, 0.91585976f, 0.91321236f,
0.91052586f, 0.90780038f, 0.90503591f, 0.90223277f, 0.89939094f,
0.89651060f, 0.89359182f, 0.89063478f, 0.88763964f, 0.88460642f,
0.88153529f, 0.87842643f, 0.87527996f, 0.87209594f, 0.86887461f,
0.86561602f, 0.86232042f, 0.85898781f, 0.85561842f, 0.85221243f,
0.84876984f, 0.84529096f, 0.84177583f, 0.83822471f, 0.83463764f,
0.83101481f, 0.82735640f, 0.82366252f, 0.81993335f, 0.81616908f,
0.81236988f, 0.80853581f, 0.80466717f, 0.80076402f, 0.79682660f,
0.79285502f, 0.78884947f, 0.78481019f, 0.78073722f, 0.77663082f,
0.77249116f, 0.76831841f, 0.76411277f, 0.75987434f, 0.75560343f,
0.75130010f, 0.74696463f, 0.74259710f, 0.73819780f, 0.73376691f,
0.72930455f, 0.72481096f, 0.72028631f, 0.71573079f, 0.71114463f,
0.70652801f, 0.70188117f, 0.69720417f, 0.69249737f, 0.68776089f,
0.68299496f, 0.67819971f, 0.67337549f, 0.66852236f, 0.66364062f,
0.65873051f, 0.65379208f, 0.64882571f, 0.64383155f, 0.63880974f,
0.63376063f, 0.62868434f, 0.62358117f, 0.61845124f, 0.61329484f,
0.60811216f, 0.60290343f, 0.59766883f, 0.59240872f, 0.58712316f,
0.58181250f, 0.57647687f, 0.57111657f, 0.56573176f, 0.56032276f,
0.55488980f, 0.54943299f, 0.54395270f, 0.53844911f, 0.53292239f,
0.52737290f, 0.52180082f, 0.51620632f, 0.51058978f, 0.50495136f,
0.49929130f, 0.49360985f, 0.48790723f, 0.48218375f, 0.47643960f,
0.47067502f, 0.46489030f, 0.45908567f, 0.45326138f, 0.44741765f,
0.44155475f, 0.43567297f, 0.42977250f, 0.42385364f, 0.41791660f,
0.41196167f, 0.40598908f, 0.39999911f, 0.39399201f, 0.38796803f,
0.38192743f, 0.37587047f, 0.36979741f, 0.36370850f, 0.35760403f,
0.35148421f, 0.34534934f, 0.33919969f, 0.33303553f, 0.32685706f,
0.32066461f, 0.31445843f, 0.30823877f, 0.30200592f, 0.29576012f,
0.28950164f, 0.28323078f, 0.27694780f, 0.27065292f, 0.26434645f,
0.25802869f, 0.25169984f, 0.24536023f, 0.23901010f, 0.23264973f,
0.22627939f, 0.21989937f, 0.21350993f, 0.20711134f, 0.20070387f,
0.19428782f, 0.18786344f, 0.18143101f, 0.17499080f, 0.16854310f,
0.16208819f, 0.15562633f, 0.14915779f, 0.14268288f, 0.13620184f,
0.12971498f, 0.12322257f, 0.11672486f, 0.11022217f, 0.10371475f,
0.097202882f, 0.090686858f, 0.084166944f, 0.077643424f, 0.071116582f,
0.064586692f, 0.058054037f, 0.051518895f, 0.044981543f, 0.038442269f,
0.031901345f, 0.025359053f, 0.018815678f, 0.012271495f, 0.0057267868f,
-0.00081816671f, -0.0073630852f, -0.013907688f, -0.020451695f, -0.026994826f,
-0.033536803f, -0.040077340f, -0.046616159f, -0.053152986f, -0.059687532f,
-0.066219524f, -0.072748676f, -0.079274714f, -0.085797355f, -0.092316322f,
-0.098831341f, -0.10534211f, -0.11184838f, -0.11834986f, -0.12484626f,
-0.13133731f, -0.13782275f, -0.14430228f, -0.15077563f, -0.15724251f,
-0.16370267f, -0.17015581f, -0.17660165f, -0.18303993f, -0.18947038f,
-0.19589271f, -0.20230664f, -0.20871192f, -0.21510825f, -0.22149536f,
-0.22787298f, -0.23424086f, -0.24059868f, -0.24694622f, -0.25328314f,
-0.25960925f, -0.26592422f, -0.27222782f, -0.27851975f, -0.28479972f,
-0.29106751f, -0.29732284f, -0.30356544f, -0.30979502f, -0.31601134f,
-0.32221413f, -0.32840309f, -0.33457801f, -0.34073856f, -0.34688455f,
-0.35301566f, -0.35913166f, -0.36523229f, -0.37131724f, -0.37738630f,
-0.38343921f, -0.38947567f, -0.39549544f, -0.40149832f, -0.40748394f,
-0.41345215f, -0.41940263f, -0.42533514f, -0.43124944f, -0.43714526f,
-0.44302234f, -0.44888046f, -0.45471936f, -0.46053877f, -0.46633846f,
-0.47211814f, -0.47787762f, -0.48361665f, -0.48933494f, -0.49503228f,
-0.50070840f, -0.50636309f, -0.51199609f, -0.51760709f, -0.52319598f,
-0.52876246f, -0.53430629f, -0.53982723f, -0.54532504f, -0.55079949f,
-0.55625033f, -0.56167740f, -0.56708032f, -0.57245898f, -0.57781315f,
-0.58314258f, -0.58844697f, -0.59372622f, -0.59897995f, -0.60420811f,
-0.60941035f, -0.61458647f, -0.61973625f, -0.62485951f, -0.62995601f,
-0.63502556f, -0.64006782f, -0.64508271f, -0.65007001f, -0.65502942f,
-0.65996075f, -0.66486382f, -0.66973841f, -0.67458433f, -0.67940134f,
-0.68418926f, -0.68894786f, -0.69367695f, -0.69837630f, -0.70304573f,
-0.70768511f, -0.71229410f, -0.71687263f, -0.72142041f, -0.72593731f,
-0.73042315f, -0.73487765f, -0.73930067f, -0.74369204f, -0.74805158f,
-0.75237900f, -0.75667429f, -0.76093709f, -0.76516730f, -0.76936477f,
-0.77352923f, -0.77766061f, -0.78175867f, -0.78582323f, -0.78985411f,
-0.79385114f, -0.79781419f, -0.80174309f, -0.80563760f, -0.80949765f,
-0.81332302f, -0.81711352f, -0.82086903f, -0.82458937f, -0.82827437f,
-0.83192390f, -0.83553779f, -0.83911592f, -0.84265804f, -0.84616417f,
-0.84963393f, -0.85306740f, -0.85646427f, -0.85982448f, -0.86314780f,
-0.86643422f, -0.86968350f, -0.87289548f, -0.87607014f, -0.87920725f,
-0.88230664f, -0.88536829f, -0.88839203f, -0.89137769f, -0.89432514f,
-0.89723432f, -0.90010506f, -0.90293723f, -0.90573072f, -0.90848541f,
-0.91120118f, -0.91387796f, -0.91651553f, -0.91911387f, -0.92167282f,
-0.92419231f, -0.92667222f, -0.92911243f, -0.93151283f, -0.93387336f,
-0.93619382f, -0.93847424f, -0.94071442f, -0.94291431f, -0.94507378f,
-0.94719279f, -0.94927126f, -0.95130903f, -0.95330608f, -0.95526224f,
-0.95717752f, -0.95905179f, -0.96088499f, -0.96267700f, -0.96442777f,
-0.96613729f, -0.96780539f, -0.96943200f, -0.97101706f, -0.97256058f,
-0.97406244f, -0.97552258f, -0.97694093f, -0.97831738f, -0.97965199f,
-0.98094457f, -0.98219514f, -0.98340368f, -0.98457009f, -0.98569429f,
-0.98677629f, -0.98781598f, -0.98881340f, -0.98976845f, -0.99068111f,
-0.99155134f, -0.99237907f, -0.99316430f, -0.99390697f, -0.99460709f,
-0.99526459f, -0.99587947f, -0.99645168f, -0.99698120f, -0.99746799f,
-0.99791211f, -0.99831343f, -0.99867201f, -0.99898779f, -0.99926084f,
-0.99949104f, -0.99967843f, -0.99982297f, -0.99992472f, -0.99998361f,
0.99999869f, 0.99989158f, 0.99961317f, 0.99916345f, 0.99854255f,
0.99775058f, 0.99678761f, 0.99565387f, 0.99434954f, 0.99287480f,
0.99122995f, 0.98941529f, 0.98743105f, 0.98527765f, 0.98295540f,
0.98046476f, 0.97780609f, 0.97497988f, 0.97198665f, 0.96882683f,
0.96550101f, 0.96200979f, 0.95835376f, 0.95453346f, 0.95054960f,
0.94640291f, 0.94209403f, 0.93762374f, 0.93299282f, 0.92820197f,
0.92325211f, 0.91814411f, 0.91287869f, 0.90745693f, 0.90187967f,
0.89614785f, 0.89026248f, 0.88422459f, 0.87803519f, 0.87169534f,
0.86520612f, 0.85856867f, 0.85178405f, 0.84485358f, 0.83777827f,
0.83055943f, 0.82319832f, 0.81569612f, 0.80805415f, 0.80027372f,
0.79235619f, 0.78430289f, 0.77611518f, 0.76779449f, 0.75934225f,
0.75075996f, 0.74204898f, 0.73321080f, 0.72424710f, 0.71515924f,
0.70594883f, 0.69661748f, 0.68716675f, 0.67759830f, 0.66791373f,
0.65811473f, 0.64820296f, 0.63818014f, 0.62804794f, 0.61780810f,
0.60746247f, 0.59701276f, 0.58646071f, 0.57580817f, 0.56505698f,
0.55420899f, 0.54326600f, 0.53222996f, 0.52110273f, 0.50988621f,
0.49858227f, 0.48719296f, 0.47572014f, 0.46416581f, 0.45253196f,
0.44082057f, 0.42903364f, 0.41717321f, 0.40524128f, 0.39323992f,
0.38117120f, 0.36903715f, 0.35683987f, 0.34458145f, 0.33226398f,
0.31988961f, 0.30746040f, 0.29497850f, 0.28244606f, 0.26986524f,
0.25723818f, 0.24456702f, 0.23185398f, 0.21910121f, 0.20631088f,
0.19348522f, 0.18062639f, 0.16773662f, 0.15481812f, 0.14187308f,
0.12890373f, 0.11591230f, 0.10290100f, 0.089872077f, 0.076827750f,
0.063770257f, 0.050701842f, 0.037624735f, 0.024541186f, 0.011453429f,
-0.0016362892f, -0.014725727f, -0.027812643f, -0.040894791f, -0.053969935f,
-0.067035832f, -0.080090240f, -0.093130924f, -0.10615565f, -0.11916219f,
-0.13214831f, -0.14511178f, -0.15805040f, -0.17096193f, -0.18384418f,
-0.19669491f, -0.20951195f, -0.22229309f, -0.23503613f, -0.24773891f,
-0.26039925f, -0.27301496f, -0.28558388f, -0.29810387f, -0.31057280f,
-0.32298848f, -0.33534884f, -0.34765175f, -0.35989508f, -0.37207675f,
-0.38419467f, -0.39624676f, -0.40823093f, -0.42014518f, -0.43198743f,
-0.44375566f, -0.45544785f, -0.46706200f, -0.47859612f, -0.49004826f,
-0.50141639f, -0.51269865f, -0.52389306f, -0.53499764f, -0.54601061f,
-0.55693001f, -0.56775403f, -0.57848072f, -0.58910829f, -0.59963489f,
-0.61005878f, -0.62037814f, -0.63059121f, -0.64069623f, -0.65069145f,
-0.66057515f, -0.67034572f, -0.68000144f, -0.68954057f, -0.69896162f,
-0.70826286f, -0.71744281f, -0.72649974f, -0.73543227f, -0.74423873f,
-0.75291771f, -0.76146764f, -0.76988715f, -0.77817470f, -0.78632891f,
-0.79434842f, -0.80223179f, -0.80997771f, -0.81758487f, -0.82505190f,
-0.83237761f, -0.83956063f, -0.84659988f, -0.85349399f, -0.86024189f,
-0.86684239f, -0.87329435f, -0.87959671f, -0.88574833f, -0.89174819f,
-0.89759529f, -0.90328854f, -0.90882701f, -0.91420978f, -0.91943592f,
-0.92450452f, -0.92941469f, -0.93416560f, -0.93875647f, -0.94318646f,
-0.94745487f, -0.95156091f, -0.95550388f, -0.95928317f, -0.96289814f,
-0.96634805f, -0.96963239f, -0.97275060f, -0.97570217f, -0.97848648f,
-0.98110318f, -0.98355180f, -0.98583186f, -0.98794299f, -0.98988485f,
-0.99165714f, -0.99325943f, -0.99469161f, -0.99595332f, -0.99704438f,
-0.99796462f, -0.99871385f, -0.99929196f, -0.99969882f, -0.99993443f,
0.99999464f, 0.99956632f, 0.99845290f, 0.99665523f, 0.99417448f,
0.99101239f, 0.98717111f, 0.98265326f, 0.97746199f, 0.97160077f,
0.96507365f, 0.95788515f, 0.95004016f, 0.94154406f, 0.93240267f,
0.92262226f, 0.91220951f, 0.90117162f, 0.88951606f, 0.87725091f,
0.86438453f, 0.85092574f, 0.83688372f, 0.82226819f, 0.80708915f,
0.79135692f, 0.77508235f, 0.75827658f, 0.74095112f, 0.72311783f,
0.70478898f, 0.68597710f, 0.66669506f, 0.64695615f, 0.62677377f,
0.60616189f, 0.58513457f, 0.56370622f, 0.54189157f, 0.51970547f,
0.49716324f, 0.47428027f, 0.45107225f, 0.42755505f, 0.40374488f,
0.37965798f, 0.35531086f, 0.33072025f, 0.30590299f, 0.28087607f,
0.25565663f, 0.23026201f, 0.20470956f, 0.17901683f, 0.15320139f,
0.12728097f, 0.10127331f, 0.075196236f, 0.049067631f, 0.022905400f,
-0.0032725304f, -0.029448219f, -0.055603724f, -0.081721120f, -0.10778251f,
-0.13377003f, -0.15966587f, -0.18545228f, -0.21111161f, -0.23662624f,
-0.26197869f, -0.28715160f, -0.31212771f, -0.33688989f, -0.36142120f,
-0.38570482f, -0.40972409f, -0.43346253f, -0.45690393f, -0.48003218f,
-0.50283146f, -0.52528608f, -0.54738069f, -0.56910020f, -0.59042966f,
-0.61135447f, -0.63186026f, -0.65193301f, -0.67155898f, -0.69072473f,
-0.70941705f, -0.72762316f, -0.74533063f, -0.76252723f, -0.77920127f,
-0.79534131f, -0.81093621f, -0.82597536f, -0.84044844f, -0.85434550f,
-0.86765707f, -0.88037395f, -0.89248747f, -0.90398932f, -0.91487163f,
-0.92512697f, -0.93474823f, -0.94372886f, -0.95206273f, -0.95974404f,
-0.96676767f, -0.97312868f, -0.97882277f, -0.98384601f, -0.98819500f,
-0.99186671f, -0.99485862f, -0.99716878f, -0.99879545f, -0.99973762f,
};
#endif
static const CELTMode mode48000_960_120 = {
48000, /* Fs */
120, /* overlap */
21, /* nbEBands */
21, /* effEBands */
{0.85000610f, 0.0000000f, 1.0000000f, 1.0000000f, }, /* preemph */
eband5ms, /* eBands */
3, /* maxLM */
8, /* nbShortMdcts */
120, /* shortMdctSize */
11, /* nbAllocVectors */
band_allocation, /* allocVectors */
logN400, /* logN */
window120, /* window */
{1920, 3, {&fft_state48000_960_0, &fft_state48000_960_1, &fft_state48000_960_2, &fft_state48000_960_3, }, mdct_twiddles960}, /* mdct */
{392, cache_index50, cache_bits50, cache_caps50}, /* cache */
};
/* List of all the available modes */
#define TOTAL_MODES 1
static const CELTMode * const static_mode_list[TOTAL_MODES] = {
&mode48000_960_120,
};

View file

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

View file

@ -0,0 +1,161 @@
/* Copyright (c) 2008-2011 Xiph.Org Foundation, Mozilla Corporation,
Gregory Maxwell
Written by Jean-Marc Valin, Gregory Maxwell, and 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 <stdio.h>
#include <string.h>
#ifndef CUSTOM_MODES
#define CUSTOM_MODES
#else
#define TEST_CUSTOM_MODES
#endif
#define CELT_C
#include "stack_alloc.h"
#include "entenc.c"
#include "entdec.c"
#include "entcode.c"
#include "cwrs.c"
#include "mathops.c"
#include "rate.h"
#define NMAX (240)
#define KMAX (128)
#ifdef TEST_CUSTOM_MODES
#define NDIMS (44)
static const int pn[NDIMS]={
2, 3, 4, 5, 6, 7, 8, 9, 10,
11, 12, 13, 14, 15, 16, 18, 20, 22,
24, 26, 28, 30, 32, 36, 40, 44, 48,
52, 56, 60, 64, 72, 80, 88, 96, 104,
112, 120, 128, 144, 160, 176, 192, 208
};
static const int pkmax[NDIMS]={
128, 128, 128, 128, 88, 52, 36, 26, 22,
18, 16, 15, 13, 12, 12, 11, 10, 9,
9, 8, 8, 7, 7, 7, 7, 6, 6,
6, 6, 6, 5, 5, 5, 5, 5, 5,
4, 4, 4, 4, 4, 4, 4, 4
};
#else /* TEST_CUSTOM_MODES */
#define NDIMS (22)
static const int pn[NDIMS]={
2, 3, 4, 6, 8, 9, 11, 12, 16,
18, 22, 24, 32, 36, 44, 48, 64, 72,
88, 96, 144, 176
};
static const int pkmax[NDIMS]={
128, 128, 128, 88, 36, 26, 18, 16, 12,
11, 9, 9, 7, 7, 6, 6, 5, 5,
5, 5, 4, 4
};
#endif
int main(void){
int t;
int n;
ALLOC_STACK;
for(t=0;t<NDIMS;t++){
int pseudo;
n=pn[t];
for(pseudo=1;pseudo<41;pseudo++)
{
int k;
#if defined(SMALL_FOOTPRINT)
opus_uint32 uu[KMAX+2U];
#endif
opus_uint32 inc;
opus_uint32 nc;
opus_uint32 i;
k=get_pulses(pseudo);
if (k>pkmax[t])break;
printf("Testing CWRS with N=%i, K=%i...\n",n,k);
#if defined(SMALL_FOOTPRINT)
nc=ncwrs_urow(n,k,uu);
#else
nc=CELT_PVQ_V(n,k);
#endif
inc=nc/20000;
if(inc<1)inc=1;
for(i=0;i<nc;i+=inc){
#if defined(SMALL_FOOTPRINT)
opus_uint32 u[KMAX+2U];
#endif
int y[NMAX];
int sy;
opus_uint32 v;
opus_uint32 ii;
int j;
#if defined(SMALL_FOOTPRINT)
memcpy(u,uu,(k+2U)*sizeof(*u));
cwrsi(n,k,i,y,u);
#else
cwrsi(n,k,i,y);
#endif
sy=0;
for(j=0;j<n;j++)sy+=abs(y[j]);
if(sy!=k){
fprintf(stderr,"N=%d Pulse count mismatch in cwrsi (%d!=%d).\n",
n,sy,k);
return 99;
}
/*printf("%6u of %u:",i,nc);
for(j=0;j<n;j++)printf(" %+3i",y[j]);
printf(" ->");*/
#if defined(SMALL_FOOTPRINT)
ii=icwrs(n,k,&v,y,u);
#else
ii=icwrs(n,y);
v=CELT_PVQ_V(n,k);
#endif
if(ii!=i){
fprintf(stderr,"Combination-index mismatch (%lu!=%lu).\n",
(long)ii,(long)i);
return 1;
}
if(v!=nc){
fprintf(stderr,"Combination count mismatch (%lu!=%lu).\n",
(long)v,(long)nc);
return 2;
}
/*printf(" %6u\n",i);*/
}
/*printf("\n");*/
}
}
return 0;
}

View file

@ -0,0 +1,179 @@
/* Copyright (c) 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.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdio.h>
#include "stack_alloc.h"
#include "kiss_fft.h"
#include "mathops.h"
#include "modes.h"
#ifndef M_PI
#define M_PI 3.141592653
#endif
int ret = 0;
void check(kiss_fft_cpx * in,kiss_fft_cpx * out,int nfft,int isinverse)
{
int bin,k;
double errpow=0,sigpow=0, snr;
for (bin=0;bin<nfft;++bin) {
double ansr = 0;
double ansi = 0;
double difr;
double difi;
for (k=0;k<nfft;++k) {
double phase = -2*M_PI*bin*k/nfft;
double re = cos(phase);
double im = sin(phase);
if (isinverse)
im = -im;
if (!isinverse)
{
re /= nfft;
im /= nfft;
}
ansr += in[k].r * re - in[k].i * im;
ansi += in[k].r * im + in[k].i * re;
}
/*printf ("%d %d ", (int)ansr, (int)ansi);*/
difr = ansr - out[bin].r;
difi = ansi - out[bin].i;
errpow += difr*difr + difi*difi;
sigpow += ansr*ansr+ansi*ansi;
}
snr = 10*log10(sigpow/errpow);
printf("nfft=%d inverse=%d,snr = %f\n",nfft,isinverse,snr );
if (snr<60) {
printf( "** poor snr: %f ** \n", snr);
ret = 1;
}
}
void test1d(int nfft,int isinverse,int arch)
{
size_t buflen = sizeof(kiss_fft_cpx)*nfft;
kiss_fft_cpx *in;
kiss_fft_cpx *out;
int k;
#ifdef CUSTOM_MODES
kiss_fft_state *cfg = opus_fft_alloc(nfft,0,0,arch);
#else
int id;
const kiss_fft_state *cfg;
CELTMode *mode = opus_custom_mode_create(48000, 960, NULL);
if (nfft == 480) id = 0;
else if (nfft == 240) id = 1;
else if (nfft == 120) id = 2;
else if (nfft == 60) id = 3;
else return;
cfg = mode->mdct.kfft[id];
#endif
in = (kiss_fft_cpx*)malloc(buflen);
out = (kiss_fft_cpx*)malloc(buflen);
for (k=0;k<nfft;++k) {
in[k].r = (rand() % 32767) - 16384;
in[k].i = (rand() % 32767) - 16384;
}
for (k=0;k<nfft;++k) {
in[k].r *= 32768;
in[k].i *= 32768;
}
if (isinverse)
{
for (k=0;k<nfft;++k) {
in[k].r /= nfft;
in[k].i /= nfft;
}
}
/*for (k=0;k<nfft;++k) printf("%d %d ", in[k].r, in[k].i);printf("\n");*/
if (isinverse)
opus_ifft(cfg,in,out, arch);
else
opus_fft(cfg,in,out, arch);
/*for (k=0;k<nfft;++k) printf("%d %d ", out[k].r, out[k].i);printf("\n");*/
check(in,out,nfft,isinverse);
free(in);
free(out);
#ifdef CUSTOM_MODES
opus_fft_free(cfg, arch);
#endif
}
int main(int argc,char ** argv)
{
ALLOC_STACK;
int arch = opus_select_arch();
if (argc>1) {
int k;
for (k=1;k<argc;++k) {
test1d(atoi(argv[k]),0,arch);
test1d(atoi(argv[k]),1,arch);
}
}else{
test1d(32,0,arch);
test1d(32,1,arch);
test1d(128,0,arch);
test1d(128,1,arch);
test1d(256,0,arch);
test1d(256,1,arch);
#ifndef RADIX_TWO_ONLY
test1d(36,0,arch);
test1d(36,1,arch);
test1d(50,0,arch);
test1d(50,1,arch);
test1d(60,0,arch);
test1d(60,1,arch);
test1d(120,0,arch);
test1d(120,1,arch);
test1d(240,0,arch);
test1d(240,1,arch);
test1d(480,0,arch);
test1d(480,1,arch);
#endif
}
return ret;
}

View file

@ -0,0 +1,383 @@
/* Copyright (c) 2007-2011 Xiph.Org Foundation, Mozilla Corporation,
Gregory Maxwell
Written by Jean-Marc Valin, Gregory Maxwell, and 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 <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <time.h>
#define CELT_C
#include "entcode.h"
#include "entenc.h"
#include "entdec.h"
#include <string.h>
#include "entenc.c"
#include "entdec.c"
#include "entcode.c"
#ifndef M_LOG2E
# define M_LOG2E 1.4426950408889634074
#endif
#define DATA_SIZE 10000000
#define DATA_SIZE2 10000
int main(int _argc,char **_argv){
ec_enc enc;
ec_dec dec;
long nbits;
long nbits2;
double entropy;
int ft;
int ftb;
int sz;
int i;
int ret;
unsigned int sym;
unsigned int seed;
unsigned char *ptr;
const char *env_seed;
ret=0;
entropy=0;
if (_argc > 2) {
fprintf(stderr, "Usage: %s [<seed>]\n", _argv[0]);
return 1;
}
env_seed = getenv("SEED");
if (_argc > 1)
seed = atoi(_argv[1]);
else if (env_seed)
seed = atoi(env_seed);
else
seed = time(NULL);
/*Testing encoding of raw bit values.*/
ptr = (unsigned char *)malloc(DATA_SIZE);
ec_enc_init(&enc,ptr, DATA_SIZE);
for(ft=2;ft<1024;ft++){
for(i=0;i<ft;i++){
entropy+=log(ft)*M_LOG2E;
ec_enc_uint(&enc,i,ft);
}
}
/*Testing encoding of raw bit values.*/
for(ftb=1;ftb<16;ftb++){
for(i=0;i<(1<<ftb);i++){
entropy+=ftb;
nbits=ec_tell(&enc);
ec_enc_bits(&enc,i,ftb);
nbits2=ec_tell(&enc);
if(nbits2-nbits!=ftb){
fprintf(stderr,"Used %li bits to encode %i bits directly.\n",
nbits2-nbits,ftb);
ret=-1;
}
}
}
nbits=ec_tell_frac(&enc);
ec_enc_done(&enc);
fprintf(stderr,
"Encoded %0.2lf bits of entropy to %0.2lf bits (%0.3lf%% wasted).\n",
entropy,ldexp(nbits,-3),100*(nbits-ldexp(entropy,3))/nbits);
fprintf(stderr,"Packed to %li bytes.\n",(long)ec_range_bytes(&enc));
ec_dec_init(&dec,ptr,DATA_SIZE);
for(ft=2;ft<1024;ft++){
for(i=0;i<ft;i++){
sym=ec_dec_uint(&dec,ft);
if(sym!=(unsigned)i){
fprintf(stderr,"Decoded %i instead of %i with ft of %i.\n",sym,i,ft);
ret=-1;
}
}
}
for(ftb=1;ftb<16;ftb++){
for(i=0;i<(1<<ftb);i++){
sym=ec_dec_bits(&dec,ftb);
if(sym!=(unsigned)i){
fprintf(stderr,"Decoded %i instead of %i with ftb of %i.\n",sym,i,ftb);
ret=-1;
}
}
}
nbits2=ec_tell_frac(&dec);
if(nbits!=nbits2){
fprintf(stderr,
"Reported number of bits used was %0.2lf, should be %0.2lf.\n",
ldexp(nbits2,-3),ldexp(nbits,-3));
ret=-1;
}
/*Testing an encoder bust prefers range coder data over raw bits.
This isn't a general guarantee, will only work for data that is buffered in
the encoder state and not yet stored in the user buffer, and should never
get used in practice.
It's mostly here for code coverage completeness.*/
/*Start with a 16-bit buffer.*/
ec_enc_init(&enc,ptr,2);
/*Write 7 raw bits.*/
ec_enc_bits(&enc,0x55,7);
/*Write 12.3 bits of range coder data.*/
ec_enc_uint(&enc,1,2);
ec_enc_uint(&enc,1,3);
ec_enc_uint(&enc,1,4);
ec_enc_uint(&enc,1,5);
ec_enc_uint(&enc,2,6);
ec_enc_uint(&enc,6,7);
ec_enc_done(&enc);
ec_dec_init(&dec,ptr,2);
if(!enc.error
/*The raw bits should have been overwritten by the range coder data.*/
||ec_dec_bits(&dec,7)!=0x05
/*And all the range coder data should have been encoded correctly.*/
||ec_dec_uint(&dec,2)!=1
||ec_dec_uint(&dec,3)!=1
||ec_dec_uint(&dec,4)!=1
||ec_dec_uint(&dec,5)!=1
||ec_dec_uint(&dec,6)!=2
||ec_dec_uint(&dec,7)!=6){
fprintf(stderr,"Encoder bust overwrote range coder data with raw bits.\n");
ret=-1;
}
srand(seed);
fprintf(stderr,"Testing random streams... Random seed: %u (%.4X)\n", seed, rand() % 65536);
for(i=0;i<409600;i++){
unsigned *data;
unsigned *tell;
unsigned tell_bits;
int j;
int zeros;
ft=rand()/((RAND_MAX>>(rand()%11U))+1U)+10;
sz=rand()/((RAND_MAX>>(rand()%9U))+1U);
data=(unsigned *)malloc(sz*sizeof(*data));
tell=(unsigned *)malloc((sz+1)*sizeof(*tell));
ec_enc_init(&enc,ptr,DATA_SIZE2);
zeros = rand()%13==0;
tell[0]=ec_tell_frac(&enc);
for(j=0;j<sz;j++){
if (zeros)
data[j]=0;
else
data[j]=rand()%ft;
ec_enc_uint(&enc,data[j],ft);
tell[j+1]=ec_tell_frac(&enc);
}
if (rand()%2==0)
while(ec_tell(&enc)%8 != 0)
ec_enc_uint(&enc, rand()%2, 2);
tell_bits = ec_tell(&enc);
ec_enc_done(&enc);
if(tell_bits!=(unsigned)ec_tell(&enc)){
fprintf(stderr,"ec_tell() changed after ec_enc_done(): %i instead of %i (Random seed: %u)\n",
ec_tell(&enc),tell_bits,seed);
ret=-1;
}
if ((tell_bits+7)/8 < ec_range_bytes(&enc))
{
fprintf (stderr, "ec_tell() lied, there's %i bytes instead of %d (Random seed: %u)\n",
ec_range_bytes(&enc), (tell_bits+7)/8,seed);
ret=-1;
}
ec_dec_init(&dec,ptr,DATA_SIZE2);
if(ec_tell_frac(&dec)!=tell[0]){
fprintf(stderr,
"Tell mismatch between encoder and decoder at symbol %i: %i instead of %i (Random seed: %u).\n",
0,ec_tell_frac(&dec),tell[0],seed);
}
for(j=0;j<sz;j++){
sym=ec_dec_uint(&dec,ft);
if(sym!=data[j]){
fprintf(stderr,
"Decoded %i instead of %i with ft of %i at position %i of %i (Random seed: %u).\n",
sym,data[j],ft,j,sz,seed);
ret=-1;
}
if(ec_tell_frac(&dec)!=tell[j+1]){
fprintf(stderr,
"Tell mismatch between encoder and decoder at symbol %i: %i instead of %i (Random seed: %u).\n",
j+1,ec_tell_frac(&dec),tell[j+1],seed);
}
}
free(tell);
free(data);
}
/*Test compatibility between multiple different encode/decode routines.*/
for(i=0;i<409600;i++){
unsigned *logp1;
unsigned *data;
unsigned *tell;
unsigned *enc_method;
int j;
sz=rand()/((RAND_MAX>>(rand()%9U))+1U);
logp1=(unsigned *)malloc(sz*sizeof(*logp1));
data=(unsigned *)malloc(sz*sizeof(*data));
tell=(unsigned *)malloc((sz+1)*sizeof(*tell));
enc_method=(unsigned *)malloc(sz*sizeof(*enc_method));
ec_enc_init(&enc,ptr,DATA_SIZE2);
tell[0]=ec_tell_frac(&enc);
for(j=0;j<sz;j++){
data[j]=rand()/((RAND_MAX>>1)+1);
logp1[j]=(rand()%15)+1;
enc_method[j]=rand()/((RAND_MAX>>2)+1);
switch(enc_method[j]){
case 0:{
ec_encode(&enc,data[j]?(1<<logp1[j])-1:0,
(1<<logp1[j])-(data[j]?0:1),1<<logp1[j]);
}break;
case 1:{
ec_encode_bin(&enc,data[j]?(1<<logp1[j])-1:0,
(1<<logp1[j])-(data[j]?0:1),logp1[j]);
}break;
case 2:{
ec_enc_bit_logp(&enc,data[j],logp1[j]);
}break;
case 3:{
unsigned char icdf[2];
icdf[0]=1;
icdf[1]=0;
ec_enc_icdf(&enc,data[j],icdf,logp1[j]);
}break;
}
tell[j+1]=ec_tell_frac(&enc);
}
ec_enc_done(&enc);
if((ec_tell(&enc)+7U)/8U<ec_range_bytes(&enc)){
fprintf(stderr,"tell() lied, there's %i bytes instead of %d (Random seed: %u)\n",
ec_range_bytes(&enc),(ec_tell(&enc)+7)/8,seed);
ret=-1;
}
ec_dec_init(&dec,ptr,DATA_SIZE2);
if(ec_tell_frac(&dec)!=tell[0]){
fprintf(stderr,
"Tell mismatch between encoder and decoder at symbol %i: %i instead of %i (Random seed: %u).\n",
0,ec_tell_frac(&dec),tell[0],seed);
}
for(j=0;j<sz;j++){
int fs;
int dec_method;
dec_method=rand()/((RAND_MAX>>2)+1);
switch(dec_method){
case 0:{
fs=ec_decode(&dec,1<<logp1[j]);
sym=fs>=(1<<logp1[j])-1;
ec_dec_update(&dec,sym?(1<<logp1[j])-1:0,
(1<<logp1[j])-(sym?0:1),1<<logp1[j]);
}break;
case 1:{
fs=ec_decode_bin(&dec,logp1[j]);
sym=fs>=(1<<logp1[j])-1;
ec_dec_update(&dec,sym?(1<<logp1[j])-1:0,
(1<<logp1[j])-(sym?0:1),1<<logp1[j]);
}break;
case 2:{
sym=ec_dec_bit_logp(&dec,logp1[j]);
}break;
case 3:{
unsigned char icdf[2];
icdf[0]=1;
icdf[1]=0;
sym=ec_dec_icdf(&dec,icdf,logp1[j]);
}break;
}
if(sym!=data[j]){
fprintf(stderr,
"Decoded %i instead of %i with logp1 of %i at position %i of %i (Random seed: %u).\n",
sym,data[j],logp1[j],j,sz,seed);
fprintf(stderr,"Encoding method: %i, decoding method: %i\n",
enc_method[j],dec_method);
ret=-1;
}
if(ec_tell_frac(&dec)!=tell[j+1]){
fprintf(stderr,
"Tell mismatch between encoder and decoder at symbol %i: %i instead of %i (Random seed: %u).\n",
j+1,ec_tell_frac(&dec),tell[j+1],seed);
}
}
free(enc_method);
free(tell);
free(data);
free(logp1);
}
ec_enc_init(&enc,ptr,DATA_SIZE2);
ec_enc_bit_logp(&enc,0,1);
ec_enc_bit_logp(&enc,0,1);
ec_enc_bit_logp(&enc,0,1);
ec_enc_bit_logp(&enc,0,1);
ec_enc_bit_logp(&enc,0,2);
ec_enc_patch_initial_bits(&enc,3,2);
if(enc.error){
fprintf(stderr,"patch_initial_bits failed");
ret=-1;
}
ec_enc_patch_initial_bits(&enc,0,5);
if(!enc.error){
fprintf(stderr,"patch_initial_bits didn't fail when it should have");
ret=-1;
}
ec_enc_done(&enc);
if(ec_range_bytes(&enc)!=1||ptr[0]!=192){
fprintf(stderr,"Got %d when expecting 192 for patch_initial_bits",ptr[0]);
ret=-1;
}
ec_enc_init(&enc,ptr,DATA_SIZE2);
ec_enc_bit_logp(&enc,0,1);
ec_enc_bit_logp(&enc,0,1);
ec_enc_bit_logp(&enc,1,6);
ec_enc_bit_logp(&enc,0,2);
ec_enc_patch_initial_bits(&enc,0,2);
if(enc.error){
fprintf(stderr,"patch_initial_bits failed");
ret=-1;
}
ec_enc_done(&enc);
if(ec_range_bytes(&enc)!=2||ptr[0]!=63){
fprintf(stderr,"Got %d when expecting 63 for patch_initial_bits",ptr[0]);
ret=-1;
}
ec_enc_init(&enc,ptr,2);
ec_enc_bit_logp(&enc,0,2);
for(i=0;i<48;i++){
ec_enc_bits(&enc,0,1);
}
ec_enc_done(&enc);
if(!enc.error){
fprintf(stderr,"Raw bits overfill didn't fail when it should have");
ret=-1;
}
ec_enc_init(&enc,ptr,2);
for(i=0;i<17;i++){
ec_enc_bits(&enc,0,1);
}
ec_enc_done(&enc);
if(!enc.error){
fprintf(stderr,"17 raw bits encoded in two bytes");
ret=-1;
}
free(ptr);
return ret;
}

View file

@ -0,0 +1,93 @@
/* Copyright (c) 2008-2011 Xiph.Org Foundation, Mozilla Corporation
Written by Jean-Marc Valin and 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 <stdio.h>
#include <stdlib.h>
#define CELT_C
#include "laplace.h"
#include "stack_alloc.h"
#include "entenc.c"
#include "entdec.c"
#include "entcode.c"
#include "laplace.c"
#define DATA_SIZE 40000
int ec_laplace_get_start_freq(int decay)
{
opus_uint32 ft = 32768 - LAPLACE_MINP*(2*LAPLACE_NMIN+1);
int fs = (ft*(16384-decay))/(16384+decay);
return fs+LAPLACE_MINP;
}
int main(void)
{
int i;
int ret = 0;
ec_enc enc;
ec_dec dec;
unsigned char *ptr;
int val[10000], decay[10000];
ALLOC_STACK;
ptr = (unsigned char *)malloc(DATA_SIZE);
ec_enc_init(&enc,ptr,DATA_SIZE);
val[0] = 3; decay[0] = 6000;
val[1] = 0; decay[1] = 5800;
val[2] = -1; decay[2] = 5600;
for (i=3;i<10000;i++)
{
val[i] = rand()%15-7;
decay[i] = rand()%11000+5000;
}
for (i=0;i<10000;i++)
ec_laplace_encode(&enc, &val[i],
ec_laplace_get_start_freq(decay[i]), decay[i]);
ec_enc_done(&enc);
ec_dec_init(&dec,ec_get_buffer(&enc),ec_range_bytes(&enc));
for (i=0;i<10000;i++)
{
int d = ec_laplace_decode(&dec,
ec_laplace_get_start_freq(decay[i]), decay[i]);
if (d != val[i])
{
fprintf (stderr, "Got %d instead of %d\n", d, val[i]);
ret = 1;
}
}
free(ptr);
return ret;
}

View file

@ -0,0 +1,266 @@
/* Copyright (c) 2008-2011 Xiph.Org Foundation, Mozilla Corporation,
Gregory Maxwell
Written by Jean-Marc Valin, Gregory Maxwell, and 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
#ifndef CUSTOM_MODES
#define CUSTOM_MODES
#endif
#include <stdio.h>
#include <math.h>
#include "mathops.h"
#include "bands.h"
#ifdef FIXED_POINT
#define WORD "%d"
#else
#define WORD "%f"
#endif
int ret = 0;
void testdiv(void)
{
opus_int32 i;
for (i=1;i<=327670;i++)
{
double prod;
opus_val32 val;
val = celt_rcp(i);
#ifdef FIXED_POINT
prod = (1./32768./65526.)*val*i;
#else
prod = val*i;
#endif
if (fabs(prod-1) > .00025)
{
fprintf (stderr, "div failed: 1/%d="WORD" (product = %f)\n", i, val, prod);
ret = 1;
}
}
}
void testsqrt(void)
{
opus_int32 i;
for (i=1;i<=1000000000;i++)
{
double ratio;
opus_val16 val;
val = celt_sqrt(i);
ratio = val/sqrt(i);
if (fabs(ratio - 1) > .0005 && fabs(val-sqrt(i)) > 2)
{
fprintf (stderr, "sqrt failed: sqrt(%d)="WORD" (ratio = %f)\n", i, val, ratio);
ret = 1;
}
i+= i>>10;
}
}
void testbitexactcos(void)
{
int i;
opus_int32 min_d,max_d,last,chk;
chk=max_d=0;
last=min_d=32767;
for(i=64;i<=16320;i++)
{
opus_int32 d;
opus_int32 q=bitexact_cos(i);
chk ^= q*i;
d = last - q;
if (d>max_d)max_d=d;
if (d<min_d)min_d=d;
last = q;
}
if ((chk!=89408644)||(max_d!=5)||(min_d!=0)||(bitexact_cos(64)!=32767)||
(bitexact_cos(16320)!=200)||(bitexact_cos(8192)!=23171))
{
fprintf (stderr, "bitexact_cos failed\n");
ret = 1;
}
}
void testbitexactlog2tan(void)
{
int i,fail;
opus_int32 min_d,max_d,last,chk;
fail=chk=max_d=0;
last=min_d=15059;
for(i=64;i<8193;i++)
{
opus_int32 d;
opus_int32 mid=bitexact_cos(i);
opus_int32 side=bitexact_cos(16384-i);
opus_int32 q=bitexact_log2tan(mid,side);
chk ^= q*i;
d = last - q;
if (q!=-1*bitexact_log2tan(side,mid))
fail = 1;
if (d>max_d)max_d=d;
if (d<min_d)min_d=d;
last = q;
}
if ((chk!=15821257)||(max_d!=61)||(min_d!=-2)||fail||
(bitexact_log2tan(32767,200)!=15059)||(bitexact_log2tan(30274,12540)!=2611)||
(bitexact_log2tan(23171,23171)!=0))
{
fprintf (stderr, "bitexact_log2tan failed\n");
ret = 1;
}
}
#ifndef FIXED_POINT
void testlog2(void)
{
float x;
for (x=0.001;x<1677700.0;x+=(x/8.0))
{
float error = fabs((1.442695040888963387*log(x))-celt_log2(x));
if (error>0.0009)
{
fprintf (stderr, "celt_log2 failed: fabs((1.442695040888963387*log(x))-celt_log2(x))>0.001 (x = %f, error = %f)\n", x,error);
ret = 1;
}
}
}
void testexp2(void)
{
float x;
for (x=-11.0;x<24.0;x+=0.0007)
{
float error = fabs(x-(1.442695040888963387*log(celt_exp2(x))));
if (error>0.0002)
{
fprintf (stderr, "celt_exp2 failed: fabs(x-(1.442695040888963387*log(celt_exp2(x))))>0.0005 (x = %f, error = %f)\n", x,error);
ret = 1;
}
}
}
void testexp2log2(void)
{
float x;
for (x=-11.0;x<24.0;x+=0.0007)
{
float error = fabs(x-(celt_log2(celt_exp2(x))));
if (error>0.001)
{
fprintf (stderr, "celt_log2/celt_exp2 failed: fabs(x-(celt_log2(celt_exp2(x))))>0.001 (x = %f, error = %f)\n", x,error);
ret = 1;
}
}
}
#else
void testlog2(void)
{
opus_val32 x;
for (x=8;x<1073741824;x+=(x>>3))
{
float error = fabs((1.442695040888963387*log(x/16384.0))-celt_log2(x)/1024.0);
if (error>0.003)
{
fprintf (stderr, "celt_log2 failed: x = %ld, error = %f\n", (long)x,error);
ret = 1;
}
}
}
void testexp2(void)
{
opus_val16 x;
for (x=-32768;x<15360;x++)
{
float error1 = fabs(x/1024.0-(1.442695040888963387*log(celt_exp2(x)/65536.0)));
float error2 = fabs(exp(0.6931471805599453094*x/1024.0)-celt_exp2(x)/65536.0);
if (error1>0.0002&&error2>0.00004)
{
fprintf (stderr, "celt_exp2 failed: x = "WORD", error1 = %f, error2 = %f\n", x,error1,error2);
ret = 1;
}
}
}
void testexp2log2(void)
{
opus_val32 x;
for (x=8;x<65536;x+=(x>>3))
{
float error = fabs(x-0.25*celt_exp2(celt_log2(x)))/16384;
if (error>0.004)
{
fprintf (stderr, "celt_log2/celt_exp2 failed: fabs(x-(celt_exp2(celt_log2(x))))>0.001 (x = %ld, error = %f)\n", (long)x,error);
ret = 1;
}
}
}
void testilog2(void)
{
opus_val32 x;
for (x=1;x<=268435455;x+=127)
{
opus_val32 lg;
opus_val32 y;
lg = celt_ilog2(x);
if (lg<0 || lg>=31)
{
printf("celt_ilog2 failed: 0<=celt_ilog2(x)<31 (x = %d, celt_ilog2(x) = %d)\n",x,lg);
ret = 1;
}
y = 1<<lg;
if (x<y || (x>>1)>=y)
{
printf("celt_ilog2 failed: 2**celt_ilog2(x)<=x<2**(celt_ilog2(x)+1) (x = %d, 2**celt_ilog2(x) = %d)\n",x,y);
ret = 1;
}
}
}
#endif
int main(void)
{
testbitexactcos();
testbitexactlog2tan();
testdiv();
testsqrt();
testlog2();
testexp2();
testexp2log2();
#ifdef FIXED_POINT
testilog2();
#endif
return ret;
}

View file

@ -0,0 +1,227 @@
/* Copyright (c) 2008-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.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdio.h>
#include "mdct.h"
#include "stack_alloc.h"
#include "kiss_fft.h"
#include "mdct.h"
#include "modes.h"
#ifndef M_PI
#define M_PI 3.141592653
#endif
int ret = 0;
void check(kiss_fft_scalar * in,kiss_fft_scalar * out,int nfft,int isinverse)
{
int bin,k;
double errpow=0,sigpow=0;
double snr;
for (bin=0;bin<nfft/2;++bin) {
double ansr = 0;
double difr;
for (k=0;k<nfft;++k) {
double phase = 2*M_PI*(k+.5+.25*nfft)*(bin+.5)/nfft;
double re = cos(phase);
re /= nfft/4;
ansr += in[k] * re;
}
/*printf ("%f %f\n", ansr, out[bin]);*/
difr = ansr - out[bin];
errpow += difr*difr;
sigpow += ansr*ansr;
}
snr = 10*log10(sigpow/errpow);
printf("nfft=%d inverse=%d,snr = %f\n",nfft,isinverse,snr );
if (snr<60) {
printf( "** poor snr: %f **\n", snr);
ret = 1;
}
}
void check_inv(kiss_fft_scalar * in,kiss_fft_scalar * out,int nfft,int isinverse)
{
int bin,k;
double errpow=0,sigpow=0;
double snr;
for (bin=0;bin<nfft;++bin) {
double ansr = 0;
double difr;
for (k=0;k<nfft/2;++k) {
double phase = 2*M_PI*(bin+.5+.25*nfft)*(k+.5)/nfft;
double re = cos(phase);
/*re *= 2;*/
ansr += in[k] * re;
}
/*printf ("%f %f\n", ansr, out[bin]);*/
difr = ansr - out[bin];
errpow += difr*difr;
sigpow += ansr*ansr;
}
snr = 10*log10(sigpow/errpow);
printf("nfft=%d inverse=%d,snr = %f\n",nfft,isinverse,snr );
if (snr<60) {
printf( "** poor snr: %f **\n", snr);
ret = 1;
}
}
void test1d(int nfft,int isinverse,int arch)
{
size_t buflen = sizeof(kiss_fft_scalar)*nfft;
kiss_fft_scalar *in;
kiss_fft_scalar *in_copy;
kiss_fft_scalar *out;
opus_val16 *window;
int k;
#ifdef CUSTOM_MODES
int shift = 0;
const mdct_lookup *cfg;
mdct_lookup _cfg;
clt_mdct_init(&_cfg, nfft, 0, arch);
cfg = &_cfg;
#else
int shift;
const mdct_lookup *cfg;
CELTMode *mode = opus_custom_mode_create(48000, 960, NULL);
if (nfft == 1920) shift = 0;
else if (nfft == 960) shift = 1;
else if (nfft == 480) shift = 2;
else if (nfft == 240) shift = 3;
else return;
cfg = &mode->mdct;
#endif
in = (kiss_fft_scalar*)malloc(buflen);
in_copy = (kiss_fft_scalar*)malloc(buflen);
out = (kiss_fft_scalar*)malloc(buflen);
window = (opus_val16*)malloc(sizeof(opus_val16)*nfft/2);
for (k=0;k<nfft;++k) {
in[k] = (rand() % 32768) - 16384;
}
for (k=0;k<nfft/2;++k) {
window[k] = Q15ONE;
}
for (k=0;k<nfft;++k) {
in[k] *= 32768;
}
if (isinverse)
{
for (k=0;k<nfft;++k) {
in[k] /= nfft;
}
}
for (k=0;k<nfft;++k)
in_copy[k] = in[k];
/*for (k=0;k<nfft;++k) printf("%d %d ", in[k].r, in[k].i);printf("\n");*/
if (isinverse)
{
for (k=0;k<nfft;++k)
out[k] = 0;
clt_mdct_backward(cfg,in,out, window, nfft/2, shift, 1, arch);
/* apply TDAC because clt_mdct_backward() no longer does that */
for (k=0;k<nfft/4;++k)
out[nfft-k-1] = out[nfft/2+k];
check_inv(in,out,nfft,isinverse);
} else {
clt_mdct_forward(cfg,in,out,window, nfft/2, shift, 1, arch);
check(in_copy,out,nfft,isinverse);
}
/*for (k=0;k<nfft;++k) printf("%d %d ", out[k].r, out[k].i);printf("\n");*/
free(in);
free(in_copy);
free(out);
free(window);
#ifdef CUSTOM_MODES
clt_mdct_clear(&_cfg, arch);
#endif
}
int main(int argc,char ** argv)
{
ALLOC_STACK;
int arch = opus_select_arch();
if (argc>1) {
int k;
for (k=1;k<argc;++k) {
test1d(atoi(argv[k]),0,arch);
test1d(atoi(argv[k]),1,arch);
}
}else{
test1d(32,0,arch);
test1d(32,1,arch);
test1d(256,0,arch);
test1d(256,1,arch);
test1d(512,0,arch);
test1d(512,1,arch);
test1d(1024,0,arch);
test1d(1024,1,arch);
test1d(2048,0,arch);
test1d(2048,1,arch);
#ifndef RADIX_TWO_ONLY
test1d(36,0,arch);
test1d(36,1,arch);
test1d(40,0,arch);
test1d(40,1,arch);
test1d(60,0,arch);
test1d(60,1,arch);
test1d(120,0,arch);
test1d(120,1,arch);
test1d(240,0,arch);
test1d(240,1,arch);
test1d(480,0,arch);
test1d(480,1,arch);
test1d(960,0,arch);
test1d(960,1,arch);
test1d(1920,0,arch);
test1d(1920,1,arch);
#endif
}
return ret;
}

View file

@ -0,0 +1,86 @@
/* Copyright (c) 2008-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.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifndef CUSTOM_MODES
#define CUSTOM_MODES
#endif
#include <stdio.h>
#include <stdlib.h>
#include "vq.h"
#include "bands.h"
#include "stack_alloc.h"
#include <math.h>
#define MAX_SIZE 100
int ret=0;
void test_rotation(int N, int K)
{
int i;
double err = 0, ener = 0, snr, snr0;
opus_val16 x0[MAX_SIZE];
opus_val16 x1[MAX_SIZE];
for (i=0;i<N;i++)
x1[i] = x0[i] = rand()%32767-16384;
exp_rotation(x1, N, 1, 1, K, SPREAD_NORMAL);
for (i=0;i<N;i++)
{
err += (x0[i]-(double)x1[i])*(x0[i]-(double)x1[i]);
ener += x0[i]*(double)x0[i];
}
snr0 = 20*log10(ener/err);
err = ener = 0;
exp_rotation(x1, N, -1, 1, K, SPREAD_NORMAL);
for (i=0;i<N;i++)
{
err += (x0[i]-(double)x1[i])*(x0[i]-(double)x1[i]);
ener += x0[i]*(double)x0[i];
}
snr = 20*log10(ener/err);
printf ("SNR for size %d (%d pulses) is %f (was %f without inverse)\n", N, K, snr, snr0);
if (snr < 60 || snr0 > 20)
{
fprintf(stderr, "FAIL!\n");
ret = 1;
}
}
int main(void)
{
ALLOC_STACK;
test_rotation(15, 3);
test_rotation(23, 5);
test_rotation(50, 3);
test_rotation(80, 1);
return ret;
}

View file

@ -0,0 +1,50 @@
/* Copyright (c) 2008-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.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "opus_types.h"
#include <stdio.h>
int main(void)
{
opus_int16 i = 1;
i <<= 14;
if (i>>14 != 1)
{
fprintf(stderr, "opus_int16 isn't 16 bits\n");
return 1;
}
if (sizeof(opus_int16)*2 != sizeof(opus_int32))
{
fprintf(stderr, "16*2 != 32\n");
return 1;
}
return 0;
}

View file

@ -39,10 +39,6 @@
#include "rate.h" #include "rate.h"
#include "pitch.h" #include "pitch.h"
#if defined(MIPSr1_ASM)
#include "mips/vq_mipsr1.h"
#endif
#ifndef OVERRIDE_vq_exp_rotation1 #ifndef OVERRIDE_vq_exp_rotation1
static void exp_rotation1(celt_norm *X, int len, int stride, opus_val16 c, opus_val16 s) static void exp_rotation1(celt_norm *X, int len, int stride, opus_val16 c, opus_val16 s)
{ {
@ -71,7 +67,7 @@ static void exp_rotation1(celt_norm *X, int len, int stride, opus_val16 c, opus_
} }
#endif /* OVERRIDE_vq_exp_rotation1 */ #endif /* OVERRIDE_vq_exp_rotation1 */
static void exp_rotation(celt_norm *X, int len, int dir, int stride, int K, int spread) 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}; static const int SPREAD_FACTOR[3]={15,10,5};
int i; int i;
@ -162,42 +158,27 @@ static unsigned extract_collapse_mask(int *iy, int N, int B)
return collapse_mask; return collapse_mask;
} }
unsigned alg_quant(celt_norm *X, int N, int K, int spread, int B, ec_enc *enc opus_val16 op_pvq_search_c(celt_norm *X, int *iy, int K, int N, int arch)
#ifdef RESYNTH
, opus_val16 gain
#endif
)
{ {
VARDECL(celt_norm, y); VARDECL(celt_norm, y);
VARDECL(int, iy); VARDECL(int, signx);
VARDECL(opus_val16, signx);
int i, j; int i, j;
opus_val16 s;
int pulsesLeft; int pulsesLeft;
opus_val32 sum; opus_val32 sum;
opus_val32 xy; opus_val32 xy;
opus_val16 yy; opus_val16 yy;
unsigned collapse_mask;
SAVE_STACK; SAVE_STACK;
celt_assert2(K>0, "alg_quant() needs at least one pulse"); (void)arch;
celt_assert2(N>1, "alg_quant() needs at least two dimensions");
ALLOC(y, N, celt_norm); ALLOC(y, N, celt_norm);
ALLOC(iy, N, int); ALLOC(signx, N, int);
ALLOC(signx, N, opus_val16);
exp_rotation(X, N, 1, B, K, spread);
/* Get rid of the sign */ /* Get rid of the sign */
sum = 0; sum = 0;
j=0; do { j=0; do {
if (X[j]>0) signx[j] = X[j]<0;
signx[j]=1; /* OPT: Make sure the compiler doesn't use a branch on ABS16(). */
else { X[j] = ABS16(X[j]);
signx[j]=-1;
X[j]=-X[j];
}
iy[j] = 0; iy[j] = 0;
y[j] = 0; y[j] = 0;
} while (++j<N); } while (++j<N);
@ -229,7 +210,12 @@ unsigned alg_quant(celt_norm *X, int N, int K, int spread, int B, ec_enc *enc
while (++j<N); while (++j<N);
sum = QCONST16(1.f,14); sum = QCONST16(1.f,14);
} }
rcp = EXTRACT16(MULT16_32_Q16(K-1, celt_rcp(sum))); #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 { j=0; do {
#ifdef FIXED_POINT #ifdef FIXED_POINT
/* It's really important to round *towards zero* here */ /* It's really important to round *towards zero* here */
@ -244,12 +230,12 @@ unsigned alg_quant(celt_norm *X, int N, int K, int spread, int B, ec_enc *enc
pulsesLeft -= iy[j]; pulsesLeft -= iy[j];
} while (++j<N); } while (++j<N);
} }
celt_assert2(pulsesLeft>=1, "Allocated too many pulses in the quick pass"); celt_sig_assert(pulsesLeft>=0);
/* This should never happen, but just in case it does (e.g. on silence) /* This should never happen, but just in case it does (e.g. on silence)
we fill the first bin with pulses. */ we fill the first bin with pulses. */
#ifdef FIXED_POINT_DEBUG #ifdef FIXED_POINT_DEBUG
celt_assert2(pulsesLeft<=N+3, "Not enough pulses in the quick pass"); celt_sig_assert(pulsesLeft<=N+3);
#endif #endif
if (pulsesLeft > N+3) if (pulsesLeft > N+3)
{ {
@ -260,12 +246,12 @@ unsigned alg_quant(celt_norm *X, int N, int K, int spread, int B, ec_enc *enc
pulsesLeft=0; pulsesLeft=0;
} }
s = 1;
for (i=0;i<pulsesLeft;i++) for (i=0;i<pulsesLeft;i++)
{ {
opus_val16 Rxy, Ryy;
int best_id; int best_id;
opus_val32 best_num = -VERY_LARGE16; opus_val32 best_num;
opus_val16 best_den = 0; opus_val16 best_den;
#ifdef FIXED_POINT #ifdef FIXED_POINT
int rshift; int rshift;
#endif #endif
@ -275,10 +261,23 @@ unsigned alg_quant(celt_norm *X, int N, int K, int spread, int B, ec_enc *enc
best_id = 0; best_id = 0;
/* The squared magnitude term gets added anyway, so we might as well /* The squared magnitude term gets added anyway, so we might as well
add it outside the loop */ add it outside the loop */
yy = ADD32(yy, 1); yy = ADD16(yy, 1);
j=0;
/* 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 { do {
opus_val16 Rxy, Ryy;
/* Temporary sums of the new pulse(s) */ /* Temporary sums of the new pulse(s) */
Rxy = EXTRACT16(SHR32(ADD32(xy, EXTEND32(X[j])),rshift)); 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 */ /* We're multiplying y[j] by two so we don't have to do it here */
@ -289,8 +288,11 @@ unsigned alg_quant(celt_norm *X, int N, int K, int spread, int B, ec_enc *enc
Rxy = MULT16_16_Q15(Rxy,Rxy); Rxy = MULT16_16_Q15(Rxy,Rxy);
/* The idea is to check for num/den >= best_num/best_den, but that way /* The idea is to check for num/den >= best_num/best_den, but that way
we can do it without any division */ we can do it without any division */
/* OPT: Make sure to use conditional moves here */ /* OPT: It's not clear whether a cmov is faster than a branch here
if (MULT16_16(best_den, Rxy) > MULT16_16(Ryy, best_num)) 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_den = Ryy;
best_num = Rxy; best_num = Rxy;
@ -305,23 +307,47 @@ unsigned alg_quant(celt_norm *X, int N, int K, int spread, int B, ec_enc *enc
/* Only now that we've made the final choice, update y/iy */ /* 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 */ /* Multiplying y[j] by 2 so we don't have to do it everywhere else */
y[best_id] += 2*s; y[best_id] += 2;
iy[best_id]++; iy[best_id]++;
} }
/* Put the original sign back */ /* Put the original sign back */
j=0; j=0;
do { do {
X[j] = MULT16_16(signx[j],X[j]); /*iy[j] = signx[j] ? -iy[j] : iy[j];*/
if (signx[j] < 0) /* OPT: The is more likely to be compiled without a branch than the code above
iy[j] = -iy[j]; but has the same performance otherwise. */
iy[j] = (iy[j]^-signx[j]) + signx[j];
} while (++j<N); } while (++j<N);
RESTORE_STACK;
return yy;
}
unsigned alg_quant(celt_norm *X, int N, int K, int spread, int B, ec_enc *enc,
opus_val16 gain, int resynth, int arch)
{
VARDECL(int, iy);
opus_val16 yy;
unsigned collapse_mask;
SAVE_STACK;
celt_assert2(K>0, "alg_quant() needs at least one pulse");
celt_assert2(N>1, "alg_quant() needs at least two dimensions");
/* Covers vectorization by up to 4. */
ALLOC(iy, N+3, int);
exp_rotation(X, N, 1, B, K, spread);
yy = op_pvq_search(X, iy, K, N, arch);
encode_pulses(iy, N, K, enc); encode_pulses(iy, N, K, enc);
#ifdef RESYNTH if (resynth)
{
normalise_residual(iy, X, N, yy, gain); normalise_residual(iy, X, N, yy, gain);
exp_rotation(X, N, -1, B, K, spread); exp_rotation(X, N, -1, B, K, spread);
#endif }
collapse_mask = extract_collapse_mask(iy, N, B); collapse_mask = extract_collapse_mask(iy, N, B);
RESTORE_STACK; RESTORE_STACK;
@ -350,7 +376,7 @@ unsigned alg_unquant(celt_norm *X, int N, int K, int spread, int B,
} }
#ifndef OVERRIDE_renormalise_vector #ifndef OVERRIDE_renormalise_vector
void renormalise_vector(celt_norm *X, int N, opus_val16 gain) void renormalise_vector(celt_norm *X, int N, opus_val16 gain, int arch)
{ {
int i; int i;
#ifdef FIXED_POINT #ifdef FIXED_POINT
@ -360,7 +386,7 @@ void renormalise_vector(celt_norm *X, int N, opus_val16 gain)
opus_val16 g; opus_val16 g;
opus_val32 t; opus_val32 t;
celt_norm *xptr; celt_norm *xptr;
E = EPSILON + celt_inner_prod(X, X, N); E = EPSILON + celt_inner_prod(X, X, N, arch);
#ifdef FIXED_POINT #ifdef FIXED_POINT
k = celt_ilog2(E)>>1; k = celt_ilog2(E)>>1;
#endif #endif
@ -377,7 +403,7 @@ void renormalise_vector(celt_norm *X, int N, opus_val16 gain)
} }
#endif /* OVERRIDE_renormalise_vector */ #endif /* OVERRIDE_renormalise_vector */
int stereo_itheta(const celt_norm *X, const celt_norm *Y, int stereo, int N) int stereo_itheta(const celt_norm *X, const celt_norm *Y, int stereo, int N, int arch)
{ {
int i; int i;
int itheta; int itheta;
@ -396,8 +422,8 @@ int stereo_itheta(const celt_norm *X, const celt_norm *Y, int stereo, int N)
Eside = MAC16_16(Eside, s, s); Eside = MAC16_16(Eside, s, s);
} }
} else { } else {
Emid += celt_inner_prod(X, X, N); Emid += celt_inner_prod(X, X, N, arch);
Eside += celt_inner_prod(Y, Y, N); Eside += celt_inner_prod(Y, Y, N, arch);
} }
mid = celt_sqrt(Emid); mid = celt_sqrt(Emid);
side = celt_sqrt(Eside); side = celt_sqrt(Eside);
@ -405,7 +431,7 @@ int stereo_itheta(const celt_norm *X, const celt_norm *Y, int stereo, int N)
/* 0.63662 = 2/pi */ /* 0.63662 = 2/pi */
itheta = MULT16_16_Q15(QCONST16(0.63662f,15),celt_atan2p(side, mid)); itheta = MULT16_16_Q15(QCONST16(0.63662f,15),celt_atan2p(side, mid));
#else #else
itheta = (int)floor(.5f+16384*0.63662f*atan2(side,mid)); itheta = (int)floor(.5f+16384*0.63662f*fast_atan2f(side,mid));
#endif #endif
return itheta; return itheta;

View file

@ -37,6 +37,23 @@
#include "entdec.h" #include "entdec.h"
#include "modes.h" #include "modes.h"
#if (defined(OPUS_X86_MAY_HAVE_SSE2) && !defined(FIXED_POINT))
#include "x86/vq_sse.h"
#endif
#if defined(MIPSr1_ASM)
#include "mips/vq_mipsr1.h"
#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 /** 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 * 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. * to 1. This is the function that will typically require the most CPU.
@ -46,12 +63,8 @@
* @param enc Entropy encoder state * @param enc Entropy encoder state
* @ret A mask indicating which blocks in the band received pulses * @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, unsigned alg_quant(celt_norm *X, int N, int K, int spread, int B, ec_enc *enc,
ec_enc *enc opus_val16 gain, int resynth, int arch);
#ifdef RESYNTH
, opus_val16 gain
#endif
);
/** Algebraic pulse decoder /** Algebraic pulse decoder
* @param X Decoded normalised spectrum (returned) * @param X Decoded normalised spectrum (returned)
@ -63,8 +76,8 @@ unsigned alg_quant(celt_norm *X, int N, int K, int spread, int B,
unsigned alg_unquant(celt_norm *X, int N, int K, int spread, int B, unsigned alg_unquant(celt_norm *X, int N, int K, int spread, int B,
ec_dec *dec, opus_val16 gain); ec_dec *dec, opus_val16 gain);
void renormalise_vector(celt_norm *X, int N, opus_val16 gain); void renormalise_vector(celt_norm *X, int N, opus_val16 gain, int arch);
int stereo_itheta(const celt_norm *X, const celt_norm *Y, int stereo, int N); int stereo_itheta(const celt_norm *X, const celt_norm *Y, int stereo, int N, int arch);
#endif /* VQ_H */ #endif /* VQ_H */

View file

@ -0,0 +1,66 @@
/* 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)
#define OVERRIDE_CELT_FIR
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 celt_fir(x, num, y, N, ord, arch) \
((void)arch, celt_fir_sse4_1(x, num, y, N, ord, arch))
#else
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 celt_fir(x, num, y, N, ord, arch) \
((*CELT_FIR_IMPL[(arch) & OPUS_ARCHMASK])(x, num, y, N, ord, arch))
#endif
#endif
#endif

View file

@ -0,0 +1,89 @@
/* 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;
xcorr_kernel(rnum, x+i-ord, sums, ord, arch);
vecSum = _mm_loadu_si128((__m128i *)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 *)(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

View file

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

View file

@ -0,0 +1,192 @@
/* 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_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_SSE2) && !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_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)
#define OVERRIDE_DUAL_INNER_PROD
#define OVERRIDE_COMB_FILTER_CONST
#undef dual_inner_prod
#undef comb_filter_const
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 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))
#else
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
#endif
#endif

View file

@ -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 *)(&x[i + 0]));
inVec2_76543210 = _mm_loadu_si128((__m128i *)(&y[i + 0]));
inVec1_FEDCBA98 = _mm_loadu_si128((__m128i *)(&x[i + 8]));
inVec2_FEDCBA98 = _mm_loadu_si128((__m128i *)(&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 *)(&x[i + 0]));
inVec2_76543210 = _mm_loadu_si128((__m128i *)(&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

View file

@ -0,0 +1,195 @@
/* 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 *)(&x[i + 0]));
inVec2_76543210 = _mm_loadu_si128((__m128i *)(&y[i + 0]));
inVec1_FEDCBA98 = _mm_loadu_si128((__m128i *)(&x[i + 8]));
inVec2_FEDCBA98 = _mm_loadu_si128((__m128i *)(&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 *)(&x[i + 0]));
inVec2_76543210 = _mm_loadu_si128((__m128i *)(&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;
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 *)(&x[j + 0]));
vecY0 = _mm_loadu_si128((__m128i *)(&y[j + 0]));
vecY1 = _mm_loadu_si128((__m128i *)(&y[j + 1]));
vecY2 = _mm_loadu_si128((__m128i *)(&y[j + 2]));
vecY3 = _mm_loadu_si128((__m128i *)(&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);
}
for (;j<len;j++)
{
vecX = OP_CVTEPI16_EPI32_M64(&x[j + 0]);
vecX0 = _mm_shuffle_epi32(vecX, 0x00);
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 *)(&sum[0]));
initSum = _mm_add_epi32(initSum, vecSum);
_mm_storeu_si128((__m128i *)sum, initSum);
}
#endif

View file

@ -0,0 +1,50 @@
/* 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)
#define OVERRIDE_OP_PVQ_SEARCH
opus_val16 op_pvq_search_sse2(celt_norm *_X, int *iy, int K, int N, int arch);
#if defined(OPUS_X86_PRESUME_SSE2)
#define op_pvq_search(x, iy, K, N, arch) \
(op_pvq_search_sse2(x, iy, K, N, arch))
#else
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

View file

@ -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*)&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*)&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*)&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*)&iy[j], y4);
}
RESTORE_STACK;
return yy;
}
#endif

View file

@ -0,0 +1,167 @@
/* 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_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

View file

@ -0,0 +1,157 @@
/* 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_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_AVX) && !defined(OPUS_X86_PRESUME_AVX))
#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]) :
"0" (InfoType)
);
#else
__asm__ __volatile__ (
"cpuid":
"=a" (CPUInfo[0]),
"=b" (CPUInfo[1]),
"=c" (CPUInfo[2]),
"=d" (CPUInfo[3]) :
"0" (InfoType)
);
#endif
#elif defined(CPU_INFO_BY_C)
__get_cpuid(InfoType, &(CPUInfo[0]), &(CPUInfo[1]), &(CPUInfo[2]), &(CPUInfo[3]));
#endif
}
#endif
typedef struct CPU_Feature{
/* SIMD: 128-bit */
int HW_SSE;
int HW_SSE2;
int HW_SSE41;
/* SIMD: 256-bit */
int HW_AVX;
} CPU_Feature;
static void opus_cpu_feature_check(CPU_Feature *cpu_feature)
{
unsigned int info[4] = {0};
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_AVX = (info[2] & (1 << 28)) != 0;
}
else {
cpu_feature->HW_SSE = 0;
cpu_feature->HW_SSE2 = 0;
cpu_feature->HW_SSE41 = 0;
cpu_feature->HW_AVX = 0;
}
}
int opus_select_arch(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_AVX)
{
return arch;
}
arch++;
return arch;
}
#endif

View file

@ -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.
*/
#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_AVX)
# define MAY_HAVE_AVX(name) name ## _avx
# else
# define MAY_HAVE_AVX(name) name ## _c
# endif
# if defined(OPUS_HAVE_RTCD)
int opus_select_arch(void);
# endif
/*gcc appears to emit MOVDQA's to load the argument of an _mm_cvtepi8_epi32()
or _mm_cvtepi16_epi32() when optimizations are disabled, even though the
actual PMOVSXWD instruction takes an m32 or m64. Unlike a normal memory
reference, these require 16-byte alignment and load a full 16 bytes (instead
of 4 or 8), possibly reading out of bounds.
We can insert an explicit MOVD or MOVQ using _mm_cvtsi32_si128() or
_mm_loadl_epi64(), which should have the same semantics as an m32 or m64
reference in the PMOVSXWD instruction itself, but gcc is not smart enough to
optimize this out when optimizations ARE enabled.
Clang, in contrast, requires us to do this always for _mm_cvtepi8_epi32
(which is fair, since technically the compiler is always allowed to do the
dereference before invoking the function implementing the intrinsic).
However, it is smart enough to eliminate the extra MOVD instruction.
For _mm_cvtepi16_epi32, it does the right thing, though does *not* optimize out
the extra MOVQ if it's specified explicitly */
# if defined(__clang__) || !defined(__OPTIMIZE__)
# define OP_CVTEPI8_EPI32_M32(x) \
(_mm_cvtepi8_epi32(_mm_cvtsi32_si128(*(int *)(x))))
# else
# define OP_CVTEPI8_EPI32_M32(x) \
(_mm_cvtepi8_epi32(*(__m128i *)(x)))
#endif
/* similar reasoning about the instruction sequence as in the 32-bit macro above,
*/
# if defined(__clang__) || !defined(__OPTIMIZE__)
# define OP_CVTEPI16_EPI32_M64(x) \
(_mm_cvtepi16_epi32(_mm_loadl_epi64((__m128i *)(x))))
# else
# define OP_CVTEPI16_EPI32_M64(x) \
(_mm_cvtepi16_epi32(*(__m128i *)(x)))
# endif
#endif

View file

@ -0,0 +1,378 @@
/* 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.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "arch.h"
#include "float_cast.h"
#include "opus_private.h"
#include "opus_defines.h"
#include "mapping_matrix.h"
#define MATRIX_INDEX(nb_rows, row, col) (nb_rows * col + row)
opus_int32 mapping_matrix_get_size(int rows, int cols)
{
opus_int32 size;
/* Mapping Matrix must only support up to 255 channels in or out.
* Additionally, the total cell count must be <= 65004 octets in order
* for the matrix to be stored in an OGG header.
*/
if (rows > 255 || cols > 255)
return 0;
size = rows * (opus_int32)cols * sizeof(opus_int16);
if (size > 65004)
return 0;
return align(sizeof(MappingMatrix)) + align(size);
}
opus_int16 *mapping_matrix_get_data(const MappingMatrix *matrix)
{
/* void* cast avoids clang -Wcast-align warning */
return (opus_int16*)(void*)((char*)matrix + align(sizeof(MappingMatrix)));
}
void mapping_matrix_init(MappingMatrix * const matrix,
int rows, int cols, int gain, const opus_int16 *data, opus_int32 data_size)
{
int i;
opus_int16 *ptr;
#if !defined(ENABLE_ASSERTIONS)
(void)data_size;
#endif
celt_assert(align(data_size) == align(rows * cols * sizeof(opus_int16)));
matrix->rows = rows;
matrix->cols = cols;
matrix->gain = gain;
ptr = mapping_matrix_get_data(matrix);
for (i = 0; i < rows * cols; i++)
{
ptr[i] = data[i];
}
}
#ifndef DISABLE_FLOAT_API
void mapping_matrix_multiply_channel_in_float(
const MappingMatrix *matrix,
const float *input,
int input_rows,
opus_val16 *output,
int output_row,
int output_rows,
int frame_size)
{
/* Matrix data is ordered col-wise. */
opus_int16* matrix_data;
int i, col;
celt_assert(input_rows <= matrix->cols && output_rows <= matrix->rows);
matrix_data = mapping_matrix_get_data(matrix);
for (i = 0; i < frame_size; i++)
{
float tmp = 0;
for (col = 0; col < input_rows; col++)
{
tmp +=
matrix_data[MATRIX_INDEX(matrix->rows, output_row, col)] *
input[MATRIX_INDEX(input_rows, col, i)];
}
#if defined(FIXED_POINT)
output[output_rows * i] = FLOAT2INT16((1/32768.f)*tmp);
#else
output[output_rows * i] = (1/32768.f)*tmp;
#endif
}
}
void mapping_matrix_multiply_channel_out_float(
const MappingMatrix *matrix,
const opus_val16 *input,
int input_row,
int input_rows,
float *output,
int output_rows,
int frame_size
)
{
/* Matrix data is ordered col-wise. */
opus_int16* matrix_data;
int i, row;
float input_sample;
celt_assert(input_rows <= matrix->cols && output_rows <= matrix->rows);
matrix_data = mapping_matrix_get_data(matrix);
for (i = 0; i < frame_size; i++)
{
#if defined(FIXED_POINT)
input_sample = (1/32768.f)*input[input_rows * i];
#else
input_sample = input[input_rows * i];
#endif
for (row = 0; row < output_rows; row++)
{
float tmp =
(1/32768.f)*matrix_data[MATRIX_INDEX(matrix->rows, row, input_row)] *
input_sample;
output[MATRIX_INDEX(output_rows, row, i)] += tmp;
}
}
}
#endif /* DISABLE_FLOAT_API */
void mapping_matrix_multiply_channel_in_short(
const MappingMatrix *matrix,
const opus_int16 *input,
int input_rows,
opus_val16 *output,
int output_row,
int output_rows,
int frame_size)
{
/* Matrix data is ordered col-wise. */
opus_int16* matrix_data;
int i, col;
celt_assert(input_rows <= matrix->cols && output_rows <= matrix->rows);
matrix_data = mapping_matrix_get_data(matrix);
for (i = 0; i < frame_size; i++)
{
opus_val32 tmp = 0;
for (col = 0; col < input_rows; col++)
{
#if defined(FIXED_POINT)
tmp +=
((opus_int32)matrix_data[MATRIX_INDEX(matrix->rows, output_row, col)] *
(opus_int32)input[MATRIX_INDEX(input_rows, col, i)]) >> 8;
#else
tmp +=
matrix_data[MATRIX_INDEX(matrix->rows, output_row, col)] *
input[MATRIX_INDEX(input_rows, col, i)];
#endif
}
#if defined(FIXED_POINT)
output[output_rows * i] = (opus_int16)((tmp + 64) >> 7);
#else
output[output_rows * i] = (1/(32768.f*32768.f))*tmp;
#endif
}
}
void mapping_matrix_multiply_channel_out_short(
const MappingMatrix *matrix,
const opus_val16 *input,
int input_row,
int input_rows,
opus_int16 *output,
int output_rows,
int frame_size)
{
/* Matrix data is ordered col-wise. */
opus_int16* matrix_data;
int i, row;
opus_int32 input_sample;
celt_assert(input_rows <= matrix->cols && output_rows <= matrix->rows);
matrix_data = mapping_matrix_get_data(matrix);
for (i = 0; i < frame_size; i++)
{
#if defined(FIXED_POINT)
input_sample = (opus_int32)input[input_rows * i];
#else
input_sample = (opus_int32)FLOAT2INT16(input[input_rows * i]);
#endif
for (row = 0; row < output_rows; row++)
{
opus_int32 tmp =
(opus_int32)matrix_data[MATRIX_INDEX(matrix->rows, row, input_row)] *
input_sample;
output[MATRIX_INDEX(output_rows, row, i)] += (tmp + 16384) >> 15;
}
}
}
const MappingMatrix mapping_matrix_foa_mixing = { 6, 6, 0 };
const opus_int16 mapping_matrix_foa_mixing_data[36] = {
16384, 0, -16384, 23170, 0, 0, 16384, 23170,
16384, 0, 0, 0, 16384, 0, -16384, -23170,
0, 0, 16384, -23170, 16384, 0, 0, 0,
0, 0, 0, 0, 32767, 0, 0, 0,
0, 0, 0, 32767
};
const MappingMatrix mapping_matrix_soa_mixing = { 11, 11, 0 };
const opus_int16 mapping_matrix_soa_mixing_data[121] = {
10923, 7723, 13377, -13377, 11585, 9459, 7723, -16384,
-6689, 0, 0, 10923, 7723, 13377, 13377, -11585,
9459, 7723, 16384, -6689, 0, 0, 10923, -15447,
13377, 0, 0, -18919, 7723, 0, 13377, 0,
0, 10923, 7723, -13377, -13377, 11585, -9459, 7723,
16384, -6689, 0, 0, 10923, -7723, 0, 13377,
-16384, 0, -15447, 0, 9459, 0, 0, 10923,
-7723, 0, -13377, 16384, 0, -15447, 0, 9459,
0, 0, 10923, 15447, 0, 0, 0, 0,
-15447, 0, -18919, 0, 0, 10923, 7723, -13377,
13377, -11585, -9459, 7723, -16384, -6689, 0, 0,
10923, -15447, -13377, 0, 0, 18919, 7723, 0,
13377, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 32767, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
32767
};
const MappingMatrix mapping_matrix_toa_mixing = { 18, 18, 0 };
const opus_int16 mapping_matrix_toa_mixing_data[324] = {
8208, 0, -881, 14369, 0, 0, -8192, -4163,
13218, 0, 0, 0, 11095, -8836, -6218, 14833,
0, 0, 8208, -10161, 881, 10161, -13218, -2944,
-8192, 2944, 0, -10488, -6218, 6248, -11095, -6248,
0, -10488, 0, 0, 8208, 10161, 881, -10161,
-13218, 2944, -8192, -2944, 0, 10488, -6218, -6248,
-11095, 6248, 0, 10488, 0, 0, 8176, 5566,
-11552, 5566, 9681, -11205, 8192, -11205, 0, 4920,
-15158, 9756, -3334, 9756, 0, -4920, 0, 0,
8176, 7871, 11552, 0, 0, 15846, 8192, 0,
-9681, -6958, 0, 13797, 3334, 0, -15158, 0,
0, 0, 8176, 0, 11552, 7871, 0, 0,
8192, 15846, 9681, 0, 0, 0, 3334, 13797,
15158, 6958, 0, 0, 8176, 5566, -11552, -5566,
-9681, -11205, 8192, 11205, 0, 4920, 15158, 9756,
-3334, -9756, 0, 4920, 0, 0, 8208, 14369,
-881, 0, 0, -4163, -8192, 0, -13218, -14833,
0, -8836, 11095, 0, 6218, 0, 0, 0,
8208, 10161, 881, 10161, 13218, 2944, -8192, 2944,
0, 10488, 6218, -6248, -11095, -6248, 0, -10488,
0, 0, 8208, -14369, -881, 0, 0, 4163,
-8192, 0, -13218, 14833, 0, 8836, 11095, 0,
6218, 0, 0, 0, 8208, 0, -881, -14369,
0, 0, -8192, 4163, 13218, 0, 0, 0,
11095, 8836, -6218, -14833, 0, 0, 8176, -5566,
-11552, 5566, -9681, 11205, 8192, -11205, 0, -4920,
15158, -9756, -3334, 9756, 0, -4920, 0, 0,
8176, 0, 11552, -7871, 0, 0, 8192, -15846,
9681, 0, 0, 0, 3334, -13797, 15158, -6958,
0, 0, 8176, -7871, 11552, 0, 0, -15846,
8192, 0, -9681, 6958, 0, -13797, 3334, 0,
-15158, 0, 0, 0, 8176, -5566, -11552, -5566,
9681, 11205, 8192, 11205, 0, -4920, -15158, -9756,
-3334, -9756, 0, 4920, 0, 0, 8208, -10161,
881, -10161, 13218, -2944, -8192, -2944, 0, -10488,
6218, 6248, -11095, 6248, 0, 10488, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
32767, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 32767
};
const MappingMatrix mapping_matrix_foa_demixing = { 6, 6, 0 };
const opus_int16 mapping_matrix_foa_demixing_data[36] = {
16384, 16384, 16384, 16384, 0, 0, 0, 23170,
0, -23170, 0, 0, -16384, 16384, -16384, 16384,
0, 0, 23170, 0, -23170, 0, 0, 0,
0, 0, 0, 0, 32767, 0, 0, 0,
0, 0, 0, 32767
};
const MappingMatrix mapping_matrix_soa_demixing = { 11, 11, 3050 };
const opus_int16 mapping_matrix_soa_demixing_data[121] = {
2771, 2771, 2771, 2771, 2771, 2771, 2771, 2771,
2771, 0, 0, 10033, 10033, -20066, 10033, 14189,
14189, -28378, 10033, -20066, 0, 0, 3393, 3393,
3393, -3393, 0, 0, 0, -3393, -3393, 0,
0, -17378, 17378, 0, -17378, -24576, 24576, 0,
17378, 0, 0, 0, -14189, 14189, 0, -14189,
-28378, 28378, 0, 14189, 0, 0, 0, 2399,
2399, -4799, -2399, 0, 0, 0, -2399, 4799,
0, 0, 1959, 1959, 1959, 1959, -3918, -3918,
-3918, 1959, 1959, 0, 0, -4156, 4156, 0,
4156, 0, 0, 0, -4156, 0, 0, 0,
8192, 8192, -16384, 8192, 16384, 16384, -32768, 8192,
-16384, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 8312, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
8312
};
const MappingMatrix mapping_matrix_toa_demixing = { 18, 18, 0 };
const opus_int16 mapping_matrix_toa_demixing_data[324] = {
8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192,
8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192,
0, 0, 0, -9779, 9779, 6263, 8857, 0,
6263, 13829, 9779, -13829, 0, -6263, 0, -8857,
-6263, -9779, 0, 0, -3413, 3413, 3413, -11359,
11359, 11359, -11359, -3413, 3413, -3413, -3413, -11359,
11359, 11359, -11359, 3413, 0, 0, 13829, 9779,
-9779, 6263, 0, 8857, -6263, 0, 9779, 0,
-13829, 6263, -8857, 0, -6263, -9779, 0, 0,
0, -15617, -15617, 6406, 0, 0, -6406, 0,
15617, 0, 0, -6406, 0, 0, 6406, 15617,
0, 0, 0, -5003, 5003, -10664, 15081, 0,
-10664, -7075, 5003, 7075, 0, 10664, 0, -15081,
10664, -5003, 0, 0, -8176, -8176, -8176, 8208,
8208, 8208, 8208, -8176, -8176, -8176, -8176, 8208,
8208, 8208, 8208, -8176, 0, 0, -7075, 5003,
-5003, -10664, 0, 15081, 10664, 0, 5003, 0,
7075, -10664, -15081, 0, 10664, -5003, 0, 0,
15617, 0, 0, 0, -6406, 6406, 0, -15617,
0, -15617, 15617, 0, 6406, -6406, 0, 0,
0, 0, 0, -11393, 11393, 2993, -4233, 0,
2993, -16112, 11393, 16112, 0, -2993, 0, 4233,
-2993, -11393, 0, 0, 0, -9974, -9974, -13617,
0, 0, 13617, 0, 9974, 0, 0, 13617,
0, 0, -13617, 9974, 0, 0, 0, 5579,
-5579, 10185, 14403, 0, 10185, -7890, -5579, 7890,
0, -10185, 0, -14403, -10185, 5579, 0, 0,
11826, -11826, -11826, -901, 901, 901, -901, 11826,
-11826, 11826, 11826, -901, 901, 901, -901, -11826,
0, 0, -7890, -5579, 5579, 10185, 0, 14403,
-10185, 0, -5579, 0, 7890, 10185, -14403, 0,
-10185, 5579, 0, 0, -9974, 0, 0, 0,
-13617, 13617, 0, 9974, 0, 9974, -9974, 0,
13617, -13617, 0, 0, 0, 0, 16112, -11393,
11393, -2993, 0, 4233, 2993, 0, -11393, 0,
-16112, -2993, -4233, 0, 2993, 11393, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
32767, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 32767
};

View file

@ -0,0 +1,133 @@
/* 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 mapping_matrix.h
* @brief Opus reference implementation mapping matrix API
*/
#ifndef MAPPING_MATRIX_H
#define MAPPING_MATRIX_H
#include "opus_types.h"
#include "opus_projection.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct MappingMatrix
{
int rows; /* number of channels outputted from matrix. */
int cols; /* number of channels inputted to matrix. */
int gain; /* in dB. S7.8-format. */
/* Matrix cell data goes here using col-wise ordering. */
} MappingMatrix;
opus_int32 mapping_matrix_get_size(int rows, int cols);
opus_int16 *mapping_matrix_get_data(const MappingMatrix *matrix);
void mapping_matrix_init(
MappingMatrix * const st,
int rows,
int cols,
int gain,
const opus_int16 *data,
opus_int32 data_size
);
#ifndef DISABLE_FLOAT_API
void mapping_matrix_multiply_channel_in_float(
const MappingMatrix *matrix,
const float *input,
int input_rows,
opus_val16 *output,
int output_row,
int output_rows,
int frame_size
);
void mapping_matrix_multiply_channel_out_float(
const MappingMatrix *matrix,
const opus_val16 *input,
int input_row,
int input_rows,
float *output,
int output_rows,
int frame_size
);
#endif /* DISABLE_FLOAT_API */
void mapping_matrix_multiply_channel_in_short(
const MappingMatrix *matrix,
const opus_int16 *input,
int input_rows,
opus_val16 *output,
int output_row,
int output_rows,
int frame_size
);
void mapping_matrix_multiply_channel_out_short(
const MappingMatrix *matrix,
const opus_val16 *input,
int input_row,
int input_rows,
opus_int16 *output,
int output_rows,
int frame_size
);
/* Pre-computed mixing and demixing matrices for 1st to 3rd-order ambisonics.
* foa: first-order ambisonics
* soa: second-order ambisonics
* toa: third-order ambisonics
*/
extern const MappingMatrix mapping_matrix_foa_mixing;
extern const opus_int16 mapping_matrix_foa_mixing_data[36];
extern const MappingMatrix mapping_matrix_soa_mixing;
extern const opus_int16 mapping_matrix_soa_mixing_data[121];
extern const MappingMatrix mapping_matrix_toa_mixing;
extern const opus_int16 mapping_matrix_toa_mixing_data[324];
extern const MappingMatrix mapping_matrix_foa_demixing;
extern const opus_int16 mapping_matrix_foa_demixing_data[36];
extern const MappingMatrix mapping_matrix_soa_demixing;
extern const opus_int16 mapping_matrix_soa_demixing_data[121];
extern const MappingMatrix mapping_matrix_toa_demixing;
extern const opus_int16 mapping_matrix_toa_demixing_data[324];
#ifdef __cplusplus
}
#endif
#endif /* MAPPING_MATRIX_H */

View file

@ -0,0 +1,144 @@
/* Copyright (c) 2008-2011 Octasic Inc.
2012-2017 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 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 HAVE_CONFIG_H
#include "config.h"
#endif
#include <math.h>
#include "opus_types.h"
#include "opus_defines.h"
#include "arch.h"
#include "tansig_table.h"
#include "mlp.h"
static OPUS_INLINE float tansig_approx(float x)
{
int i;
float y, dy;
float sign=1;
/* Tests are reversed to catch NaNs */
if (!(x<8))
return 1;
if (!(x>-8))
return -1;
#ifndef FIXED_POINT
/* Another check in case of -ffast-math */
if (celt_isnan(x))
return 0;
#endif
if (x<0)
{
x=-x;
sign=-1;
}
i = (int)floor(.5f+25*x);
x -= .04f*i;
y = tansig_table[i];
dy = 1-y*y;
y = y + x*dy*(1 - y*x);
return sign*y;
}
static OPUS_INLINE float sigmoid_approx(float x)
{
return .5f + .5f*tansig_approx(.5f*x);
}
static void gemm_accum(float *out, const opus_int8 *weights, int rows, int cols, int col_stride, const float *x)
{
int i, j;
for (i=0;i<rows;i++)
{
for (j=0;j<cols;j++)
out[i] += weights[j*col_stride + i]*x[j];
}
}
void compute_dense(const DenseLayer *layer, float *output, const float *input)
{
int i;
int N, M;
int stride;
M = layer->nb_inputs;
N = layer->nb_neurons;
stride = N;
for (i=0;i<N;i++)
output[i] = layer->bias[i];
gemm_accum(output, layer->input_weights, N, M, stride, input);
for (i=0;i<N;i++)
output[i] *= WEIGHTS_SCALE;
if (layer->sigmoid) {
for (i=0;i<N;i++)
output[i] = sigmoid_approx(output[i]);
} else {
for (i=0;i<N;i++)
output[i] = tansig_approx(output[i]);
}
}
void compute_gru(const GRULayer *gru, float *state, const float *input)
{
int i;
int N, M;
int stride;
float tmp[MAX_NEURONS];
float z[MAX_NEURONS];
float r[MAX_NEURONS];
float h[MAX_NEURONS];
M = gru->nb_inputs;
N = gru->nb_neurons;
stride = 3*N;
/* Compute update gate. */
for (i=0;i<N;i++)
z[i] = gru->bias[i];
gemm_accum(z, gru->input_weights, N, M, stride, input);
gemm_accum(z, gru->recurrent_weights, N, N, stride, state);
for (i=0;i<N;i++)
z[i] = sigmoid_approx(WEIGHTS_SCALE*z[i]);
/* Compute reset gate. */
for (i=0;i<N;i++)
r[i] = gru->bias[N + i];
gemm_accum(r, &gru->input_weights[N], N, M, stride, input);
gemm_accum(r, &gru->recurrent_weights[N], N, N, stride, state);
for (i=0;i<N;i++)
r[i] = sigmoid_approx(WEIGHTS_SCALE*r[i]);
/* Compute output. */
for (i=0;i<N;i++)
h[i] = gru->bias[2*N + i];
for (i=0;i<N;i++)
tmp[i] = state[i] * r[i];
gemm_accum(h, &gru->input_weights[2*N], N, M, stride, input);
gemm_accum(h, &gru->recurrent_weights[2*N], N, N, stride, tmp);
for (i=0;i<N;i++)
h[i] = z[i]*state[i] + (1-z[i])*tansig_approx(WEIGHTS_SCALE*h[i]);
for (i=0;i<N;i++)
state[i] = h[i];
}

View file

@ -0,0 +1,60 @@
/* Copyright (c) 2017 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 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.
*/
#ifndef _MLP_H_
#define _MLP_H_
#include "opus_types.h"
#define WEIGHTS_SCALE (1.f/128)
#define MAX_NEURONS 32
typedef struct {
const opus_int8 *bias;
const opus_int8 *input_weights;
int nb_inputs;
int nb_neurons;
int sigmoid;
} DenseLayer;
typedef struct {
const opus_int8 *bias;
const opus_int8 *input_weights;
const opus_int8 *recurrent_weights;
int nb_inputs;
int nb_neurons;
} GRULayer;
extern const DenseLayer layer0;
extern const GRULayer layer1;
extern const DenseLayer layer2;
void compute_dense(const DenseLayer *layer, float *output, const float *input);
void compute_gru(const GRULayer *gru, float *state, const float *input);
#endif /* _MLP_H_ */

View file

@ -0,0 +1,672 @@
/*This file is automatically generated from a Keras model*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "mlp.h"
static const opus_int8 layer0_weights[800] = {
-30, -9, 2, -12, 5, -1, 8, 9,
9, 8, -13, 18, -17, -34, -5, 17,
-11, 0, -4, 10, 2, 10, 15, -8,
2, -1, 0, 5, 13, -3, -16, 1,
-5, 3, 7, -28, -13, 6, 36, -3,
19, -60, -17, -28, 7, -11, -30, -7,
2, -42, -21, -3, 6, -22, 33, -9,
7, -30, 21, -14, 24, -11, -20, -18,
-5, -12, 12, -49, -50, -49, 16, 9,
-37, -1, 9, 34, -13, -31, -31, 12,
16, 44, -42, 2, -9, 8, -18, -6,
9, 36, 19, 11, 13, 12, -21, 3,
-28, -12, 3, 33, 25, -14, 11, 1,
-94, -39, 18, -12, -11, -15, -7, 49,
52, 10, -43, 9, 57, 8, 21, -6,
14, -15, 44, -8, 7, -30, -13, -2,
-9, 25, -2, -127, 18, -11, -52, 26,
-27, 27, 10, -10, 7, 43, 6, -24,
41, 10, -18, -27, 10, 17, 9, 10,
-17, -10, 20, -6, 22, 55, 35, -80,
36, 25, -24, -36, 15, 9, -19, 88,
19, 64, -51, -35, 17, 0, -7, 41,
-16, 27, 4, 15, -1, 18, -16, 47,
-39, -54, -8, 13, -25, -20, 102, -18,
-5, 44, 11, -28, 71, 2, -51, -5,
5, 2, -83, -9, -29, 8, 21, -53,
58, -37, -7, 13, 38, 9, 34, -1,
-41, 21, 4, -24, -36, -33, -21, 32,
75, -2, 1, -68, -1, 47, -29, 32,
20, 12, -65, -87, 5, 16, -12, 24,
40, 15, 7, 19, -26, -17, 17, 6,
-2, -37, -30, -9, 32, -127, -39, 0,
-31, -27, 4, -22, 23, -6, -77, 35,
-61, 32, -37, -24, 13, -11, -1, -40,
-3, 17, -7, 13, 11, 59, -19, 10,
6, -18, 0, 13, 3, -6, -23, 19,
11, -17, 13, -1, -80, 40, -53, 69,
-29, -54, 0, -4, 33, -25, -2, 38,
35, 36, -15, 46, 2, -13, -16, -8,
-8, 12, -24, -9, -55, -5, -9, 32,
11, 7, 12, -18, -10, -86, -38, 54,
37, -25, 18, -43, 7, -27, -27, -54,
13, 9, 22, 70, 6, 35, -7, 23,
-15, -44, -6, 7, -66, -85, 32, 40,
-19, -9, -7, 12, -15, 7, 2, 6,
-35, 11, 28, 0, 26, 14, 1, 1,
4, 12, 18, 35, 22, -18, -3, 14,
-1, 7, 14, -8, -14, -3, 4, -3,
-19, -7, -1, -25, -27, 25, -26, -2,
33, -22, -27, -25, 4, -9, 7, 21,
26, -30, 10, -9, -20, 11, 27, 10,
5, -18, 14, -4, 2, -17, -5, -7,
-9, -13, 15, 29, 1, -10, -16, -10,
35, 36, -7, -22, -44, 17, 30, 22,
21, -1, 22, -11, 32, -8, -7, 5,
-10, 5, 30, -20, 29, -20, -34, 12,
-4, -6, 6, -13, 10, -5, -68, -1,
24, 9, 19, -24, -64, 31, 19, 27,
-26, 75, -45, 41, 39, -42, 8, 6,
23, -30, 16, -25, 30, 34, 8, -38,
-3, 18, 16, -31, 22, -4, -9, 1,
20, 9, 38, -32, 0, -45, 0, -6,
-13, 11, -25, -32, -22, 31, -24, -11,
-11, -4, -4, 20, -34, 22, 20, 9,
-25, 27, -5, 28, -29, 29, 6, 21,
-6, -18, 54, 4, -46, 23, 21, -14,
-31, 36, -41, -24, 4, 22, 10, 11,
7, 36, -32, -13, -52, -17, 24, 28,
-37, -36, -1, 24, 9, -38, 35, 48,
18, 2, -1, 45, 10, 39, 24, -38,
13, 8, -16, 8, 25, 11, 7, -29,
-11, 7, 20, -30, -38, -45, 14, -18,
-28, -9, 65, 61, 22, -53, -38, -16,
36, 46, 20, -39, 32, -61, -6, -6,
-36, -33, -18, -28, 56, 101, 45, 11,
-28, -23, -29, -61, 20, -47, 2, 48,
27, -17, 1, 40, 1, 3, -51, 15,
35, 28, 22, 35, 53, -61, -29, 12,
-6, -21, 10, 3, -20, 2, -25, 1,
-6, 31, 11, -3, 1, -10, -52, 6,
126, -105, 122, 127, -128, 127, 127, -128,
127, 108, 12, 127, 48, -128, -36, -128,
127, 127, -128, -128, 127, 89, -128, 127,
-128, -128, -128, 127, 127, -128, -128, -93,
-82, 20, 125, 65, -82, 127, 38, -74,
81, 88, -88, 79, 51, -47, -111, -26,
14, 83, -88, -112, 24, 35, -101, 98,
-99, -48, -45, 46, 83, -60, -79, 45,
-20, -41, 9, 4, 52, 54, 93, -10,
4, 13, 3, 123, 6, 94, -111, -69,
-14, -31, 10, 12, 53, -79, -11, -21,
-2, -44, -72, 92, 65, -57, 56, -38,
127, -56, -128, 127, 127, -128, 86, 117,
-75, -128, 127, -19, -99, -112, 127, -128,
127, -48, 114, 118, -128, -128, 117, -17,
-6, 121, -128, 127, -128, 82, 54, -106,
127, 127, -33, 100, -39, -23, 18, -78,
-34, -29, -1, -30, 127, -26, 127, -128,
126, -128, 27, -23, -79, -120, -127, 127,
72, 66, 29, 7, -66, -56, -117, -128
};
static const opus_int8 layer0_bias[32] = {
51, -16, 1, 13, -5, -6, -16, -7,
11, -6, 106, 26, 28, -14, 21, -29,
7, 18, -18, -17, 21, -17, -9, 20,
-25, -3, -34, 48, 11, -13, -31, -20
};
static const opus_int8 layer1_weights[2304] = {
22, -1, -7, 7, 29, -27, -31, -17,
-13, 33, 44, -8, 11, 33, 24, 78,
15, 19, 30, -2, -24, 5, 49, 5,
36, 29, -14, -11, -48, -33, 21, -42,
-38, -12, 55, -37, 54, -8, 1, 36,
17, 0, 51, 31, 59, 7, -12, 53,
4, 32, -14, 48, 5, -10, -16, -8,
1, -16, -56, -24, -6, 18, -2, 23,
6, 46, -6, -10, 20, 35, -44, -15,
-49, 36, 16, 5, -7, -79, -67, 12,
70, -3, -79, -54, -85, -24, 47, -22,
33, 21, 69, -1, 11, 22, 14, -16,
-16, -22, -28, -11, 11, -41, 31, -26,
-33, -19, -4, 27, 32, -50, 5, -10,
-38, -22, -8, 35, -31, 1, -41, -15,
-11, 44, 28, -17, -41, -23, 17, 2,
-23, -26, -13, -13, -17, 6, 14, -31,
-25, 9, -19, 39, -8, 4, 31, -1,
-45, -11, -28, -92, -46, -15, 21, 118,
-22, 45, -51, 11, -20, -20, -15, 13,
-21, -97, -29, -32, -23, -42, 94, 1,
23, -8, 63, -3, -46, 19, -26, 32,
-40, -74, -26, 26, -4, -13, 30, -20,
-30, -25, -14, -31, -45, -43, 4, -60,
-48, -12, -34, 2, 2, 3, 13, 15,
11, 16, 5, 46, -9, -55, -16, -57,
29, 14, 38, -50, -2, -44, -11, -8,
52, -27, -38, -7, 20, 47, 17, -59,
0, 47, 46, -63, 35, -17, 19, 33,
68, -19, 2, 15, -16, 28, -16, -103,
26, -35, 47, -39, -60, 30, 31, -23,
-52, -13, 116, 47, -25, 30, 40, 30,
-22, 2, 12, -27, -18, 31, -10, 27,
-8, -66, 12, 14, 4, -26, -28, -13,
3, 13, -26, -51, 37, 5, 2, -21,
47, 3, 13, 25, -41, -27, -8, -4,
5, -76, -33, 28, 10, 9, -46, -74,
19, 28, 25, 31, 54, -55, 68, 38,
-24, -32, 2, 4, 68, 11, -1, 99,
5, 16, -2, -74, 40, 26, -26, 33,
31, -1, -68, 14, -6, 25, 9, 29,
60, 61, 7, -7, 0, -24, 7, 77,
4, -1, 16, -7, 13, -15, -19, 28,
-31, -24, -16, 37, 24, 13, 30, 10,
-30, 11, 11, -10, 22, 60, 28, 45,
-3, -40, -62, -5, -102, 9, -32, -27,
-54, 21, 15, -5, 37, -43, -11, 37,
-19, 47, -64, -128, -27, -114, 21, -66,
59, 46, -3, -12, -87, -9, 4, 19,
-113, -36, 78, 57, -26, -38, -77, -10,
6, 6, -75, 25, -97, -11, 33, -46,
1, 13, -21, -33, -20, 16, -6, -3,
-11, -4, -27, 38, 8, -41, -2, -33,
18, 19, -26, 1, -29, -22, -4, -14,
-55, -11, -80, -3, 11, 34, 90, 51,
11, 17, 43, 36, 127, -32, 29, 103,
9, 27, 13, 64, 56, 70, -14, 3,
-12, 10, 37, 3, 12, -22, -10, 46,
28, 10, 20, 26, -24, 18, 9, 7,
14, 34, -5, -7, 31, -14, -56, 11,
-18, -8, -17, -7, -10, -40, 10, -33,
-32, -43, 5, 9, 11, -4, 10, 50,
-12, -5, 46, 9, 7, 1, 11, 15,
91, -17, 7, -50, 23, 6, -30, -99,
0, -17, 14, 8, -10, -25, -30, -69,
-62, 31, 127, 114, -23, 101, -5, -54,
-6, -22, 7, -56, 39, 18, -29, 0,
46, 8, -79, 4, -21, 18, -32, 62,
-12, -8, -12, -58, 31, -32, 17, 6,
-24, 25, 24, 9, -4, -19, 45, 6,
17, -14, 5, -27, 16, -4, -41, 25,
-36, 5, 15, 12, 50, 27, 25, 23,
-44, -69, -9, -19, -48, -8, 4, 12,
-6, 13, -19, -30, -36, 26, 37, -1,
-3, -30, -42, -14, -10, -20, 26, -54,
-27, -44, 4, 73, -26, 90, 32, -69,
-29, -16, 3, 103, 15, -17, 37, 24,
-23, -31, 33, -37, -64, 25, 13, -81,
-28, -32, 27, 5, -35, -23, 15, -22,
19, -7, 9, 30, 19, -23, 27, -13,
43, 29, -29, -6, 9, -40, -33, -33,
-32, 9, 11, -48, -8, -23, -52, 46,
17, -22, -42, 35, -15, -41, 16, 34,
31, -42, -19, -11, 55, 7, -39, 89,
-11, -33, 20, -14, 22, 32, 3, -17,
-6, 14, 34, 1, 55, -21, -90, -8,
18, 27, 13, -29, 21, 15, -33, -51,
-9, -11, 4, -16, -18, 23, -4, -4,
48, 1, 7, 29, -14, -12, -16, 17,
35, 8, 0, -7, -2, 9, 8, 17,
-6, 53, -32, -21, -50, 5, 99, -60,
-5, -53, 10, -31, 12, -5, 7, 80,
36, 18, -31, 9, 98, 36, -63, -35,
4, -13, -28, -24, 28, -13, 18, 16,
-1, -18, -34, 10, 20, 7, 4, 29,
11, 25, -7, 36, 14, 45, 24, 1,
-16, 30, 6, 35, -6, -11, -24, 13,
-1, 27, 39, 20, 48, -11, -4, -13,
28, 11, -31, -18, 31, -29, 22, -2,
-20, -16, 5, 30, -12, -28, -3, 93,
-16, 23, 18, -29, 6, -54, -37, 28,
-3, -3, -47, -3, -36, -55, -3, 41,
-10, 47, -2, 23, 42, -7, -71, -27,
83, -64, 7, -24, 8, 26, -17, 15,
12, 31, -30, -38, -13, -33, -56, 4,
-17, 20, 18, 1, -30, -5, -6, -31,
-14, -37, 0, 22, 10, -30, 37, -17,
18, 6, 5, 23, -36, -32, 14, 18,
-13, -61, -52, -69, 44, -30, 16, 18,
-4, -25, 14, 81, 26, -8, -23, -59,
52, -104, 17, 119, -32, 26, 17, 1,
23, 45, 29, -64, -57, -14, 73, 21,
-13, -13, 9, -68, -7, -52, 3, 24,
-39, 44, -15, 27, 14, 19, -9, -28,
-11, 5, 3, -34, -2, 2, 22, -6,
-23, 4, 3, 13, -22, -13, -10, -18,
29, 6, 44, -13, -24, -8, 2, 30,
14, 43, 6, 17, -73, -6, -7, 20,
-80, -7, -7, -28, 15, -69, -38, -5,
-100, -35, 15, -79, 23, 29, -18, -27,
21, -66, -37, 8, -22, -39, 48, 4,
-13, 1, -9, 11, -29, 22, 6, -49,
32, -14, 47, -18, -4, 44, -52, -74,
43, 30, 23, -14, 5, 0, -27, 4,
-7, 10, -4, 10, 1, -16, 11, -18,
-2, -5, 2, -11, 0, -20, -4, 38,
74, 59, 39, 64, -10, 26, -3, -40,
-68, 3, -30, -51, 8, -19, -27, -46,
51, 52, 54, 36, 90, 92, 14, 13,
-5, 0, 16, -62, 16, 11, -47, -37,
-6, -5, 21, 54, -57, 32, 42, -6,
62, -9, 16, 21, 24, 9, -10, -4,
33, 50, 13, -15, 1, -35, -48, 18,
-11, -17, -67, -13, 21, 38, -44, 36,
-16, 29, 17, 5, -10, 18, 17, -32,
2, 8, 22, -56, -15, -32, 40, 43,
19, 46, -7, -100, -96, 19, 53, 24,
21, -26, -48, -101, -82, 61, 38, -85,
-28, -34, -1, 63, -5, -5, 39, 39,
-38, 32, -12, -28, 20, 40, -8, 2,
31, 12, -35, -13, 20, -25, 30, 8,
3, -13, -9, -20, 2, -13, 24, 37,
-10, 33, 6, 20, -16, -24, -6, -6,
-19, -5, 22, 21, 10, 11, -4, -39,
-1, 6, 49, 41, -15, -57, 21, -62,
77, -69, -13, 0, -74, 1, -7, -38,
-8, 6, 63, 28, 4, 26, -52, 82,
63, 13, 45, -33, 44, -52, -65, -21,
-46, -49, 64, -17, 32, 24, 68, -39,
-16, -5, -26, 28, 5, -61, -28, 2,
24, 11, -12, -33, 9, -37, -3, -28,
22, -37, -12, 19, 0, -18, -2, 14,
1, 4, 8, -9, -2, 43, -17, -2,
-66, -31, 56, -40, -87, -36, -2, -4,
-42, -45, -1, 31, -43, -15, 27, 63,
-11, 32, -10, -33, 27, -19, 4, 15,
-26, -34, 29, -4, -39, -65, 14, -20,
-21, -17, -36, 13, 59, 47, -38, -33,
13, -37, -8, -37, -7, -6, -76, -31,
-12, -46, 7, 24, -21, -30, -14, 9,
15, -12, -13, 47, -27, -25, -1, -39,
0, 20, -9, 6, 7, 4, 3, 7,
39, 50, 22, -7, 14, -20, 1, 70,
-28, 29, -41, 10, -16, -5, -28, -2,
-37, 32, -18, 17, 62, -11, -20, -50,
36, 21, -62, -12, -56, 52, 50, 17,
3, 48, 44, -41, -25, 3, 16, -3,
0, 33, -6, 15, 27, 34, -25, 22,
9, 17, -11, 36, 16, -2, 12, 21,
-52, 45, -2, -10, 46, 21, -18, 67,
-28, -13, 30, 37, 42, 16, -9, 11,
75, 7, -64, -40, -10, 29, 57, -23,
5, 53, -77, 3, -17, -5, 47, -55,
-35, -36, -13, 52, -53, -71, 52, -111,
-23, -26, -28, 29, -43, 55, -19, 43,
-19, 54, -12, -33, -44, -39, -19, -10,
-31, -10, 21, 38, -57, -20, 2, -25,
8, -6, 50, 12, 15, 25, -25, 15,
-30, -6, 9, 25, 37, 19, -4, 31,
-22, 2, 4, 2, 36, 7, 3, -34,
-80, 36, -10, -2, -5, 31, -36, 49,
-70, 20, -36, 21, 24, 25, -46, -51,
36, -58, -48, -40, -10, 55, 71, 47,
10, -1, 1, 2, -46, -68, 16, 13,
0, -74, -29, 73, -52, -18, -11, 7,
-44, -82, -32, -70, -28, -1, -39, -68,
-6, -41, 12, -22, -16, 40, -11, -25,
51, -9, 21, 4, 4, -34, 7, -78,
16, 6, -38, -30, -2, -44, 32, 0,
22, 64, 5, -72, -2, -14, -10, -16,
-8, -25, 12, 102, -58, 37, -10, -23,
15, 49, 7, -7, 2, -20, -32, 45,
-6, 48, 28, 30, 33, -1, 22, -6,
30, 65, -17, 29, 74, 37, -26, -10,
15, -24, 19, -66, 22, -10, -31, -1,
-18, -9, 11, 37, -4, 45, 5, 41,
17, 1, 1, 24, -58, 41, 5, -51,
14, 8, 43, 16, -10, -1, 45, 32,
-64, 3, -33, -25, -3, -27, -68, 12,
23, -11, -13, -37, -40, 4, -21, -12,
32, -23, -19, 76, 41, -23, -24, -44,
-65, -1, -15, 1, 71, 63, 5, 20,
-3, 21, -23, 31, -32, 18, -2, 27,
31, 46, -5, -39, -5, -35, 18, -18,
-40, -10, 3, 12, 2, -2, -22, 40,
5, -6, 60, 36, 3, 29, -27, 10,
25, -54, 5, 26, 39, 35, -24, -37,
30, -91, 28, -4, -21, -27, -39, -6,
5, 12, -128, 38, -16, 29, -95, -29,
82, -2, 35, 2, 12, 8, -22, 10,
80, -47, 2, -25, -73, -79, 16, -30,
-32, -66, 48, 21, -45, -11, -47, 14,
-27, -17, -7, 15, -44, -14, -44, -26,
-32, 26, -23, 17, -7, -28, 26, -6,
28, 6, -26, 2, 13, -14, -23, -14,
19, 46, 16, 2, -33, -21, 28, -17,
-42, 44, -37, 1, -39, 28, 84, -46,
15, 10, 13, -44, 72, -26, 26, 32,
-28, -12, -83, 2, 10, -30, -44, -10,
-28, 53, 45, 65, 0, -25, 57, 36,
-33, 6, 29, 44, -53, 11, 19, -2,
-27, 35, 32, 49, 4, 23, 38, 36,
24, 10, 51, -39, 4, -7, 26, 37,
-35, 11, -47, -18, 28, 16, -35, 42,
17, -21, -41, 28, 14, -12, 11, -45,
7, -43, -15, 18, -5, 38, -40, -50,
-30, -21, 9, -98, 13, 12, 23, 75,
-56, -7, -3, -4, -1, -34, 12, -49,
11, 26, -18, -28, -17, 33, 13, -14,
40, 24, -72, -37, 10, 17, -6, 22,
16, 16, -6, -12, -30, -14, 10, 40,
-23, 12, 15, -3, -15, 13, -56, -4,
-30, 1, -3, -17, 27, 50, -5, 64,
-36, -19, 7, 29, 22, 25, 9, -16,
-58, -69, -40, -61, -71, -14, 42, 93,
26, 11, -6, -58, -11, 70, -52, 19,
9, -30, -33, 11, -37, -47, -21, -22,
-40, 10, 47, 4, -23, 17, 48, 41,
-48, 14, 10, 15, 34, -23, -2, -47,
23, -32, -13, -10, -26, -26, -4, 16,
38, -14, 0, -12, -7, -7, 20, 44,
-1, -32, -27, -16, 4, -6, -18, 14,
5, 4, -29, 28, 7, -7, 15, -11,
-20, -45, -36, 16, 84, 34, -59, -30,
22, 126, 8, 68, 79, -17, 21, -68,
37, 5, 15, 63, 49, 127, -90, 85,
43, 7, 16, 9, 6, -45, -57, -43,
57, 11, -23, -11, -29, 60, -26, 0,
7, 42, -24, 10, 23, -25, 8, -7,
-40, 19, -17, 35, 4, 27, -39, -91,
27, -36, 34, 2, 16, -24, 25, 7,
-21, 5, 17, 10, -22, -30, 9, -17,
-61, -26, 33, 21, 58, -51, -14, 69,
-38, 20, 7, 80, -4, -65, -6, -27,
53, -12, 47, -1, -15, 1, 60, 102,
-79, -4, 12, 9, 22, 37, -8, -4,
37, 2, -3, -15, -16, -11, -5, 19,
-6, -43, 20, -25, -18, 10, -27, 0,
-28, -27, -11, 10, -18, -2, -4, -16,
26, 14, -6, 7, -6, 1, 53, -2,
-29, 23, 9, -30, -6, -4, -6, 56,
70, 0, -33, -20, -17, -9, -24, 46,
-5, -105, 47, -46, -51, 20, 20, -53,
-81, -1, -7, 75, -5, -21, -65, 12,
-52, 22, -50, -12, 49, 54, 76, -81,
10, 45, -41, -59, 18, -19, 25, 14,
-31, -53, -5, 12, 31, 84, -23, 2,
7, 2, 10, -32, 39, -2, -12, 1,
-9, 0, -10, -11, 9, 15, -8, -2,
2, -1, 10, 14, -5, -40, 19, -7,
-7, 26, -4, 2, 1, -27, 35, 32,
21, -31, 26, 43, -9, 4, -32, 40,
-62, -52, 36, 22, 38, 22, 36, -96,
6, -10, -23, -49, 15, -33, -18, -3,
0, 41, 21, -19, 21, 23, -39, -23,
-6, 6, 47, 56, 4, 74, 0, -98,
29, -47, -14, -36, 21, -22, 22, 16,
13, 12, 16, -5, 13, 17, -13, -15,
1, -34, -26, 26, 12, 32, 27, 13,
-67, 27, 2, 8, 10, 18, 16, 20,
-17, -17, 57, -64, 5, 14, 19, 31,
-18, -44, -46, -16, 4, -25, 17, -126,
-24, 39, 4, 8, 55, -25, -34, 39,
-16, 3, 9, 71, 72, -31, -55, 6,
10, -25, 32, -85, -21, 18, -8, 15,
12, -27, -7, 1, -21, -2, -5, 48,
-16, 18, 1, -22, -26, 16, 14, -31,
27, -6, -15, -21, 4, -14, 18, -36
};
static const opus_int8 layer1_recur_weights[1728] = {
20, 67, -99, 12, 41, -25, 49, -44,
35, 81, 110, 47, 34, -66, -14, 14,
-60, 34, 29, -73, 10, 41, 35, 89,
7, -35, 22, 7, 27, -20, -6, 56,
26, 66, 6, 33, -55, 53, 1, -21,
14, 17, 68, 55, 59, 0, 18, -9,
5, -41, 6, -5, -114, -12, 29, 42,
-23, 10, 81, -27, 20, -53, -30, -62,
40, 95, 25, -4, 3, 18, -8, -15,
-29, -82, 2, -57, -3, -61, -29, -29,
49, 2, -55, 5, -69, -99, -49, -51,
6, -25, 12, 89, 44, -33, 5, 41,
1, 23, -37, -37, -28, -48, 3, 4,
-41, -30, -57, -35, -39, -1, -13, -56,
-5, 50, 49, 41, -4, -4, 33, -22,
-1, 33, 34, 18, 40, -42, 12, 1,
-6, -2, 18, 17, 39, 44, 11, 65,
-60, -45, 10, 91, 21, 9, -62, -11,
8, 69, 37, 24, -30, 21, 26, -27,
1, -28, 24, 66, -8, 6, -71, 34,
24, 44, 58, -78, -19, 57, 17, -60,
1, 12, -3, -1, -40, 22, 11, -5,
25, 12, 1, 72, 79, 7, -50, 23,
18, 13, 21, -11, -20, 5, 77, -94,
24, 15, 57, -51, 3, 36, 53, -1,
4, 14, 30, -31, 22, 40, 32, -11,
-34, -36, -59, 58, 25, 21, -54, -23,
40, 46, 18, 0, 12, 54, -96, -99,
-59, 5, 119, -38, 50, 55, 12, -16,
67, 0, 34, 35, 39, 35, -1, 69,
24, 27, -30, -35, -4, -70, 2, -44,
-7, -6, 19, -9, 60, 44, -21, -10,
37, 43, -16, -3, 30, -15, -65, 31,
-55, 18, -98, 76, 64, 25, 24, -18,
-7, -68, -10, 38, 27, -60, 36, 33,
16, 30, 34, -39, -37, 31, 12, 53,
-54, 14, -26, -49, -128, -13, -5, -22,
-11, -85, 55, -8, -51, -11, -33, -10,
-31, -76, -41, 23, 44, -40, -54, -127,
-101, 19, -23, -15, 15, 27, 58, -60,
8, 14, -33, 1, 48, -9, -11, -123,
3, 53, 23, 4, -28, 22, 2, -29,
-67, 36, 12, 7, 55, -21, 88, 20,
-1, -21, -17, 3, 41, 32, -10, -14,
-5, -57, 67, 57, 21, 23, -2, -27,
-73, -24, 120, 21, 18, -35, 42, -7,
3, -45, -25, 76, -34, 50, 11, -54,
-91, 3, -113, -20, -5, 47, 15, -47,
17, 27, -3, -26, -7, 10, 7, 74,
-40, 64, -7, -5, -24, -49, -24, -3,
-10, 27, -17, -8, -3, 14, -27, 33,
13, 39, 28, -7, -38, 29, 16, 44,
19, 55, -3, 9, -13, -57, 43, 43,
31, 0, -93, -17, 19, -56, 4, -12,
-25, 37, -85, -13, -118, 33, -17, 56,
71, -80, -4, 6, -11, -18, 47, -52,
25, 9, 48, -107, 1, 21, 20, -3,
10, -16, -4, 24, 17, 31, -61, -18,
-50, 24, -10, 12, 71, 26, 11, -3,
4, 1, 0, -7, -40, 18, 38, -34,
38, 17, 8, -34, 2, 21, 123, -32,
-26, 43, 14, -34, -1, -9, 37, -16,
6, -17, -62, 68, 22, 17, 11, -75,
33, -80, 62, -9, -75, 76, 36, -41,
-8, -40, -11, -71, 40, -39, 62, -49,
-81, 16, -9, -52, 52, 61, 17, -103,
-27, -10, -8, -54, -57, 21, 23, -16,
-52, 36, 18, 10, -5, 8, 15, -29,
5, -19, -37, 8, -53, 6, 19, -37,
38, -17, 48, 10, 0, 81, 46, 70,
-29, 101, 11, 44, -44, -3, 24, 11,
3, 14, -9, 11, 14, -45, 13, 46,
-3, -57, 68, 44, 63, 98, 25, -28,
-23, 15, 32, -10, 53, -6, -2, -9,
-6, 16, -107, -11, -11, -28, 59, 57,
-22, 38, 42, 83, 27, 5, 29, -30,
12, -21, -13, 31, 38, -21, 58, -10,
-10, -15, -2, -5, 11, 12, -73, -28,
-38, 22, 2, -25, 73, -52, -12, -55,
32, -63, 21, 51, 33, 52, -26, 55,
-26, -26, 57, -32, -4, -52, -61, 21,
-33, -91, -51, 69, -90, -53, -38, -44,
12, -76, -20, 77, -45, -7, 86, 43,
-109, -33, -105, -40, -121, -10, 0, -72,
45, -51, -75, -49, -38, -1, -62, 18,
-1, 30, -44, -14, -10, -67, 40, -10,
-34, 46, -64, -32, 29, -13, 33, 3,
-32, -5, 28, -27, -25, 93, 24, 68,
-40, 57, 23, -3, -21, -58, 17, -39,
-17, -22, -89, 11, 18, -46, 27, 24,
46, 127, 61, 87, 31, 127, -36, 47,
-23, 47, 127, -24, 110, 122, 30, 100,
0, 96, -12, 6, 50, 44, -13, 73,
4, 55, -11, -15, 49, 42, -6, 20,
-35, 58, 18, 38, 42, 72, 19, -21,
11, 9, -37, 7, 29, 31, 16, -17,
13, -50, 19, 5, -23, 51, -16, -5,
4, -24, 76, 10, -53, -28, -7, -65,
74, 40, -16, -29, 32, -16, -49, -35,
-3, 59, -96, -50, -43, -43, -61, -15,
-8, -36, -34, -33, -14, 11, -3, -39,
4, -114, -123, -11, -49, -21, 14, -56,
1, 43, -63, 26, 40, 18, -10, -26,
-14, -15, -35, -35, -11, 32, -44, -67,
2, 22, 7, 3, -9, -30, -51, -28,
28, 6, -22, 16, 34, -25, -52, -54,
-8, -6, 5, 8, 20, -16, -17, -44,
27, 3, 31, -5, -48, -1, -3, 116,
11, 71, -31, -47, 109, 50, -22, -12,
-57, 32, 66, 8, -25, -93, -54, -10,
19, -76, -34, 97, 48, -36, -18, -30,
-39, -26, -12, 28, 14, 12, -12, -31,
38, 2, 10, 4, -40, 20, 16, -61,
2, 64, 39, 5, 15, 33, 40, -61,
-49, 93, -10, 33, 28, -11, -27, -18,
39, -62, -6, -6, 62, 11, -8, 38,
-67, 12, 27, 39, -27, 123, -18, -6,
-65, 83, -64, 20, 19, -11, 33, 24,
17, 56, 78, 7, -15, 54, -101, -9,
115, -96, 50, 51, 35, 34, 27, 37,
-40, -11, 8, -36, 42, -45, 2, -23,
0, 67, -8, -9, -13, 50, -14, -27,
4, 0, -8, -14, 30, -9, 29, 15,
9, -38, 37, -8, 50, -46, 54, 41,
-11, -8, -11, -26, 39, 45, 14, -26,
-17, -27, 69, 38, 39, 98, 66, 0,
42, 123, -101, -19, -83, 117, -32, 56,
10, 12, -88, 79, -53, 56, 63, 95,
-62, 9, 36, -13, -79, -16, 37, -46,
35, -34, 14, 17, -54, 5, 21, -7,
7, 63, 56, 15, 27, -76, -25, 4,
-26, -63, 28, -67, -52, 43, -47, -70,
40, -12, 40, -66, -37, 0, 35, 37,
-53, 4, -17, -51, 11, 21, 14, -34,
-4, 24, -42, 29, 22, 7, 28, 12,
37, 39, -39, -19, 65, -60, -50, -2,
1, 82, 39, 19, -23, -43, -22, -67,
-35, -34, 32, 102, 81, 127, 36, 67,
-45, 1, -67, -52, -4, 35, 20, 28,
71, 86, -35, -9, -83, -34, 12, 9,
-23, 2, 14, 28, -23, 7, -25, 45,
7, 17, -37, 0, -19, 31, 26, 40,
-27, -16, 17, 5, -21, 23, 24, 96,
-55, 52, -19, -14, -6, 1, 50, -34,
86, -53, 38, 2, -52, -36, -13, 60,
-85, -120, 32, 7, -12, 22, 70, -7,
-94, 38, -76, -31, -20, 15, -28, 7,
6, 40, 53, 88, 3, 38, 18, -8,
-22, -23, 51, 37, -9, 13, -32, 25,
-21, 27, 31, 20, 18, -9, -13, 1,
21, -24, -13, 39, 15, -11, -29, -36,
18, 15, 8, 27, 21, -94, -1, -22,
49, 66, -1, 6, -3, -40, -18, 6,
28, 12, 33, -59, 62, 60, -48, 90,
-1, 108, 9, 18, -2, 27, 77, -65,
82, -48, -38, -19, -11, 127, 50, 66,
18, -13, -22, 60, -38, 40, -14, -26,
-13, 38, 67, 57, 30, 33, 26, 36,
38, -17, 27, -28, 20, 12, -64, 18,
5, -33, -27, 13, -26, 32, 35, -5,
-48, -14, 92, 43, -47, -14, 40, 11,
51, 66, 22, -63, -16, -61, 4, -28,
27, 20, -33, -30, -21, -29, -53, 31,
-40, 24, 43, -4, -19, 21, 67, 20,
100, -16, -93, 78, -6, -18, -52, -37,
-9, 66, -31, -8, 26, 18, 4, 24,
-22, 17, -2, -13, 27, 0, 8, -18,
-25, 5, -21, -24, -7, 18, -93, 21,
7, 2, -75, 69, 50, -5, -15, -17,
60, -42, 55, 1, -4, 3, 10, 46,
16, -13, 45, -7, -10, -44, -108, 49,
2, -15, -64, -12, -72, 32, -38, -45,
10, -54, 13, -13, -27, -36, -64, 58,
-62, -101, 88, -86, -71, -39, -9, -128,
32, 15, -4, 54, -16, -39, -26, -36,
46, 48, -64, -10, 19, 30, -13, 34,
-8, 50, 60, -22, -6, -11, -30, 5,
50, 32, 56, 0, 25, 6, 68, 11,
-29, 45, -9, -12, 4, 1, 18, -49,
0, -38, -19, 90, 29, 35, 51, 8,
-48, 96, -1, -12, -9, -32, -63, -65,
-7, 38, 89, 28, -85, -28, -23, -25,
-128, 56, 79, -36, 99, -6, -37, 7,
-13, -69, -46, -29, 25, 64, -21, 17,
1, 42, -66, 1, 80, 26, -32, 21,
15, 15, 6, 6, -10, 15, 127, 5,
38, 27, 87, -57, -25, 11, 72, -21,
-5, 11, -13, -66, 78, 36, -3, 41,
-21, 8, -33, 23, 73, 28, 57, -25,
-5, 4, -22, -47, 15, 4, -57, -72,
33, 1, 18, 2, 53, -71, -99, -21,
-3, -111, 108, 71, -14, 82, 25, 61,
-48, 5, 9, -51, -20, -25, -3, 14,
-33, 14, -3, -34, 22, 12, -19, -38,
-16, 2, 21, 16, 26, -31, 75, 44,
-31, 16, 26, 66, 17, -9, -22, -22,
22, -44, 22, 27, 2, 58, -14, 10,
-73, -42, 55, -25, -61, 72, -1, 30,
-58, -25, 63, 26, -48, -40, 26, -30,
60, 8, -17, -1, -18, -20, 43, -20,
-4, -28, 127, -106, 29, 70, 64, -27,
39, -33, -5, -88, -40, -52, 26, 44,
-17, 23, 2, -49, 22, -9, -8, 86,
49, -43, -60, 1, 10, 45, 36, -53,
-4, 33, 38, 48, -72, 1, 19, 21,
-65, 4, -5, -62, 27, -25, 17, -6,
6, -45, -39, -46, 4, 26, 127, -9,
18, -33, -18, -3, 33, 2, -5, 15,
-26, -22, -117, -63, -17, -59, 61, -74,
7, -47, -58, -128, -67, 15, -16, -128,
12, 2, 20, 9, -48, -40, 43, 3,
-40, -16, -38, -6, -22, -28, -16, -59,
-22, 6, -5, 11, -12, -66, -40, 27,
-62, -44, -19, 38, -3, 39, -8, 40,
-24, 13, 21, 50, -60, -22, 53, -29,
-6, 1, 22, -59, 0, 17, -39, 115
};
static const opus_int8 layer1_bias[72] = {
-42, 20, 16, 0, 105, 60, 1, -97,
24, 60, 18, 13, 62, 25, 127, 34,
79, 55, 118, 127, 95, 31, -4, 87,
21, 12, 2, -14, 18, 23, 8, 17,
-1, -8, 5, 4, 24, 37, 21, 13,
36, 13, 17, 18, 37, 30, 33, 1,
8, -16, -11, -5, -31, -3, -5, 0,
6, 3, 58, -7, -1, -16, 5, -13,
16, 10, -2, -14, 11, -4, 3, -11
};
static const opus_int8 layer2_weights[48] = {
-113, -88, 31, -128, -126, -61, 85, -35,
118, -128, -61, 127, -128, -17, -128, 127,
104, -9, -128, 33, 45, 127, 5, 83,
84, -128, -85, -128, -45, 48, -53, -128,
46, 127, -17, 125, 117, -41, -117, -91,
-127, -68, -1, -89, -80, 32, 106, 7
};
static const opus_int8 layer2_bias[2] = {
14, 117
};
const DenseLayer layer0 = {
layer0_bias,
layer0_weights,
25, 32, 0
};
const GRULayer layer1 = {
layer1_bias,
layer1_weights,
layer1_recur_weights,
32, 24
};
const DenseLayer layer2 = {
layer2_bias,
layer2_weights,
24, 2, 1
};

View file

@ -0,0 +1,278 @@
/********************************************************************
* *
* THIS FILE IS PART OF THE Ogg CONTAINER SOURCE CODE. *
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
* *
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2018 *
* by the Xiph.Org Foundation http://www.xiph.org/ *
* *
********************************************************************/
#include "os_types.h"
static const ogg_uint32_t crc_lookup[8][256]={
{0x00000000,0x04c11db7,0x09823b6e,0x0d4326d9,0x130476dc,0x17c56b6b,0x1a864db2,0x1e475005,
0x2608edb8,0x22c9f00f,0x2f8ad6d6,0x2b4bcb61,0x350c9b64,0x31cd86d3,0x3c8ea00a,0x384fbdbd,
0x4c11db70,0x48d0c6c7,0x4593e01e,0x4152fda9,0x5f15adac,0x5bd4b01b,0x569796c2,0x52568b75,
0x6a1936c8,0x6ed82b7f,0x639b0da6,0x675a1011,0x791d4014,0x7ddc5da3,0x709f7b7a,0x745e66cd,
0x9823b6e0,0x9ce2ab57,0x91a18d8e,0x95609039,0x8b27c03c,0x8fe6dd8b,0x82a5fb52,0x8664e6e5,
0xbe2b5b58,0xbaea46ef,0xb7a96036,0xb3687d81,0xad2f2d84,0xa9ee3033,0xa4ad16ea,0xa06c0b5d,
0xd4326d90,0xd0f37027,0xddb056fe,0xd9714b49,0xc7361b4c,0xc3f706fb,0xceb42022,0xca753d95,
0xf23a8028,0xf6fb9d9f,0xfbb8bb46,0xff79a6f1,0xe13ef6f4,0xe5ffeb43,0xe8bccd9a,0xec7dd02d,
0x34867077,0x30476dc0,0x3d044b19,0x39c556ae,0x278206ab,0x23431b1c,0x2e003dc5,0x2ac12072,
0x128e9dcf,0x164f8078,0x1b0ca6a1,0x1fcdbb16,0x018aeb13,0x054bf6a4,0x0808d07d,0x0cc9cdca,
0x7897ab07,0x7c56b6b0,0x71159069,0x75d48dde,0x6b93dddb,0x6f52c06c,0x6211e6b5,0x66d0fb02,
0x5e9f46bf,0x5a5e5b08,0x571d7dd1,0x53dc6066,0x4d9b3063,0x495a2dd4,0x44190b0d,0x40d816ba,
0xaca5c697,0xa864db20,0xa527fdf9,0xa1e6e04e,0xbfa1b04b,0xbb60adfc,0xb6238b25,0xb2e29692,
0x8aad2b2f,0x8e6c3698,0x832f1041,0x87ee0df6,0x99a95df3,0x9d684044,0x902b669d,0x94ea7b2a,
0xe0b41de7,0xe4750050,0xe9362689,0xedf73b3e,0xf3b06b3b,0xf771768c,0xfa325055,0xfef34de2,
0xc6bcf05f,0xc27dede8,0xcf3ecb31,0xcbffd686,0xd5b88683,0xd1799b34,0xdc3abded,0xd8fba05a,
0x690ce0ee,0x6dcdfd59,0x608edb80,0x644fc637,0x7a089632,0x7ec98b85,0x738aad5c,0x774bb0eb,
0x4f040d56,0x4bc510e1,0x46863638,0x42472b8f,0x5c007b8a,0x58c1663d,0x558240e4,0x51435d53,
0x251d3b9e,0x21dc2629,0x2c9f00f0,0x285e1d47,0x36194d42,0x32d850f5,0x3f9b762c,0x3b5a6b9b,
0x0315d626,0x07d4cb91,0x0a97ed48,0x0e56f0ff,0x1011a0fa,0x14d0bd4d,0x19939b94,0x1d528623,
0xf12f560e,0xf5ee4bb9,0xf8ad6d60,0xfc6c70d7,0xe22b20d2,0xe6ea3d65,0xeba91bbc,0xef68060b,
0xd727bbb6,0xd3e6a601,0xdea580d8,0xda649d6f,0xc423cd6a,0xc0e2d0dd,0xcda1f604,0xc960ebb3,
0xbd3e8d7e,0xb9ff90c9,0xb4bcb610,0xb07daba7,0xae3afba2,0xaafbe615,0xa7b8c0cc,0xa379dd7b,
0x9b3660c6,0x9ff77d71,0x92b45ba8,0x9675461f,0x8832161a,0x8cf30bad,0x81b02d74,0x857130c3,
0x5d8a9099,0x594b8d2e,0x5408abf7,0x50c9b640,0x4e8ee645,0x4a4ffbf2,0x470cdd2b,0x43cdc09c,
0x7b827d21,0x7f436096,0x7200464f,0x76c15bf8,0x68860bfd,0x6c47164a,0x61043093,0x65c52d24,
0x119b4be9,0x155a565e,0x18197087,0x1cd86d30,0x029f3d35,0x065e2082,0x0b1d065b,0x0fdc1bec,
0x3793a651,0x3352bbe6,0x3e119d3f,0x3ad08088,0x2497d08d,0x2056cd3a,0x2d15ebe3,0x29d4f654,
0xc5a92679,0xc1683bce,0xcc2b1d17,0xc8ea00a0,0xd6ad50a5,0xd26c4d12,0xdf2f6bcb,0xdbee767c,
0xe3a1cbc1,0xe760d676,0xea23f0af,0xeee2ed18,0xf0a5bd1d,0xf464a0aa,0xf9278673,0xfde69bc4,
0x89b8fd09,0x8d79e0be,0x803ac667,0x84fbdbd0,0x9abc8bd5,0x9e7d9662,0x933eb0bb,0x97ffad0c,
0xafb010b1,0xab710d06,0xa6322bdf,0xa2f33668,0xbcb4666d,0xb8757bda,0xb5365d03,0xb1f740b4},
{0x00000000,0xd219c1dc,0xa0f29e0f,0x72eb5fd3,0x452421a9,0x973de075,0xe5d6bfa6,0x37cf7e7a,
0x8a484352,0x5851828e,0x2abadd5d,0xf8a31c81,0xcf6c62fb,0x1d75a327,0x6f9efcf4,0xbd873d28,
0x10519b13,0xc2485acf,0xb0a3051c,0x62bac4c0,0x5575baba,0x876c7b66,0xf58724b5,0x279ee569,
0x9a19d841,0x4800199d,0x3aeb464e,0xe8f28792,0xdf3df9e8,0x0d243834,0x7fcf67e7,0xadd6a63b,
0x20a33626,0xf2baf7fa,0x8051a829,0x524869f5,0x6587178f,0xb79ed653,0xc5758980,0x176c485c,
0xaaeb7574,0x78f2b4a8,0x0a19eb7b,0xd8002aa7,0xefcf54dd,0x3dd69501,0x4f3dcad2,0x9d240b0e,
0x30f2ad35,0xe2eb6ce9,0x9000333a,0x4219f2e6,0x75d68c9c,0xa7cf4d40,0xd5241293,0x073dd34f,
0xbabaee67,0x68a32fbb,0x1a487068,0xc851b1b4,0xff9ecfce,0x2d870e12,0x5f6c51c1,0x8d75901d,
0x41466c4c,0x935fad90,0xe1b4f243,0x33ad339f,0x04624de5,0xd67b8c39,0xa490d3ea,0x76891236,
0xcb0e2f1e,0x1917eec2,0x6bfcb111,0xb9e570cd,0x8e2a0eb7,0x5c33cf6b,0x2ed890b8,0xfcc15164,
0x5117f75f,0x830e3683,0xf1e56950,0x23fca88c,0x1433d6f6,0xc62a172a,0xb4c148f9,0x66d88925,
0xdb5fb40d,0x094675d1,0x7bad2a02,0xa9b4ebde,0x9e7b95a4,0x4c625478,0x3e890bab,0xec90ca77,
0x61e55a6a,0xb3fc9bb6,0xc117c465,0x130e05b9,0x24c17bc3,0xf6d8ba1f,0x8433e5cc,0x562a2410,
0xebad1938,0x39b4d8e4,0x4b5f8737,0x994646eb,0xae893891,0x7c90f94d,0x0e7ba69e,0xdc626742,
0x71b4c179,0xa3ad00a5,0xd1465f76,0x035f9eaa,0x3490e0d0,0xe689210c,0x94627edf,0x467bbf03,
0xfbfc822b,0x29e543f7,0x5b0e1c24,0x8917ddf8,0xbed8a382,0x6cc1625e,0x1e2a3d8d,0xcc33fc51,
0x828cd898,0x50951944,0x227e4697,0xf067874b,0xc7a8f931,0x15b138ed,0x675a673e,0xb543a6e2,
0x08c49bca,0xdadd5a16,0xa83605c5,0x7a2fc419,0x4de0ba63,0x9ff97bbf,0xed12246c,0x3f0be5b0,
0x92dd438b,0x40c48257,0x322fdd84,0xe0361c58,0xd7f96222,0x05e0a3fe,0x770bfc2d,0xa5123df1,
0x189500d9,0xca8cc105,0xb8679ed6,0x6a7e5f0a,0x5db12170,0x8fa8e0ac,0xfd43bf7f,0x2f5a7ea3,
0xa22feebe,0x70362f62,0x02dd70b1,0xd0c4b16d,0xe70bcf17,0x35120ecb,0x47f95118,0x95e090c4,
0x2867adec,0xfa7e6c30,0x889533e3,0x5a8cf23f,0x6d438c45,0xbf5a4d99,0xcdb1124a,0x1fa8d396,
0xb27e75ad,0x6067b471,0x128ceba2,0xc0952a7e,0xf75a5404,0x254395d8,0x57a8ca0b,0x85b10bd7,
0x383636ff,0xea2ff723,0x98c4a8f0,0x4add692c,0x7d121756,0xaf0bd68a,0xdde08959,0x0ff94885,
0xc3cab4d4,0x11d37508,0x63382adb,0xb121eb07,0x86ee957d,0x54f754a1,0x261c0b72,0xf405caae,
0x4982f786,0x9b9b365a,0xe9706989,0x3b69a855,0x0ca6d62f,0xdebf17f3,0xac544820,0x7e4d89fc,
0xd39b2fc7,0x0182ee1b,0x7369b1c8,0xa1707014,0x96bf0e6e,0x44a6cfb2,0x364d9061,0xe45451bd,
0x59d36c95,0x8bcaad49,0xf921f29a,0x2b383346,0x1cf74d3c,0xceee8ce0,0xbc05d333,0x6e1c12ef,
0xe36982f2,0x3170432e,0x439b1cfd,0x9182dd21,0xa64da35b,0x74546287,0x06bf3d54,0xd4a6fc88,
0x6921c1a0,0xbb38007c,0xc9d35faf,0x1bca9e73,0x2c05e009,0xfe1c21d5,0x8cf77e06,0x5eeebfda,
0xf33819e1,0x2121d83d,0x53ca87ee,0x81d34632,0xb61c3848,0x6405f994,0x16eea647,0xc4f7679b,
0x79705ab3,0xab699b6f,0xd982c4bc,0x0b9b0560,0x3c547b1a,0xee4dbac6,0x9ca6e515,0x4ebf24c9},
{0x00000000,0x01d8ac87,0x03b1590e,0x0269f589,0x0762b21c,0x06ba1e9b,0x04d3eb12,0x050b4795,
0x0ec56438,0x0f1dc8bf,0x0d743d36,0x0cac91b1,0x09a7d624,0x087f7aa3,0x0a168f2a,0x0bce23ad,
0x1d8ac870,0x1c5264f7,0x1e3b917e,0x1fe33df9,0x1ae87a6c,0x1b30d6eb,0x19592362,0x18818fe5,
0x134fac48,0x129700cf,0x10fef546,0x112659c1,0x142d1e54,0x15f5b2d3,0x179c475a,0x1644ebdd,
0x3b1590e0,0x3acd3c67,0x38a4c9ee,0x397c6569,0x3c7722fc,0x3daf8e7b,0x3fc67bf2,0x3e1ed775,
0x35d0f4d8,0x3408585f,0x3661add6,0x37b90151,0x32b246c4,0x336aea43,0x31031fca,0x30dbb34d,
0x269f5890,0x2747f417,0x252e019e,0x24f6ad19,0x21fdea8c,0x2025460b,0x224cb382,0x23941f05,
0x285a3ca8,0x2982902f,0x2beb65a6,0x2a33c921,0x2f388eb4,0x2ee02233,0x2c89d7ba,0x2d517b3d,
0x762b21c0,0x77f38d47,0x759a78ce,0x7442d449,0x714993dc,0x70913f5b,0x72f8cad2,0x73206655,
0x78ee45f8,0x7936e97f,0x7b5f1cf6,0x7a87b071,0x7f8cf7e4,0x7e545b63,0x7c3daeea,0x7de5026d,
0x6ba1e9b0,0x6a794537,0x6810b0be,0x69c81c39,0x6cc35bac,0x6d1bf72b,0x6f7202a2,0x6eaaae25,
0x65648d88,0x64bc210f,0x66d5d486,0x670d7801,0x62063f94,0x63de9313,0x61b7669a,0x606fca1d,
0x4d3eb120,0x4ce61da7,0x4e8fe82e,0x4f5744a9,0x4a5c033c,0x4b84afbb,0x49ed5a32,0x4835f6b5,
0x43fbd518,0x4223799f,0x404a8c16,0x41922091,0x44996704,0x4541cb83,0x47283e0a,0x46f0928d,
0x50b47950,0x516cd5d7,0x5305205e,0x52dd8cd9,0x57d6cb4c,0x560e67cb,0x54679242,0x55bf3ec5,
0x5e711d68,0x5fa9b1ef,0x5dc04466,0x5c18e8e1,0x5913af74,0x58cb03f3,0x5aa2f67a,0x5b7a5afd,
0xec564380,0xed8eef07,0xefe71a8e,0xee3fb609,0xeb34f19c,0xeaec5d1b,0xe885a892,0xe95d0415,
0xe29327b8,0xe34b8b3f,0xe1227eb6,0xe0fad231,0xe5f195a4,0xe4293923,0xe640ccaa,0xe798602d,
0xf1dc8bf0,0xf0042777,0xf26dd2fe,0xf3b57e79,0xf6be39ec,0xf766956b,0xf50f60e2,0xf4d7cc65,
0xff19efc8,0xfec1434f,0xfca8b6c6,0xfd701a41,0xf87b5dd4,0xf9a3f153,0xfbca04da,0xfa12a85d,
0xd743d360,0xd69b7fe7,0xd4f28a6e,0xd52a26e9,0xd021617c,0xd1f9cdfb,0xd3903872,0xd24894f5,
0xd986b758,0xd85e1bdf,0xda37ee56,0xdbef42d1,0xdee40544,0xdf3ca9c3,0xdd555c4a,0xdc8df0cd,
0xcac91b10,0xcb11b797,0xc978421e,0xc8a0ee99,0xcdaba90c,0xcc73058b,0xce1af002,0xcfc25c85,
0xc40c7f28,0xc5d4d3af,0xc7bd2626,0xc6658aa1,0xc36ecd34,0xc2b661b3,0xc0df943a,0xc10738bd,
0x9a7d6240,0x9ba5cec7,0x99cc3b4e,0x981497c9,0x9d1fd05c,0x9cc77cdb,0x9eae8952,0x9f7625d5,
0x94b80678,0x9560aaff,0x97095f76,0x96d1f3f1,0x93dab464,0x920218e3,0x906bed6a,0x91b341ed,
0x87f7aa30,0x862f06b7,0x8446f33e,0x859e5fb9,0x8095182c,0x814db4ab,0x83244122,0x82fceda5,
0x8932ce08,0x88ea628f,0x8a839706,0x8b5b3b81,0x8e507c14,0x8f88d093,0x8de1251a,0x8c39899d,
0xa168f2a0,0xa0b05e27,0xa2d9abae,0xa3010729,0xa60a40bc,0xa7d2ec3b,0xa5bb19b2,0xa463b535,
0xafad9698,0xae753a1f,0xac1ccf96,0xadc46311,0xa8cf2484,0xa9178803,0xab7e7d8a,0xaaa6d10d,
0xbce23ad0,0xbd3a9657,0xbf5363de,0xbe8bcf59,0xbb8088cc,0xba58244b,0xb831d1c2,0xb9e97d45,
0xb2275ee8,0xb3fff26f,0xb19607e6,0xb04eab61,0xb545ecf4,0xb49d4073,0xb6f4b5fa,0xb72c197d},
{0x00000000,0xdc6d9ab7,0xbc1a28d9,0x6077b26e,0x7cf54c05,0xa098d6b2,0xc0ef64dc,0x1c82fe6b,
0xf9ea980a,0x258702bd,0x45f0b0d3,0x999d2a64,0x851fd40f,0x59724eb8,0x3905fcd6,0xe5686661,
0xf7142da3,0x2b79b714,0x4b0e057a,0x97639fcd,0x8be161a6,0x578cfb11,0x37fb497f,0xeb96d3c8,
0x0efeb5a9,0xd2932f1e,0xb2e49d70,0x6e8907c7,0x720bf9ac,0xae66631b,0xce11d175,0x127c4bc2,
0xeae946f1,0x3684dc46,0x56f36e28,0x8a9ef49f,0x961c0af4,0x4a719043,0x2a06222d,0xf66bb89a,
0x1303defb,0xcf6e444c,0xaf19f622,0x73746c95,0x6ff692fe,0xb39b0849,0xd3ecba27,0x0f812090,
0x1dfd6b52,0xc190f1e5,0xa1e7438b,0x7d8ad93c,0x61082757,0xbd65bde0,0xdd120f8e,0x017f9539,
0xe417f358,0x387a69ef,0x580ddb81,0x84604136,0x98e2bf5d,0x448f25ea,0x24f89784,0xf8950d33,
0xd1139055,0x0d7e0ae2,0x6d09b88c,0xb164223b,0xade6dc50,0x718b46e7,0x11fcf489,0xcd916e3e,
0x28f9085f,0xf49492e8,0x94e32086,0x488eba31,0x540c445a,0x8861deed,0xe8166c83,0x347bf634,
0x2607bdf6,0xfa6a2741,0x9a1d952f,0x46700f98,0x5af2f1f3,0x869f6b44,0xe6e8d92a,0x3a85439d,
0xdfed25fc,0x0380bf4b,0x63f70d25,0xbf9a9792,0xa31869f9,0x7f75f34e,0x1f024120,0xc36fdb97,
0x3bfad6a4,0xe7974c13,0x87e0fe7d,0x5b8d64ca,0x470f9aa1,0x9b620016,0xfb15b278,0x277828cf,
0xc2104eae,0x1e7dd419,0x7e0a6677,0xa267fcc0,0xbee502ab,0x6288981c,0x02ff2a72,0xde92b0c5,
0xcceefb07,0x108361b0,0x70f4d3de,0xac994969,0xb01bb702,0x6c762db5,0x0c019fdb,0xd06c056c,
0x3504630d,0xe969f9ba,0x891e4bd4,0x5573d163,0x49f12f08,0x959cb5bf,0xf5eb07d1,0x29869d66,
0xa6e63d1d,0x7a8ba7aa,0x1afc15c4,0xc6918f73,0xda137118,0x067eebaf,0x660959c1,0xba64c376,
0x5f0ca517,0x83613fa0,0xe3168dce,0x3f7b1779,0x23f9e912,0xff9473a5,0x9fe3c1cb,0x438e5b7c,
0x51f210be,0x8d9f8a09,0xede83867,0x3185a2d0,0x2d075cbb,0xf16ac60c,0x911d7462,0x4d70eed5,
0xa81888b4,0x74751203,0x1402a06d,0xc86f3ada,0xd4edc4b1,0x08805e06,0x68f7ec68,0xb49a76df,
0x4c0f7bec,0x9062e15b,0xf0155335,0x2c78c982,0x30fa37e9,0xec97ad5e,0x8ce01f30,0x508d8587,
0xb5e5e3e6,0x69887951,0x09ffcb3f,0xd5925188,0xc910afe3,0x157d3554,0x750a873a,0xa9671d8d,
0xbb1b564f,0x6776ccf8,0x07017e96,0xdb6ce421,0xc7ee1a4a,0x1b8380fd,0x7bf43293,0xa799a824,
0x42f1ce45,0x9e9c54f2,0xfeebe69c,0x22867c2b,0x3e048240,0xe26918f7,0x821eaa99,0x5e73302e,
0x77f5ad48,0xab9837ff,0xcbef8591,0x17821f26,0x0b00e14d,0xd76d7bfa,0xb71ac994,0x6b775323,
0x8e1f3542,0x5272aff5,0x32051d9b,0xee68872c,0xf2ea7947,0x2e87e3f0,0x4ef0519e,0x929dcb29,
0x80e180eb,0x5c8c1a5c,0x3cfba832,0xe0963285,0xfc14ccee,0x20795659,0x400ee437,0x9c637e80,
0x790b18e1,0xa5668256,0xc5113038,0x197caa8f,0x05fe54e4,0xd993ce53,0xb9e47c3d,0x6589e68a,
0x9d1cebb9,0x4171710e,0x2106c360,0xfd6b59d7,0xe1e9a7bc,0x3d843d0b,0x5df38f65,0x819e15d2,
0x64f673b3,0xb89be904,0xd8ec5b6a,0x0481c1dd,0x18033fb6,0xc46ea501,0xa419176f,0x78748dd8,
0x6a08c61a,0xb6655cad,0xd612eec3,0x0a7f7474,0x16fd8a1f,0xca9010a8,0xaae7a2c6,0x768a3871,
0x93e25e10,0x4f8fc4a7,0x2ff876c9,0xf395ec7e,0xef171215,0x337a88a2,0x530d3acc,0x8f60a07b},
{0x00000000,0x490d678d,0x921acf1a,0xdb17a897,0x20f48383,0x69f9e40e,0xb2ee4c99,0xfbe32b14,
0x41e90706,0x08e4608b,0xd3f3c81c,0x9afeaf91,0x611d8485,0x2810e308,0xf3074b9f,0xba0a2c12,
0x83d20e0c,0xcadf6981,0x11c8c116,0x58c5a69b,0xa3268d8f,0xea2bea02,0x313c4295,0x78312518,
0xc23b090a,0x8b366e87,0x5021c610,0x192ca19d,0xe2cf8a89,0xabc2ed04,0x70d54593,0x39d8221e,
0x036501af,0x4a686622,0x917fceb5,0xd872a938,0x2391822c,0x6a9ce5a1,0xb18b4d36,0xf8862abb,
0x428c06a9,0x0b816124,0xd096c9b3,0x999bae3e,0x6278852a,0x2b75e2a7,0xf0624a30,0xb96f2dbd,
0x80b70fa3,0xc9ba682e,0x12adc0b9,0x5ba0a734,0xa0438c20,0xe94eebad,0x3259433a,0x7b5424b7,
0xc15e08a5,0x88536f28,0x5344c7bf,0x1a49a032,0xe1aa8b26,0xa8a7ecab,0x73b0443c,0x3abd23b1,
0x06ca035e,0x4fc764d3,0x94d0cc44,0xddddabc9,0x263e80dd,0x6f33e750,0xb4244fc7,0xfd29284a,
0x47230458,0x0e2e63d5,0xd539cb42,0x9c34accf,0x67d787db,0x2edae056,0xf5cd48c1,0xbcc02f4c,
0x85180d52,0xcc156adf,0x1702c248,0x5e0fa5c5,0xa5ec8ed1,0xece1e95c,0x37f641cb,0x7efb2646,
0xc4f10a54,0x8dfc6dd9,0x56ebc54e,0x1fe6a2c3,0xe40589d7,0xad08ee5a,0x761f46cd,0x3f122140,
0x05af02f1,0x4ca2657c,0x97b5cdeb,0xdeb8aa66,0x255b8172,0x6c56e6ff,0xb7414e68,0xfe4c29e5,
0x444605f7,0x0d4b627a,0xd65ccaed,0x9f51ad60,0x64b28674,0x2dbfe1f9,0xf6a8496e,0xbfa52ee3,
0x867d0cfd,0xcf706b70,0x1467c3e7,0x5d6aa46a,0xa6898f7e,0xef84e8f3,0x34934064,0x7d9e27e9,
0xc7940bfb,0x8e996c76,0x558ec4e1,0x1c83a36c,0xe7608878,0xae6deff5,0x757a4762,0x3c7720ef,
0x0d9406bc,0x44996131,0x9f8ec9a6,0xd683ae2b,0x2d60853f,0x646de2b2,0xbf7a4a25,0xf6772da8,
0x4c7d01ba,0x05706637,0xde67cea0,0x976aa92d,0x6c898239,0x2584e5b4,0xfe934d23,0xb79e2aae,
0x8e4608b0,0xc74b6f3d,0x1c5cc7aa,0x5551a027,0xaeb28b33,0xe7bfecbe,0x3ca84429,0x75a523a4,
0xcfaf0fb6,0x86a2683b,0x5db5c0ac,0x14b8a721,0xef5b8c35,0xa656ebb8,0x7d41432f,0x344c24a2,
0x0ef10713,0x47fc609e,0x9cebc809,0xd5e6af84,0x2e058490,0x6708e31d,0xbc1f4b8a,0xf5122c07,
0x4f180015,0x06156798,0xdd02cf0f,0x940fa882,0x6fec8396,0x26e1e41b,0xfdf64c8c,0xb4fb2b01,
0x8d23091f,0xc42e6e92,0x1f39c605,0x5634a188,0xadd78a9c,0xe4daed11,0x3fcd4586,0x76c0220b,
0xccca0e19,0x85c76994,0x5ed0c103,0x17dda68e,0xec3e8d9a,0xa533ea17,0x7e244280,0x3729250d,
0x0b5e05e2,0x4253626f,0x9944caf8,0xd049ad75,0x2baa8661,0x62a7e1ec,0xb9b0497b,0xf0bd2ef6,
0x4ab702e4,0x03ba6569,0xd8adcdfe,0x91a0aa73,0x6a438167,0x234ee6ea,0xf8594e7d,0xb15429f0,
0x888c0bee,0xc1816c63,0x1a96c4f4,0x539ba379,0xa878886d,0xe175efe0,0x3a624777,0x736f20fa,
0xc9650ce8,0x80686b65,0x5b7fc3f2,0x1272a47f,0xe9918f6b,0xa09ce8e6,0x7b8b4071,0x328627fc,
0x083b044d,0x413663c0,0x9a21cb57,0xd32cacda,0x28cf87ce,0x61c2e043,0xbad548d4,0xf3d82f59,
0x49d2034b,0x00df64c6,0xdbc8cc51,0x92c5abdc,0x692680c8,0x202be745,0xfb3c4fd2,0xb231285f,
0x8be90a41,0xc2e46dcc,0x19f3c55b,0x50fea2d6,0xab1d89c2,0xe210ee4f,0x390746d8,0x700a2155,
0xca000d47,0x830d6aca,0x581ac25d,0x1117a5d0,0xeaf48ec4,0xa3f9e949,0x78ee41de,0x31e32653},
{0x00000000,0x1b280d78,0x36501af0,0x2d781788,0x6ca035e0,0x77883898,0x5af02f10,0x41d82268,
0xd9406bc0,0xc26866b8,0xef107130,0xf4387c48,0xb5e05e20,0xaec85358,0x83b044d0,0x989849a8,
0xb641ca37,0xad69c74f,0x8011d0c7,0x9b39ddbf,0xdae1ffd7,0xc1c9f2af,0xecb1e527,0xf799e85f,
0x6f01a1f7,0x7429ac8f,0x5951bb07,0x4279b67f,0x03a19417,0x1889996f,0x35f18ee7,0x2ed9839f,
0x684289d9,0x736a84a1,0x5e129329,0x453a9e51,0x04e2bc39,0x1fcab141,0x32b2a6c9,0x299aabb1,
0xb102e219,0xaa2aef61,0x8752f8e9,0x9c7af591,0xdda2d7f9,0xc68ada81,0xebf2cd09,0xf0dac071,
0xde0343ee,0xc52b4e96,0xe853591e,0xf37b5466,0xb2a3760e,0xa98b7b76,0x84f36cfe,0x9fdb6186,
0x0743282e,0x1c6b2556,0x311332de,0x2a3b3fa6,0x6be31dce,0x70cb10b6,0x5db3073e,0x469b0a46,
0xd08513b2,0xcbad1eca,0xe6d50942,0xfdfd043a,0xbc252652,0xa70d2b2a,0x8a753ca2,0x915d31da,
0x09c57872,0x12ed750a,0x3f956282,0x24bd6ffa,0x65654d92,0x7e4d40ea,0x53355762,0x481d5a1a,
0x66c4d985,0x7decd4fd,0x5094c375,0x4bbcce0d,0x0a64ec65,0x114ce11d,0x3c34f695,0x271cfbed,
0xbf84b245,0xa4acbf3d,0x89d4a8b5,0x92fca5cd,0xd32487a5,0xc80c8add,0xe5749d55,0xfe5c902d,
0xb8c79a6b,0xa3ef9713,0x8e97809b,0x95bf8de3,0xd467af8b,0xcf4fa2f3,0xe237b57b,0xf91fb803,
0x6187f1ab,0x7aaffcd3,0x57d7eb5b,0x4cffe623,0x0d27c44b,0x160fc933,0x3b77debb,0x205fd3c3,
0x0e86505c,0x15ae5d24,0x38d64aac,0x23fe47d4,0x622665bc,0x790e68c4,0x54767f4c,0x4f5e7234,
0xd7c63b9c,0xccee36e4,0xe196216c,0xfabe2c14,0xbb660e7c,0xa04e0304,0x8d36148c,0x961e19f4,
0xa5cb3ad3,0xbee337ab,0x939b2023,0x88b32d5b,0xc96b0f33,0xd243024b,0xff3b15c3,0xe41318bb,
0x7c8b5113,0x67a35c6b,0x4adb4be3,0x51f3469b,0x102b64f3,0x0b03698b,0x267b7e03,0x3d53737b,
0x138af0e4,0x08a2fd9c,0x25daea14,0x3ef2e76c,0x7f2ac504,0x6402c87c,0x497adff4,0x5252d28c,
0xcaca9b24,0xd1e2965c,0xfc9a81d4,0xe7b28cac,0xa66aaec4,0xbd42a3bc,0x903ab434,0x8b12b94c,
0xcd89b30a,0xd6a1be72,0xfbd9a9fa,0xe0f1a482,0xa12986ea,0xba018b92,0x97799c1a,0x8c519162,
0x14c9d8ca,0x0fe1d5b2,0x2299c23a,0x39b1cf42,0x7869ed2a,0x6341e052,0x4e39f7da,0x5511faa2,
0x7bc8793d,0x60e07445,0x4d9863cd,0x56b06eb5,0x17684cdd,0x0c4041a5,0x2138562d,0x3a105b55,
0xa28812fd,0xb9a01f85,0x94d8080d,0x8ff00575,0xce28271d,0xd5002a65,0xf8783ded,0xe3503095,
0x754e2961,0x6e662419,0x431e3391,0x58363ee9,0x19ee1c81,0x02c611f9,0x2fbe0671,0x34960b09,
0xac0e42a1,0xb7264fd9,0x9a5e5851,0x81765529,0xc0ae7741,0xdb867a39,0xf6fe6db1,0xedd660c9,
0xc30fe356,0xd827ee2e,0xf55ff9a6,0xee77f4de,0xafafd6b6,0xb487dbce,0x99ffcc46,0x82d7c13e,
0x1a4f8896,0x016785ee,0x2c1f9266,0x37379f1e,0x76efbd76,0x6dc7b00e,0x40bfa786,0x5b97aafe,
0x1d0ca0b8,0x0624adc0,0x2b5cba48,0x3074b730,0x71ac9558,0x6a849820,0x47fc8fa8,0x5cd482d0,
0xc44ccb78,0xdf64c600,0xf21cd188,0xe934dcf0,0xa8ecfe98,0xb3c4f3e0,0x9ebce468,0x8594e910,
0xab4d6a8f,0xb06567f7,0x9d1d707f,0x86357d07,0xc7ed5f6f,0xdcc55217,0xf1bd459f,0xea9548e7,
0x720d014f,0x69250c37,0x445d1bbf,0x5f7516c7,0x1ead34af,0x058539d7,0x28fd2e5f,0x33d52327},
{0x00000000,0x4f576811,0x9eaed022,0xd1f9b833,0x399cbdf3,0x76cbd5e2,0xa7326dd1,0xe86505c0,
0x73397be6,0x3c6e13f7,0xed97abc4,0xa2c0c3d5,0x4aa5c615,0x05f2ae04,0xd40b1637,0x9b5c7e26,
0xe672f7cc,0xa9259fdd,0x78dc27ee,0x378b4fff,0xdfee4a3f,0x90b9222e,0x41409a1d,0x0e17f20c,
0x954b8c2a,0xda1ce43b,0x0be55c08,0x44b23419,0xacd731d9,0xe38059c8,0x3279e1fb,0x7d2e89ea,
0xc824f22f,0x87739a3e,0x568a220d,0x19dd4a1c,0xf1b84fdc,0xbeef27cd,0x6f169ffe,0x2041f7ef,
0xbb1d89c9,0xf44ae1d8,0x25b359eb,0x6ae431fa,0x8281343a,0xcdd65c2b,0x1c2fe418,0x53788c09,
0x2e5605e3,0x61016df2,0xb0f8d5c1,0xffafbdd0,0x17cab810,0x589dd001,0x89646832,0xc6330023,
0x5d6f7e05,0x12381614,0xc3c1ae27,0x8c96c636,0x64f3c3f6,0x2ba4abe7,0xfa5d13d4,0xb50a7bc5,
0x9488f9e9,0xdbdf91f8,0x0a2629cb,0x457141da,0xad14441a,0xe2432c0b,0x33ba9438,0x7cedfc29,
0xe7b1820f,0xa8e6ea1e,0x791f522d,0x36483a3c,0xde2d3ffc,0x917a57ed,0x4083efde,0x0fd487cf,
0x72fa0e25,0x3dad6634,0xec54de07,0xa303b616,0x4b66b3d6,0x0431dbc7,0xd5c863f4,0x9a9f0be5,
0x01c375c3,0x4e941dd2,0x9f6da5e1,0xd03acdf0,0x385fc830,0x7708a021,0xa6f11812,0xe9a67003,
0x5cac0bc6,0x13fb63d7,0xc202dbe4,0x8d55b3f5,0x6530b635,0x2a67de24,0xfb9e6617,0xb4c90e06,
0x2f957020,0x60c21831,0xb13ba002,0xfe6cc813,0x1609cdd3,0x595ea5c2,0x88a71df1,0xc7f075e0,
0xbadefc0a,0xf589941b,0x24702c28,0x6b274439,0x834241f9,0xcc1529e8,0x1dec91db,0x52bbf9ca,
0xc9e787ec,0x86b0effd,0x574957ce,0x181e3fdf,0xf07b3a1f,0xbf2c520e,0x6ed5ea3d,0x2182822c,
0x2dd0ee65,0x62878674,0xb37e3e47,0xfc295656,0x144c5396,0x5b1b3b87,0x8ae283b4,0xc5b5eba5,
0x5ee99583,0x11befd92,0xc04745a1,0x8f102db0,0x67752870,0x28224061,0xf9dbf852,0xb68c9043,
0xcba219a9,0x84f571b8,0x550cc98b,0x1a5ba19a,0xf23ea45a,0xbd69cc4b,0x6c907478,0x23c71c69,
0xb89b624f,0xf7cc0a5e,0x2635b26d,0x6962da7c,0x8107dfbc,0xce50b7ad,0x1fa90f9e,0x50fe678f,
0xe5f41c4a,0xaaa3745b,0x7b5acc68,0x340da479,0xdc68a1b9,0x933fc9a8,0x42c6719b,0x0d91198a,
0x96cd67ac,0xd99a0fbd,0x0863b78e,0x4734df9f,0xaf51da5f,0xe006b24e,0x31ff0a7d,0x7ea8626c,
0x0386eb86,0x4cd18397,0x9d283ba4,0xd27f53b5,0x3a1a5675,0x754d3e64,0xa4b48657,0xebe3ee46,
0x70bf9060,0x3fe8f871,0xee114042,0xa1462853,0x49232d93,0x06744582,0xd78dfdb1,0x98da95a0,
0xb958178c,0xf60f7f9d,0x27f6c7ae,0x68a1afbf,0x80c4aa7f,0xcf93c26e,0x1e6a7a5d,0x513d124c,
0xca616c6a,0x8536047b,0x54cfbc48,0x1b98d459,0xf3fdd199,0xbcaab988,0x6d5301bb,0x220469aa,
0x5f2ae040,0x107d8851,0xc1843062,0x8ed35873,0x66b65db3,0x29e135a2,0xf8188d91,0xb74fe580,
0x2c139ba6,0x6344f3b7,0xb2bd4b84,0xfdea2395,0x158f2655,0x5ad84e44,0x8b21f677,0xc4769e66,
0x717ce5a3,0x3e2b8db2,0xefd23581,0xa0855d90,0x48e05850,0x07b73041,0xd64e8872,0x9919e063,
0x02459e45,0x4d12f654,0x9ceb4e67,0xd3bc2676,0x3bd923b6,0x748e4ba7,0xa577f394,0xea209b85,
0x970e126f,0xd8597a7e,0x09a0c24d,0x46f7aa5c,0xae92af9c,0xe1c5c78d,0x303c7fbe,0x7f6b17af,
0xe4376989,0xab600198,0x7a99b9ab,0x35ced1ba,0xddabd47a,0x92fcbc6b,0x43050458,0x0c526c49},
{0x00000000,0x5ba1dcca,0xb743b994,0xece2655e,0x6a466e9f,0x31e7b255,0xdd05d70b,0x86a40bc1,
0xd48cdd3e,0x8f2d01f4,0x63cf64aa,0x386eb860,0xbecab3a1,0xe56b6f6b,0x09890a35,0x5228d6ff,
0xadd8a7cb,0xf6797b01,0x1a9b1e5f,0x413ac295,0xc79ec954,0x9c3f159e,0x70dd70c0,0x2b7cac0a,
0x79547af5,0x22f5a63f,0xce17c361,0x95b61fab,0x1312146a,0x48b3c8a0,0xa451adfe,0xfff07134,
0x5f705221,0x04d18eeb,0xe833ebb5,0xb392377f,0x35363cbe,0x6e97e074,0x8275852a,0xd9d459e0,
0x8bfc8f1f,0xd05d53d5,0x3cbf368b,0x671eea41,0xe1bae180,0xba1b3d4a,0x56f95814,0x0d5884de,
0xf2a8f5ea,0xa9092920,0x45eb4c7e,0x1e4a90b4,0x98ee9b75,0xc34f47bf,0x2fad22e1,0x740cfe2b,
0x262428d4,0x7d85f41e,0x91679140,0xcac64d8a,0x4c62464b,0x17c39a81,0xfb21ffdf,0xa0802315,
0xbee0a442,0xe5417888,0x09a31dd6,0x5202c11c,0xd4a6cadd,0x8f071617,0x63e57349,0x3844af83,
0x6a6c797c,0x31cda5b6,0xdd2fc0e8,0x868e1c22,0x002a17e3,0x5b8bcb29,0xb769ae77,0xecc872bd,
0x13380389,0x4899df43,0xa47bba1d,0xffda66d7,0x797e6d16,0x22dfb1dc,0xce3dd482,0x959c0848,
0xc7b4deb7,0x9c15027d,0x70f76723,0x2b56bbe9,0xadf2b028,0xf6536ce2,0x1ab109bc,0x4110d576,
0xe190f663,0xba312aa9,0x56d34ff7,0x0d72933d,0x8bd698fc,0xd0774436,0x3c952168,0x6734fda2,
0x351c2b5d,0x6ebdf797,0x825f92c9,0xd9fe4e03,0x5f5a45c2,0x04fb9908,0xe819fc56,0xb3b8209c,
0x4c4851a8,0x17e98d62,0xfb0be83c,0xa0aa34f6,0x260e3f37,0x7dafe3fd,0x914d86a3,0xcaec5a69,
0x98c48c96,0xc365505c,0x2f873502,0x7426e9c8,0xf282e209,0xa9233ec3,0x45c15b9d,0x1e608757,
0x79005533,0x22a189f9,0xce43eca7,0x95e2306d,0x13463bac,0x48e7e766,0xa4058238,0xffa45ef2,
0xad8c880d,0xf62d54c7,0x1acf3199,0x416eed53,0xc7cae692,0x9c6b3a58,0x70895f06,0x2b2883cc,
0xd4d8f2f8,0x8f792e32,0x639b4b6c,0x383a97a6,0xbe9e9c67,0xe53f40ad,0x09dd25f3,0x527cf939,
0x00542fc6,0x5bf5f30c,0xb7179652,0xecb64a98,0x6a124159,0x31b39d93,0xdd51f8cd,0x86f02407,
0x26700712,0x7dd1dbd8,0x9133be86,0xca92624c,0x4c36698d,0x1797b547,0xfb75d019,0xa0d40cd3,
0xf2fcda2c,0xa95d06e6,0x45bf63b8,0x1e1ebf72,0x98bab4b3,0xc31b6879,0x2ff90d27,0x7458d1ed,
0x8ba8a0d9,0xd0097c13,0x3ceb194d,0x674ac587,0xe1eece46,0xba4f128c,0x56ad77d2,0x0d0cab18,
0x5f247de7,0x0485a12d,0xe867c473,0xb3c618b9,0x35621378,0x6ec3cfb2,0x8221aaec,0xd9807626,
0xc7e0f171,0x9c412dbb,0x70a348e5,0x2b02942f,0xada69fee,0xf6074324,0x1ae5267a,0x4144fab0,
0x136c2c4f,0x48cdf085,0xa42f95db,0xff8e4911,0x792a42d0,0x228b9e1a,0xce69fb44,0x95c8278e,
0x6a3856ba,0x31998a70,0xdd7bef2e,0x86da33e4,0x007e3825,0x5bdfe4ef,0xb73d81b1,0xec9c5d7b,
0xbeb48b84,0xe515574e,0x09f73210,0x5256eeda,0xd4f2e51b,0x8f5339d1,0x63b15c8f,0x38108045,
0x9890a350,0xc3317f9a,0x2fd31ac4,0x7472c60e,0xf2d6cdcf,0xa9771105,0x4595745b,0x1e34a891,
0x4c1c7e6e,0x17bda2a4,0xfb5fc7fa,0xa0fe1b30,0x265a10f1,0x7dfbcc3b,0x9119a965,0xcab875af,
0x3548049b,0x6ee9d851,0x820bbd0f,0xd9aa61c5,0x5f0e6a04,0x04afb6ce,0xe84dd390,0xb3ec0f5a,
0xe1c4d9a5,0xba65056f,0x56876031,0x0d26bcfb,0x8b82b73a,0xd0236bf0,0x3cc10eae,0x6760d264}};

File diff suppressed because it is too large Load diff

View file

@ -11,7 +11,6 @@
******************************************************************** ********************************************************************
function: toplevel libogg include function: toplevel libogg include
last mod: $Id: ogg.h 18044 2011-08-01 17:55:20Z gmaxwell $
********************************************************************/ ********************************************************************/
#ifndef _OGG_H #ifndef _OGG_H

View file

@ -104,6 +104,10 @@ OPUS_EXPORT void opus_pcm_soft_clip(float *_x, int N, int C, float *declip_mem)
/* Compute a such that maxval + a*maxval^2 = 1 */ /* Compute a such that maxval + a*maxval^2 = 1 */
a=(maxval-1)/(maxval*maxval); a=(maxval-1)/(maxval*maxval);
/* Slightly boost "a" by 2^-22. This is just enough to ensure -ffast-math
does not cause output values larger than +/-1, but small enough not
to matter even for 24-bit output. */
a += a*2.4e-7f;
if (x[i*C]>0) if (x[i*C]>0)
a = -a; a = -a;
/* Apply soft clipping */ /* Apply soft clipping */
@ -133,7 +137,6 @@ OPUS_EXPORT void opus_pcm_soft_clip(float *_x, int N, int C, float *declip_mem)
} }
#endif #endif
#if 0
int encode_size(int size, unsigned char *data) int encode_size(int size, unsigned char *data)
{ {
if (size < 252) if (size < 252)
@ -146,7 +149,6 @@ int encode_size(int size, unsigned char *data)
return 2; return 2;
} }
} }
#endif
static int parse_size(const unsigned char *data, opus_int32 len, opus_int16 *size) static int parse_size(const unsigned char *data, opus_int32 len, opus_int16 *size)
{ {
@ -203,8 +205,10 @@ int opus_packet_parse_impl(const unsigned char *data, opus_int32 len,
opus_int32 pad = 0; opus_int32 pad = 0;
const unsigned char *data0 = data; const unsigned char *data0 = data;
if (size==NULL) if (size==NULL || len<0)
return OPUS_BAD_ARG; return OPUS_BAD_ARG;
if (len==0)
return OPUS_INVALID_PACKET;
framesize = opus_packet_get_samples_per_frame(data, 48000); framesize = opus_packet_get_samples_per_frame(data, 48000);
@ -248,7 +252,7 @@ int opus_packet_parse_impl(const unsigned char *data, opus_int32 len,
/* Number of frames encoded in bits 0 to 5 */ /* Number of frames encoded in bits 0 to 5 */
ch = *data++; ch = *data++;
count = ch&0x3F; count = ch&0x3F;
if (count <= 0 || framesize*count > 5760) if (count <= 0 || framesize*(opus_int32)count > 5760)
return OPUS_INVALID_PACKET; return OPUS_INVALID_PACKET;
len--; len--;
/* Padding flag is bit 6 */ /* Padding flag is bit 6 */
@ -342,7 +346,6 @@ int opus_packet_parse_impl(const unsigned char *data, opus_int32 len,
return count; return count;
} }
#if 0
int opus_packet_parse(const unsigned char *data, opus_int32 len, int opus_packet_parse(const unsigned char *data, opus_int32 len,
unsigned char *out_toc, const unsigned char *frames[48], unsigned char *out_toc, const unsigned char *frames[48],
opus_int16 size[48], int *payload_offset) opus_int16 size[48], int *payload_offset)
@ -350,5 +353,4 @@ int opus_packet_parse(const unsigned char *data, opus_int32 len,
return opus_packet_parse_impl(data, len, 0, out_toc, return opus_packet_parse_impl(data, len, 0, out_toc,
frames, size, payload_offset, NULL); frames, size, payload_offset, NULL);
} }
#endif

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