pure sdk for main

This commit is contained in:
divadiow
2025-08-27 09:51:58 +01:00
parent f0d033f1c9
commit 0571416e7c
3283 changed files with 1577720 additions and 1 deletions
+983
View File
@@ -0,0 +1,983 @@
/* 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 "opus_config.h"
#endif
#define ANALYSIS_C
#ifdef MLP_TRAINING
#include <stdio.h>
#endif
#include "../celt/mathops.h"
#include "../celt/kiss_fft.h"
#include "../celt/celt.h"
#include "../celt/modes.h"
#include "../celt/arch.h"
#include "../celt/quant_bands.h"
#include "analysis.h"
#include "mlp.h"
#include "../celt/stack_alloc.h"
#include "../celt/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;
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;
/* 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);
if (!info_out->valid)
return;
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); */
}
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
#ifdef FIXED_POINT
static int is_digital_silence32(const opus_val32* pcm, int frame_size, int channels, int lsb_depth)
{
int silence = 0;
opus_val32 sample_max = 0;
#ifdef MLP_TRAINING
return 0;
#endif
sample_max = celt_maxabs32(pcm, frame_size*channels);
silence = (sample_max == 0);
(void)lsb_depth;
return silence;
}
#else
#define is_digital_silence32(pcm, frame_size, channels, lsb_depth) is_digital_silence(pcm, frame_size, channels, lsb_depth)
#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;
int is_silence;
SAVE_STACK;
if (!tonal->initialized)
{
tonal->mem_fill = 240;
tonal->initialized = 1;
}
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];
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;
is_silence = is_digital_silence32(tonal->inmem, ANALYSIS_BUF_SIZE, 1, lsb_depth);
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;
if (is_silence)
{
/* On silence, copy the previous analysis. */
int prev_pos = tonal->write_pos-2;
if (prev_pos < 0)
prev_pos += DETECT_SIZE;
OPUS_COPY(info, &tonal->info[prev_pos], 1);
RESTORE_STACK;
return;
}
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-5f + (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;
analysis_compute_dense(&layer0, layer_out, features);
analysis_compute_gru(&layer1, tonal->rnn_state, layer_out);
analysis_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;
}
tonality_get_info(analysis, analysis_info, frame_size);
}
#endif /* DISABLE_FLOAT_API */
+103
View File
@@ -0,0 +1,103 @@
/* 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/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;
int initialized;
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
+315
View File
@@ -0,0 +1,315 @@
/* Copyright (c) 2022 Amazon */
/*
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifdef HAVE_CONFIG_H
#include "opus_config.h"
#endif
#include "../include/opus_types.h"
#include "../include/opus_defines.h"
#include "../celt/arch.h"
#include "../celt/os_support.h"
#include "opus_private.h"
/* Given an extension payload, advance data to the next extension and return the
length of the remaining extensions. */
opus_int32 skip_extension(const unsigned char **data, opus_int32 len, opus_int32 *header_size)
{
int id, L;
if (len==0)
return 0;
id = **data>>1;
L = **data&1;
if (id == 0 && L == 1)
{
*header_size = 1;
if (len < 1)
return -1;
(*data)++;
len--;
return len;
} else if (id > 0 && id < 32)
{
if (len < 1+L)
return -1;
*data += 1+L;
len -= 1+L;
*header_size = 1;
return len;
} else {
if (L==0)
{
*data += len;
*header_size = 1;
return 0;
} else {
opus_int32 bytes=0;
*header_size = 1;
do {
(*data)++;
len--;
if (len == 0)
return -1;
bytes += **data;
(*header_size)++;
} while (**data == 255);
(*data)++;
len--;
if (bytes <= len)
{
len -= bytes;
*data += bytes;
} else {
return -1;
}
return len;
}
}
}
/* Count the number of extensions, excluding real padding and separators. */
opus_int32 opus_packet_extensions_count(const unsigned char *data, opus_int32 len)
{
opus_int32 curr_len;
opus_int32 count=0;
const unsigned char *curr_data = data;
celt_assert(len >= 0);
celt_assert(data != NULL || len == 0);
curr_len = len;
while (curr_len > 0)
{
int id;
opus_int32 header_size;
id = *curr_data>>1;
curr_len = skip_extension(&curr_data, curr_len, &header_size);
if (curr_len < 0)
return OPUS_INVALID_PACKET;
if (id > 1)
count++;
}
return count;
}
/* Extract extensions from Opus padding (excluding real padding and separators) */
opus_int32 opus_packet_extensions_parse(const unsigned char *data, opus_int32 len, opus_extension_data *extensions, opus_int32 *nb_extensions)
{
const unsigned char *curr_data;
opus_int32 curr_len;
int curr_frame=0;
opus_int32 count=0;
celt_assert(len >= 0);
celt_assert(data != NULL || len == 0);
celt_assert(nb_extensions != NULL);
celt_assert(extensions != NULL || *nb_extensions == 0);
curr_data = data;
curr_len = len;
while (curr_len > 0)
{
int id;
opus_int32 header_size;
opus_extension_data curr_ext;
id = *curr_data>>1;
if (id > 1)
{
curr_ext.id = id;
curr_ext.frame = curr_frame;
curr_ext.data = curr_data;
} else if (id == 1)
{
int L = *curr_data&1;
if (L==0)
curr_frame++;
else {
if (curr_len >= 2)
curr_frame += curr_data[1];
/* Else we're at the end and it doesn't matter. */
}
if (curr_frame >= 48)
{
*nb_extensions = count;
return OPUS_INVALID_PACKET;
}
}
curr_len = skip_extension(&curr_data, curr_len, &header_size);
/* printf("curr_len = %d, header_size = %d\n", curr_len, header_size); */
if (curr_len < 0)
{
*nb_extensions = count;
return OPUS_INVALID_PACKET;
}
celt_assert(curr_data - data == len - curr_len);
if (id > 1)
{
if (count == *nb_extensions)
{
return OPUS_BUFFER_TOO_SMALL;
}
curr_ext.len = curr_data - curr_ext.data - header_size;
curr_ext.data += header_size;
extensions[count++] = curr_ext;
}
}
celt_assert(curr_len == 0);
*nb_extensions = count;
return OPUS_OK;
}
opus_int32 opus_packet_extensions_generate(unsigned char *data, opus_int32 len, const opus_extension_data *extensions, opus_int32 nb_extensions, int pad)
{
int max_frame=0;
opus_int32 i;
int frame;
int curr_frame = 0;
opus_int32 pos = 0;
opus_int32 written = 0;
celt_assert(len >= 0);
for (i=0;i<nb_extensions;i++)
{
max_frame = IMAX(max_frame, extensions[i].frame);
if (extensions[i].id < 2 || extensions[i].id > 127)
return OPUS_BAD_ARG;
}
if (max_frame >= 48) return OPUS_BAD_ARG;
for (frame=0;frame<=max_frame;frame++)
{
for (i=0;i<nb_extensions;i++)
{
if (extensions[i].frame == frame)
{
/* Insert separator when needed. */
if (frame != curr_frame) {
int diff = frame - curr_frame;
if (len-pos < 2)
return OPUS_BUFFER_TOO_SMALL;
if (diff == 1) {
if (data) data[pos] = 0x02;
pos++;
} else {
if (data) data[pos] = 0x03;
pos++;
if (data) data[pos] = diff;
pos++;
}
curr_frame = frame;
}
if (extensions[i].id < 32)
{
if (extensions[i].len < 0 || extensions[i].len > 1)
return OPUS_BAD_ARG;
if (len-pos < extensions[i].len+1)
return OPUS_BUFFER_TOO_SMALL;
if (data) data[pos] = (extensions[i].id<<1) + extensions[i].len;
pos++;
if (extensions[i].len > 0) {
if (data) data[pos] = extensions[i].data[0];
pos++;
}
} else {
int last;
opus_int32 length_bytes;
if (extensions[i].len < 0)
return OPUS_BAD_ARG;
last = (written == nb_extensions - 1);
length_bytes = 1 + extensions[i].len/255;
if (last)
length_bytes = 0;
if (len-pos < 1 + length_bytes + extensions[i].len)
return OPUS_BUFFER_TOO_SMALL;
if (data) data[pos] = (extensions[i].id<<1) + !last;
pos++;
if (!last)
{
opus_int32 j;
for (j=0;j<extensions[i].len/255;j++) {
if (data) data[pos] = 255;
pos++;
}
if (data) data[pos] = extensions[i].len % 255;
pos++;
}
if (data) OPUS_COPY(&data[pos], extensions[i].data, extensions[i].len);
pos += extensions[i].len;
}
written++;
}
}
}
/* If we need to pad, just prepend 0x01 bytes. Even better would be to fill the
end with zeros, but that requires checking that turning the last extesion into
an L=1 case still fits. */
if (pad && pos < len)
{
opus_int32 padding = len - pos;
if (data) {
OPUS_MOVE(data+padding, data, pos);
for (i=0;i<padding;i++)
data[i] = 0x01;
}
pos += padding;
}
return pos;
}
#if 0
#include <stdio.h>
int main()
{
opus_extension_data ext[] = {{2, 0, (const unsigned char *)"a", 1},
{32, 10, (const unsigned char *)"DRED", 4},
{33, 1, (const unsigned char *)"NOT DRED", 8},
{3, 4, (const unsigned char *)NULL, 0}
};
opus_extension_data ext2[10];
int i, len;
int nb_ext = 10;
unsigned char packet[10000];
len = opus_packet_extensions_generate(packet, 32, ext, 4, 1);
for (i=0;i<len;i++)
{
printf("%#04x ", packet[i]);
if (i%16 == 15)
printf("\n");
}
printf("\n");
printf("count = %d\n", opus_packet_extensions_count(packet, len));
opus_packet_extensions_parse(packet, len, ext2, &nb_ext);
for (i=0;i<nb_ext;i++)
{
int j;
printf("%d %d {", ext2[i].id, ext2[i].frame);
for (j=0;j<ext2[i].len;j++) printf("%#04x ", ext2[i].data[j]);
printf("} %d\n", ext2[i].len);
}
}
#endif
+132
View File
@@ -0,0 +1,132 @@
/* 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 "opus_config.h"
#endif
#include <math.h>
#include "../include/opus_types.h"
#include "../include/opus_defines.h"
#include "../celt/arch.h"
#include "mlp.h"
#define fmadd(a, b, c) ((a)*(b)+(c))
static OPUS_INLINE float tansig_approx(float x)
{
const float N0 = 952.52801514f;
const float N1 = 96.39235687f;
const float N2 = 0.60863042f;
const float D0 = 952.72399902f;
const float D1 = 413.36801147f;
const float D2 = 11.88600922f;
float X2, num, den;
X2 = x*x;
num = fmadd(fmadd(N2, X2, N1), X2, N0);
den = fmadd(fmadd(D2, X2, D1), X2, D0);
num = num*x/den;
return MAX32(-1.f, MIN32(1.f, num));
}
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 analysis_compute_dense(const AnalysisDenseLayer *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 analysis_compute_gru(const AnalysisGRULayer *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];
}
+60
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 "../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;
} AnalysisDenseLayer;
typedef struct {
const opus_int8 *bias;
const opus_int8 *input_weights;
const opus_int8 *recurrent_weights;
int nb_inputs;
int nb_neurons;
} AnalysisGRULayer;
extern const AnalysisDenseLayer layer0;
extern const AnalysisGRULayer layer1;
extern const AnalysisDenseLayer layer2;
void analysis_compute_dense(const AnalysisDenseLayer *layer, float *output, const float *input);
void analysis_compute_gru(const AnalysisGRULayer *gru, float *state, const float *input);
#endif /* MLP_H_ */
+672
View File
@@ -0,0 +1,672 @@
/*This file is automatically generated from a Keras model*/
#ifdef HAVE_CONFIG_H
#include "opus_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 AnalysisDenseLayer layer0 = {
layer0_bias,
layer0_weights,
25, 32, 0
};
const AnalysisGRULayer layer1 = {
layer1_bias,
layer1_weights,
layer1_recur_weights,
32, 24
};
const AnalysisDenseLayer layer2 = {
layer2_bias,
layer2_weights,
24, 2, 1
};
+362
View File
@@ -0,0 +1,362 @@
/* Copyright (c) 2011 Xiph.Org Foundation, Skype Limited
Written by Jean-Marc Valin and Koen Vos */
/*
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifdef HAVE_CONFIG_H
#include "opus_config.h"
#endif
#include "../include/opus.h"
#include "opus_private.h"
#ifndef DISABLE_FLOAT_API
OPUS_EXPORT void opus_pcm_soft_clip(float *_x, int N, int C, float *declip_mem)
{
int c;
int i;
float *x;
if (C<1 || N<1 || !_x || !declip_mem) return;
/* First thing: saturate everything to +/- 2 which is the highest level our
non-linearity can handle. At the point where the signal reaches +/-2,
the derivative will be zero anyway, so this doesn't introduce any
discontinuity in the derivative. */
for (i=0;i<N*C;i++)
_x[i] = MAX16(-2.f, MIN16(2.f, _x[i]));
for (c=0;c<C;c++)
{
float a;
float x0;
int curr;
x = _x+c;
a = declip_mem[c];
/* Continue applying the non-linearity from the previous frame to avoid
any discontinuity. */
for (i=0;i<N;i++)
{
if (x[i*C]*a>=0)
break;
x[i*C] = x[i*C]+a*x[i*C]*x[i*C];
}
curr=0;
x0 = x[0];
while(1)
{
int start, end;
float maxval;
int special=0;
int peak_pos;
for (i=curr;i<N;i++)
{
if (x[i*C]>1 || x[i*C]<-1)
break;
}
if (i==N)
{
a=0;
break;
}
peak_pos = i;
start=end=i;
maxval=ABS16(x[i*C]);
/* Look for first zero crossing before clipping */
while (start>0 && x[i*C]*x[(start-1)*C]>=0)
start--;
/* Look for first zero crossing after clipping */
while (end<N && x[i*C]*x[end*C]>=0)
{
/* Look for other peaks until the next zero-crossing. */
if (ABS16(x[end*C])>maxval)
{
maxval = ABS16(x[end*C]);
peak_pos = end;
}
end++;
}
/* Detect the special case where we clip before the first zero crossing */
special = (start==0 && x[i*C]*x[0]>=0);
/* Compute a such that maxval + a*maxval^2 = 1 */
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)
a = -a;
/* Apply soft clipping */
for (i=start;i<end;i++)
x[i*C] = x[i*C]+a*x[i*C]*x[i*C];
if (special && peak_pos>=2)
{
/* Add a linear ramp from the first sample to the signal peak.
This avoids a discontinuity at the beginning of the frame. */
float delta;
float offset = x0-x[0];
delta = offset / peak_pos;
for (i=curr;i<peak_pos;i++)
{
offset -= delta;
x[i*C] += offset;
x[i*C] = MAX16(-1.f, MIN16(1.f, x[i*C]));
}
}
curr = end;
if (curr==N)
break;
}
declip_mem[c] = a;
}
}
#endif
int encode_size(int size, unsigned char *data)
{
if (size < 252)
{
data[0] = size;
return 1;
} else {
data[0] = 252+(size&0x3);
data[1] = (size-(int)data[0])>>2;
return 2;
}
}
static int parse_size(const unsigned char *data, opus_int32 len, opus_int16 *size)
{
if (len<1)
{
*size = -1;
return -1;
} else if (data[0]<252)
{
*size = data[0];
return 1;
} else if (len<2)
{
*size = -1;
return -1;
} else {
*size = 4*data[1] + data[0];
return 2;
}
}
int opus_packet_get_samples_per_frame(const unsigned char *data,
opus_int32 Fs)
{
int audiosize;
if (data[0]&0x80)
{
audiosize = ((data[0]>>3)&0x3);
audiosize = (Fs<<audiosize)/400;
} else if ((data[0]&0x60) == 0x60)
{
audiosize = (data[0]&0x08) ? Fs/50 : Fs/100;
} else {
audiosize = ((data[0]>>3)&0x3);
if (audiosize == 3)
audiosize = Fs*60/1000;
else
audiosize = (Fs<<audiosize)/100;
}
return audiosize;
}
int opus_packet_parse_impl(const unsigned char *data, opus_int32 len,
int self_delimited, unsigned char *out_toc,
const unsigned char *frames[48], opus_int16 size[48],
int *payload_offset, opus_int32 *packet_offset,
const unsigned char **padding, opus_int32 *padding_len)
{
int i, bytes;
int count;
int cbr;
unsigned char ch, toc;
int framesize;
opus_int32 last_size;
opus_int32 pad = 0;
const unsigned char *data0 = data;
if (size==NULL || len<0)
return OPUS_BAD_ARG;
if (len==0)
return OPUS_INVALID_PACKET;
framesize = opus_packet_get_samples_per_frame(data, 48000);
cbr = 0;
toc = *data++;
len--;
last_size = len;
switch (toc&0x3)
{
/* One frame */
case 0:
count=1;
break;
/* Two CBR frames */
case 1:
count=2;
cbr = 1;
if (!self_delimited)
{
if (len&0x1)
return OPUS_INVALID_PACKET;
last_size = len/2;
/* If last_size doesn't fit in size[0], we'll catch it later */
size[0] = (opus_int16)last_size;
}
break;
/* Two VBR frames */
case 2:
count = 2;
bytes = parse_size(data, len, size);
len -= bytes;
if (size[0]<0 || size[0] > len)
return OPUS_INVALID_PACKET;
data += bytes;
last_size = len-size[0];
break;
/* Multiple CBR/VBR frames (from 0 to 120 ms) */
default: /*case 3:*/
if (len<1)
return OPUS_INVALID_PACKET;
/* Number of frames encoded in bits 0 to 5 */
ch = *data++;
count = ch&0x3F;
if (count <= 0 || framesize*(opus_int32)count > 5760)
return OPUS_INVALID_PACKET;
len--;
/* Padding flag is bit 6 */
if (ch&0x40)
{
int p;
do {
int tmp;
if (len<=0)
return OPUS_INVALID_PACKET;
p = *data++;
len--;
tmp = p==255 ? 254: p;
len -= tmp;
pad += tmp;
} while (p==255);
}
if (len<0)
return OPUS_INVALID_PACKET;
/* VBR flag is bit 7 */
cbr = !(ch&0x80);
if (!cbr)
{
/* VBR case */
last_size = len;
for (i=0;i<count-1;i++)
{
bytes = parse_size(data, len, size+i);
len -= bytes;
if (size[i]<0 || size[i] > len)
return OPUS_INVALID_PACKET;
data += bytes;
last_size -= bytes+size[i];
}
if (last_size<0)
return OPUS_INVALID_PACKET;
} else if (!self_delimited)
{
/* CBR case */
last_size = len/count;
if (last_size*count!=len)
return OPUS_INVALID_PACKET;
for (i=0;i<count-1;i++)
size[i] = (opus_int16)last_size;
}
break;
}
/* Self-delimited framing has an extra size for the last frame. */
if (self_delimited)
{
bytes = parse_size(data, len, size+count-1);
len -= bytes;
if (size[count-1]<0 || size[count-1] > len)
return OPUS_INVALID_PACKET;
data += bytes;
/* For CBR packets, apply the size to all the frames. */
if (cbr)
{
if (size[count-1]*count > len)
return OPUS_INVALID_PACKET;
for (i=0;i<count-1;i++)
size[i] = size[count-1];
} else if (bytes+size[count-1] > last_size)
return OPUS_INVALID_PACKET;
} else
{
/* Because it's not encoded explicitly, it's possible the size of the
last packet (or all the packets, for the CBR case) is larger than
1275. Reject them here.*/
if (last_size > 1275)
return OPUS_INVALID_PACKET;
size[count-1] = (opus_int16)last_size;
}
if (payload_offset)
*payload_offset = (int)(data-data0);
for (i=0;i<count;i++)
{
if (frames)
frames[i] = data;
data += size[i];
}
if (padding != NULL)
{
*padding = data;
*padding_len = pad;
}
if (packet_offset)
*packet_offset = pad+(opus_int32)(data-data0);
if (out_toc)
*out_toc = toc;
return count;
}
int opus_packet_parse(const unsigned char *data, opus_int32 len,
unsigned char *out_toc, const unsigned char *frames[48],
opus_int16 size[48], int *payload_offset)
{
return opus_packet_parse_impl(data, len, 0, out_toc,
frames, size, payload_offset, NULL, NULL, NULL);
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+223
View File
@@ -0,0 +1,223 @@
/* Copyright (c) 2012 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 OPUS_PRIVATE_H
#define OPUS_PRIVATE_H
#include "../celt/arch.h"
#include "../include/opus.h"
#include "../celt/celt.h"
#include <stdarg.h> /* va_list */
#include <stddef.h> /* offsetof */
struct OpusRepacketizer {
unsigned char toc;
int nb_frames;
const unsigned char *frames[48];
opus_int16 len[48];
int framesize;
const unsigned char *paddings[48];
opus_int32 padding_len[48];
};
typedef struct {
int id;
int frame;
const unsigned char *data;
opus_int32 len;
} opus_extension_data;
typedef struct ChannelLayout {
int nb_channels;
int nb_streams;
int nb_coupled_streams;
unsigned char mapping[256];
} ChannelLayout;
typedef enum {
MAPPING_TYPE_NONE,
MAPPING_TYPE_SURROUND,
MAPPING_TYPE_AMBISONICS
} MappingType;
struct OpusMSEncoder {
ChannelLayout layout;
int arch;
int lfe_stream;
int application;
int variable_duration;
MappingType mapping_type;
opus_int32 bitrate_bps;
/* Encoder states go here */
/* then opus_val32 window_mem[channels*120]; */
/* then opus_val32 preemph_mem[channels]; */
};
struct OpusMSDecoder {
ChannelLayout layout;
/* Decoder states go here */
};
int opus_multistream_encoder_ctl_va_list(struct OpusMSEncoder *st, int request,
va_list ap);
int opus_multistream_decoder_ctl_va_list(struct OpusMSDecoder *st, int request,
va_list ap);
int validate_layout(const ChannelLayout *layout);
int get_left_channel(const ChannelLayout *layout, int stream_id, int prev);
int get_right_channel(const ChannelLayout *layout, int stream_id, int prev);
int get_mono_channel(const ChannelLayout *layout, int stream_id, int prev);
typedef void (*opus_copy_channel_in_func)(
opus_val16 *dst,
int dst_stride,
const void *src,
int src_stride,
int src_channel,
int frame_size,
void *user_data
);
typedef void (*opus_copy_channel_out_func)(
void *dst,
int dst_stride,
int dst_channel,
const opus_val16 *src,
int src_stride,
int frame_size,
void *user_data
);
#define MODE_SILK_ONLY 1000
#define MODE_HYBRID 1001
#define MODE_CELT_ONLY 1002
#define OPUS_SET_VOICE_RATIO_REQUEST 11018
#define OPUS_GET_VOICE_RATIO_REQUEST 11019
/** Configures the encoder's expected percentage of voice
* opposed to music or other signals.
*
* @note This interface is currently more aspiration than actuality. It's
* ultimately expected to bias an automatic signal classifier, but it currently
* just shifts the static bitrate to mode mapping around a little bit.
*
* @param[in] x <tt>int</tt>: Voice percentage in the range 0-100, inclusive.
* @hideinitializer */
#define OPUS_SET_VOICE_RATIO(x) OPUS_SET_VOICE_RATIO_REQUEST, __opus_check_int(x)
/** Gets the encoder's configured voice ratio value, @see OPUS_SET_VOICE_RATIO
*
* @param[out] x <tt>int*</tt>: Voice percentage in the range 0-100, inclusive.
* @hideinitializer */
#define OPUS_GET_VOICE_RATIO(x) OPUS_GET_VOICE_RATIO_REQUEST, __opus_check_int_ptr(x)
#define OPUS_SET_FORCE_MODE_REQUEST 11002
#define OPUS_SET_FORCE_MODE(x) OPUS_SET_FORCE_MODE_REQUEST, __opus_check_int(x)
typedef void (*downmix_func)(const void *, opus_val32 *, int, int, int, int, int);
void downmix_float(const void *_x, opus_val32 *sub, int subframe, int offset, int c1, int c2, int C);
void downmix_int(const void *_x, opus_val32 *sub, int subframe, int offset, int c1, int c2, int C);
int is_digital_silence(const opus_val16* pcm, int frame_size, int channels, int lsb_depth);
int encode_size(int size, unsigned char *data);
opus_int32 frame_size_select(opus_int32 frame_size, int variable_duration, opus_int32 Fs);
opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_size,
unsigned char *data, opus_int32 out_data_bytes, int lsb_depth,
const void *analysis_pcm, opus_int32 analysis_size, int c1, int c2,
int analysis_channels, downmix_func downmix, int float_api);
int opus_decode_native(OpusDecoder *st, const unsigned char *data, opus_int32 len,
opus_val16 *pcm, int frame_size, int decode_fec, int self_delimited,
opus_int32 *packet_offset, int soft_clip, const OpusDRED *dred, opus_int32 dred_offset);
/* Make sure everything is properly aligned. */
static OPUS_INLINE int align(int i)
{
struct foo {char c; union { void* p; opus_int32 i; opus_val32 v; } u;};
unsigned int alignment = offsetof(struct foo, u);
/* Optimizing compilers should optimize div and multiply into and
for all sensible alignment values. */
return ((i + alignment - 1) / alignment) * alignment;
}
/* More than that is ridiculous for now (3 * max frames per packet)*/
opus_int32 skip_extension(const unsigned char **data, opus_int32 len, opus_int32 *header_size);
int opus_packet_parse_impl(const unsigned char *data, opus_int32 len,
int self_delimited, unsigned char *out_toc,
const unsigned char *frames[48], opus_int16 size[48],
int *payload_offset, opus_int32 *packet_offset,
const unsigned char **padding, opus_int32 *padding_len);
opus_int32 opus_repacketizer_out_range_impl(OpusRepacketizer *rp, int begin, int end,
unsigned char *data, opus_int32 maxlen, int self_delimited, int pad,
const opus_extension_data *extensions, int nb_extensions);
int pad_frame(unsigned char *data, opus_int32 len, opus_int32 new_len);
int opus_multistream_encode_native
(
struct OpusMSEncoder *st,
opus_copy_channel_in_func copy_channel_in,
const void *pcm,
int analysis_frame_size,
unsigned char *data,
opus_int32 max_data_bytes,
int lsb_depth,
downmix_func downmix,
int float_api,
void *user_data
);
int opus_multistream_decode_native(
struct OpusMSDecoder *st,
const unsigned char *data,
opus_int32 len,
void *pcm,
opus_copy_channel_out_func copy_channel_out,
int frame_size,
int decode_fec,
int soft_clip,
void *user_data
);
opus_int32 opus_packet_extensions_parse(const unsigned char *data, opus_int32 len, opus_extension_data *extensions, opus_int32 *nb_extensions);
opus_int32 opus_packet_extensions_generate(unsigned char *data, opus_int32 len, const opus_extension_data *extensions, int nb_extensions, int pad);
opus_int32 opus_packet_extensions_count(const unsigned char *data, opus_int32 len);
opus_int32 opus_packet_pad_impl(unsigned char *data, opus_int32 len, opus_int32 new_len, int pad, const opus_extension_data *extensions, int nb_extensions);
#endif /* OPUS_PRIVATE_H */
+463
View File
@@ -0,0 +1,463 @@
/* Copyright (c) 2011 Xiph.Org Foundation
Written by Jean-Marc Valin */
/*
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifdef HAVE_CONFIG_H
#include "opus_config.h"
#endif
#include "../include/opus.h"
#include "opus_private.h"
#include "../celt/os_support.h"
#include "../celt/stack_alloc.h"
int opus_repacketizer_get_size(void)
{
return sizeof(OpusRepacketizer);
}
OpusRepacketizer *opus_repacketizer_init(OpusRepacketizer *rp)
{
rp->nb_frames = 0;
return rp;
}
OpusRepacketizer *opus_repacketizer_create(void)
{
OpusRepacketizer *rp;
rp=(OpusRepacketizer *)opus_alloc(opus_repacketizer_get_size());
if(rp==NULL)return NULL;
return opus_repacketizer_init(rp);
}
void opus_repacketizer_destroy(OpusRepacketizer *rp)
{
opus_free(rp);
}
static int opus_repacketizer_cat_impl(OpusRepacketizer *rp, const unsigned char *data, opus_int32 len, int self_delimited)
{
unsigned char tmp_toc;
int curr_nb_frames,ret;
/* Set of check ToC */
if (len<1) return OPUS_INVALID_PACKET;
if (rp->nb_frames == 0)
{
rp->toc = data[0];
rp->framesize = opus_packet_get_samples_per_frame(data, 8000);
} else if ((rp->toc&0xFC) != (data[0]&0xFC))
{
/*fprintf(stderr, "toc mismatch: 0x%x vs 0x%x\n", rp->toc, data[0]);*/
return OPUS_INVALID_PACKET;
}
curr_nb_frames = opus_packet_get_nb_frames(data, len);
if(curr_nb_frames<1) return OPUS_INVALID_PACKET;
/* Check the 120 ms maximum packet size */
if ((curr_nb_frames+rp->nb_frames)*rp->framesize > 960)
{
return OPUS_INVALID_PACKET;
}
ret=opus_packet_parse_impl(data, len, self_delimited, &tmp_toc, &rp->frames[rp->nb_frames], &rp->len[rp->nb_frames],
NULL, NULL, &rp->paddings[rp->nb_frames], &rp->padding_len[rp->nb_frames]);
if(ret<1)return ret;
/* set padding length to zero for all but the first frame */
while (curr_nb_frames > 1)
{
rp->nb_frames++;
rp->padding_len[rp->nb_frames] = 0;
rp->paddings[rp->nb_frames] = NULL;
curr_nb_frames--;
}
rp->nb_frames++;
return OPUS_OK;
}
int opus_repacketizer_cat(OpusRepacketizer *rp, const unsigned char *data, opus_int32 len)
{
return opus_repacketizer_cat_impl(rp, data, len, 0);
}
int opus_repacketizer_get_nb_frames(OpusRepacketizer *rp)
{
return rp->nb_frames;
}
opus_int32 opus_repacketizer_out_range_impl(OpusRepacketizer *rp, int begin, int end,
unsigned char *data, opus_int32 maxlen, int self_delimited, int pad, const opus_extension_data *extensions, int nb_extensions)
{
int i, count;
opus_int32 tot_size;
opus_int16 *len;
const unsigned char **frames;
unsigned char * ptr;
int ones_begin=0, ones_end=0;
int ext_begin=0, ext_len=0;
int ext_count, total_ext_count;
VARDECL(opus_extension_data, all_extensions);
SAVE_STACK;
if (begin<0 || begin>=end || end>rp->nb_frames)
{
/*fprintf(stderr, "%d %d %d\n", begin, end, rp->nb_frames);*/
RESTORE_STACK;
return OPUS_BAD_ARG;
}
count = end-begin;
len = rp->len+begin;
frames = rp->frames+begin;
if (self_delimited)
tot_size = 1 + (len[count-1]>=252);
else
tot_size = 0;
/* figure out total number of extensions */
total_ext_count = nb_extensions;
for (i=begin;i<end;i++)
{
int n = opus_packet_extensions_count(rp->paddings[i], rp->padding_len[i]);
if (n > 0) total_ext_count += n;
}
ALLOC(all_extensions, total_ext_count ? total_ext_count : ALLOC_NONE, opus_extension_data);
/* copy over any extensions that were passed in */
for (ext_count=0;ext_count<nb_extensions;ext_count++)
{
all_extensions[ext_count] = extensions[ext_count];
}
/* incorporate any extensions from the repacketizer padding */
for (i=begin;i<end;i++)
{
int frame_ext_count, j;
frame_ext_count = total_ext_count - ext_count;
int ret = opus_packet_extensions_parse(rp->paddings[i], rp->padding_len[i],
&all_extensions[ext_count], &frame_ext_count);
if (ret<0)
{
RESTORE_STACK;
return OPUS_INTERNAL_ERROR;
}
/* renumber the extension frame numbers */
for (j=0;j<frame_ext_count;j++)
{
all_extensions[ext_count+j].frame += i-begin;
}
ext_count += frame_ext_count;
}
ptr = data;
if (count==1)
{
/* Code 0 */
tot_size += len[0]+1;
if (tot_size > maxlen)
{
RESTORE_STACK;
return OPUS_BUFFER_TOO_SMALL;
}
*ptr++ = rp->toc&0xFC;
} else if (count==2)
{
if (len[1] == len[0])
{
/* Code 1 */
tot_size += 2*len[0]+1;
if (tot_size > maxlen)
{
RESTORE_STACK;
return OPUS_BUFFER_TOO_SMALL;
}
*ptr++ = (rp->toc&0xFC) | 0x1;
} else {
/* Code 2 */
tot_size += len[0]+len[1]+2+(len[0]>=252);
if (tot_size > maxlen)
{
RESTORE_STACK;
return OPUS_BUFFER_TOO_SMALL;
}
*ptr++ = (rp->toc&0xFC) | 0x2;
ptr += encode_size(len[0], ptr);
}
}
if (count > 2 || (pad && tot_size < maxlen) || ext_count > 0)
{
/* Code 3 */
int vbr;
int pad_amount=0;
/* Restart the process for the padding case */
ptr = data;
if (self_delimited)
tot_size = 1 + (len[count-1]>=252);
else
tot_size = 0;
vbr = 0;
for (i=1;i<count;i++)
{
if (len[i] != len[0])
{
vbr=1;
break;
}
}
if (vbr)
{
tot_size += 2;
for (i=0;i<count-1;i++)
tot_size += 1 + (len[i]>=252) + len[i];
tot_size += len[count-1];
if (tot_size > maxlen)
{
RESTORE_STACK;
return OPUS_BUFFER_TOO_SMALL;
}
*ptr++ = (rp->toc&0xFC) | 0x3;
*ptr++ = count | 0x80;
} else {
tot_size += count*len[0]+2;
if (tot_size > maxlen)
{
RESTORE_STACK;
return OPUS_BUFFER_TOO_SMALL;
}
*ptr++ = (rp->toc&0xFC) | 0x3;
*ptr++ = count;
}
pad_amount = pad ? (maxlen-tot_size) : 0;
if (ext_count>0)
{
/* figure out how much space we need for the extensions */
ext_len = opus_packet_extensions_generate(NULL, maxlen-tot_size, all_extensions, ext_count, 0);
if (ext_len < 0) return ext_len;
if (!pad)
pad_amount = ext_len + ext_len/254 + 1;
}
if (pad_amount != 0)
{
int nb_255s;
data[1] |= 0x40;
nb_255s = (pad_amount-1)/255;
if (tot_size + ext_len + nb_255s + 1 > maxlen)
{
RESTORE_STACK;
return OPUS_BUFFER_TOO_SMALL;
}
ext_begin = tot_size+pad_amount-ext_len;
/* Prepend 0x01 padding */
ones_begin = tot_size+nb_255s+1;
ones_end = tot_size+pad_amount-ext_len;
for (i=0;i<nb_255s;i++)
*ptr++ = 255;
*ptr++ = pad_amount-255*nb_255s-1;
tot_size += pad_amount;
}
if (vbr)
{
for (i=0;i<count-1;i++)
ptr += encode_size(len[i], ptr);
}
}
if (self_delimited) {
int sdlen = encode_size(len[count-1], ptr);
ptr += sdlen;
}
/* Copy the actual data */
for (i=0;i<count;i++)
{
/* Using OPUS_MOVE() instead of OPUS_COPY() in case we're doing in-place
padding from opus_packet_pad or opus_packet_unpad(). */
/* assert disabled because it's not valid in C. */
/* celt_assert(frames[i] + len[i] <= data || ptr <= frames[i]); */
OPUS_MOVE(ptr, frames[i], len[i]);
ptr += len[i];
}
if (ext_len > 0) {
int ret = opus_packet_extensions_generate(&data[ext_begin], ext_len, all_extensions, ext_count, 0);
celt_assert(ret == ext_len);
}
for (i=ones_begin;i<ones_end;i++)
data[i] = 0x01;
if (pad && ext_count==0)
{
/* Fill padding with zeros. */
while (ptr<data+maxlen)
*ptr++=0;
}
RESTORE_STACK;
return tot_size;
}
opus_int32 opus_repacketizer_out_range(OpusRepacketizer *rp, int begin, int end, unsigned char *data, opus_int32 maxlen)
{
return opus_repacketizer_out_range_impl(rp, begin, end, data, maxlen, 0, 0, NULL, 0);
}
opus_int32 opus_repacketizer_out(OpusRepacketizer *rp, unsigned char *data, opus_int32 maxlen)
{
return opus_repacketizer_out_range_impl(rp, 0, rp->nb_frames, data, maxlen, 0, 0, NULL, 0);
}
opus_int32 opus_packet_pad_impl(unsigned char *data, opus_int32 len, opus_int32 new_len, int pad, const opus_extension_data *extensions, int nb_extensions)
{
OpusRepacketizer rp;
opus_int32 ret;
VARDECL(unsigned char, copy);
SAVE_STACK;
if (len < 1)
return OPUS_BAD_ARG;
if (len==new_len)
return OPUS_OK;
else if (len > new_len)
return OPUS_BAD_ARG;
ALLOC(copy, len, unsigned char);
opus_repacketizer_init(&rp);
/* Moving payload to the end of the packet so we can do in-place padding */
OPUS_COPY(copy, data, len);
ret = opus_repacketizer_cat(&rp, copy, len);
if (ret != OPUS_OK)
return ret;
ret = opus_repacketizer_out_range_impl(&rp, 0, rp.nb_frames, data, new_len, 0, pad, extensions, nb_extensions);
RESTORE_STACK;
return ret;
}
int opus_packet_pad(unsigned char *data, opus_int32 len, opus_int32 new_len)
{
opus_int32 ret;
ALLOC_STACK;
ret = opus_packet_pad_impl(data, len, new_len, 1, NULL, 0);
RESTORE_STACK;
if (ret > 0)
return OPUS_OK;
else
return ret;
}
opus_int32 opus_packet_unpad(unsigned char *data, opus_int32 len)
{
OpusRepacketizer rp;
opus_int32 ret;
int i;
if (len < 1)
return OPUS_BAD_ARG;
opus_repacketizer_init(&rp);
ret = opus_repacketizer_cat(&rp, data, len);
if (ret < 0)
return ret;
/* Discard all padding and extensions. */
for (i=0;i<rp.nb_frames;i++) {
rp.padding_len[i] = 0;
rp.paddings[i] = NULL;
}
ret = opus_repacketizer_out_range_impl(&rp, 0, rp.nb_frames, data, len, 0, 0, NULL, 0);
celt_assert(ret > 0 && ret <= len);
return ret;
}
int opus_multistream_packet_pad(unsigned char *data, opus_int32 len, opus_int32 new_len, int nb_streams)
{
int s;
int count;
unsigned char toc;
opus_int16 size[48];
opus_int32 packet_offset;
opus_int32 amount;
if (len < 1)
return OPUS_BAD_ARG;
if (len==new_len)
return OPUS_OK;
else if (len > new_len)
return OPUS_BAD_ARG;
amount = new_len - len;
/* Seek to last stream */
for (s=0;s<nb_streams-1;s++)
{
if (len<=0)
return OPUS_INVALID_PACKET;
count = opus_packet_parse_impl(data, len, 1, &toc, NULL,
size, NULL, &packet_offset, NULL, NULL);
if (count<0)
return count;
data += packet_offset;
len -= packet_offset;
}
return opus_packet_pad(data, len, len+amount);
}
opus_int32 opus_multistream_packet_unpad(unsigned char *data, opus_int32 len, int nb_streams)
{
int s;
unsigned char toc;
opus_int16 size[48];
opus_int32 packet_offset;
OpusRepacketizer rp;
unsigned char *dst;
opus_int32 dst_len;
if (len < 1)
return OPUS_BAD_ARG;
dst = data;
dst_len = 0;
/* Unpad all frames */
for (s=0;s<nb_streams;s++)
{
opus_int32 ret;
int i;
int self_delimited = s!=nb_streams-1;
if (len<=0)
return OPUS_INVALID_PACKET;
opus_repacketizer_init(&rp);
ret = opus_packet_parse_impl(data, len, self_delimited, &toc, NULL,
size, NULL, &packet_offset, NULL, NULL);
if (ret<0)
return ret;
ret = opus_repacketizer_cat_impl(&rp, data, packet_offset, self_delimited);
if (ret < 0)
return ret;
/* Discard all padding and extensions. */
for (i=0;i<rp.nb_frames;i++) {
rp.padding_len[i] = 0;
rp.paddings[i] = NULL;
}
ret = opus_repacketizer_out_range_impl(&rp, 0, rp.nb_frames, dst, len, self_delimited, 0, NULL, 0);
if (ret < 0)
return ret;
else
dst_len += ret;
dst += ret;
data += packet_offset;
len -= packet_offset;
}
return dst_len;
}