feat: integrate Opus codec into lib/libopus + voice messages in chatgui

- Add lib/libopus/ (opus v1.6.1 embedded source: CELT 18 .c, SILK 77 .c, SILK float 28 .c, OPUS core 14 .c)
- Add lib/opus_codec.h/.c (wrapper: encoder, decoder, raw PCM int16)
- Add tests/test_opus_codec.c (7 tests: silence, sine, compression, PLC, null, defaults, multi-frame)
- chatgui: AudioRecorder (miniaudio capture, 48kHz mono)
- chatgui: VoiceEncoder (PCM→Opus file with custom container)
- chatgui: VoicePlayer (Opus→PCM playback via SoundManager)
- chatgui: PTT button in InputBar, voice message send/receive in MessageList
- chatgui: AudioDeviceSettingsPage (device selection, persisted in ui_state)
- chatgui: MessageDelegate voice message rendering (play button + duration)
- Update autotools: configure.ac, Makefile.am, src/Makefile.am, tests/Makefile.am
- Update CMake: chatgui CMakeLists.txt, libutun CMakeLists.txt (link libopus_internal.a)
This commit is contained in:
Evgeny committed 2026-07-26 20:34:38 +03:00
1 parent 4a23593020
commit 4fde0b0325
260 files changed
+72665 -16

No files matched your search

+982
View File
@@ -0,0 +1,982 @@
/* Copyright (c) 2011 Xiph.Org Foundation
Written by Jean-Marc Valin */
/*
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#define ANALYSIS_C
#ifdef MLP_TRAINING
#include <stdio.h>
#endif
#include "mathops.h"
#include "kiss_fft.h"
#include "celt.h"
#include "modes.h"
#include "arch.h"
#include "quant_bands.h"
#include "analysis.h"
#include "mlp.h"
#include "stack_alloc.h"
#include "float_cast.h"
#ifndef M_PI
#define M_PI 3.141592653
#endif
#ifndef DISABLE_FLOAT_API
#define TRANSITION_PENALTY 10
static const float dct_table[128] = {
0.250000f, 0.250000f, 0.250000f, 0.250000f, 0.250000f, 0.250000f, 0.250000f, 0.250000f,
0.250000f, 0.250000f, 0.250000f, 0.250000f, 0.250000f, 0.250000f, 0.250000f, 0.250000f,
0.351851f, 0.338330f, 0.311806f, 0.273300f, 0.224292f, 0.166664f, 0.102631f, 0.034654f,
-0.034654f,-0.102631f,-0.166664f,-0.224292f,-0.273300f,-0.311806f,-0.338330f,-0.351851f,
0.346760f, 0.293969f, 0.196424f, 0.068975f,-0.068975f,-0.196424f,-0.293969f,-0.346760f,
-0.346760f,-0.293969f,-0.196424f,-0.068975f, 0.068975f, 0.196424f, 0.293969f, 0.346760f,
0.338330f, 0.224292f, 0.034654f,-0.166664f,-0.311806f,-0.351851f,-0.273300f,-0.102631f,
0.102631f, 0.273300f, 0.351851f, 0.311806f, 0.166664f,-0.034654f,-0.224292f,-0.338330f,
0.326641f, 0.135299f,-0.135299f,-0.326641f,-0.326641f,-0.135299f, 0.135299f, 0.326641f,
0.326641f, 0.135299f,-0.135299f,-0.326641f,-0.326641f,-0.135299f, 0.135299f, 0.326641f,
0.311806f, 0.034654f,-0.273300f,-0.338330f,-0.102631f, 0.224292f, 0.351851f, 0.166664f,
-0.166664f,-0.351851f,-0.224292f, 0.102631f, 0.338330f, 0.273300f,-0.034654f,-0.311806f,
0.293969f,-0.068975f,-0.346760f,-0.196424f, 0.196424f, 0.346760f, 0.068975f,-0.293969f,
-0.293969f, 0.068975f, 0.346760f, 0.196424f,-0.196424f,-0.346760f,-0.068975f, 0.293969f,
0.273300f,-0.166664f,-0.338330f, 0.034654f, 0.351851f, 0.102631f,-0.311806f,-0.224292f,
0.224292f, 0.311806f,-0.102631f,-0.351851f,-0.034654f, 0.338330f, 0.166664f,-0.273300f,
};
static const float analysis_window[240] = {
0.000043f, 0.000171f, 0.000385f, 0.000685f, 0.001071f, 0.001541f, 0.002098f, 0.002739f,
0.003466f, 0.004278f, 0.005174f, 0.006156f, 0.007222f, 0.008373f, 0.009607f, 0.010926f,
0.012329f, 0.013815f, 0.015385f, 0.017037f, 0.018772f, 0.020590f, 0.022490f, 0.024472f,
0.026535f, 0.028679f, 0.030904f, 0.033210f, 0.035595f, 0.038060f, 0.040604f, 0.043227f,
0.045928f, 0.048707f, 0.051564f, 0.054497f, 0.057506f, 0.060591f, 0.063752f, 0.066987f,
0.070297f, 0.073680f, 0.077136f, 0.080665f, 0.084265f, 0.087937f, 0.091679f, 0.095492f,
0.099373f, 0.103323f, 0.107342f, 0.111427f, 0.115579f, 0.119797f, 0.124080f, 0.128428f,
0.132839f, 0.137313f, 0.141849f, 0.146447f, 0.151105f, 0.155823f, 0.160600f, 0.165435f,
0.170327f, 0.175276f, 0.180280f, 0.185340f, 0.190453f, 0.195619f, 0.200838f, 0.206107f,
0.211427f, 0.216797f, 0.222215f, 0.227680f, 0.233193f, 0.238751f, 0.244353f, 0.250000f,
0.255689f, 0.261421f, 0.267193f, 0.273005f, 0.278856f, 0.284744f, 0.290670f, 0.296632f,
0.302628f, 0.308658f, 0.314721f, 0.320816f, 0.326941f, 0.333097f, 0.339280f, 0.345492f,
0.351729f, 0.357992f, 0.364280f, 0.370590f, 0.376923f, 0.383277f, 0.389651f, 0.396044f,
0.402455f, 0.408882f, 0.415325f, 0.421783f, 0.428254f, 0.434737f, 0.441231f, 0.447736f,
0.454249f, 0.460770f, 0.467298f, 0.473832f, 0.480370f, 0.486912f, 0.493455f, 0.500000f,
0.506545f, 0.513088f, 0.519630f, 0.526168f, 0.532702f, 0.539230f, 0.545751f, 0.552264f,
0.558769f, 0.565263f, 0.571746f, 0.578217f, 0.584675f, 0.591118f, 0.597545f, 0.603956f,
0.610349f, 0.616723f, 0.623077f, 0.629410f, 0.635720f, 0.642008f, 0.648271f, 0.654508f,
0.660720f, 0.666903f, 0.673059f, 0.679184f, 0.685279f, 0.691342f, 0.697372f, 0.703368f,
0.709330f, 0.715256f, 0.721144f, 0.726995f, 0.732807f, 0.738579f, 0.744311f, 0.750000f,
0.755647f, 0.761249f, 0.766807f, 0.772320f, 0.777785f, 0.783203f, 0.788573f, 0.793893f,
0.799162f, 0.804381f, 0.809547f, 0.814660f, 0.819720f, 0.824724f, 0.829673f, 0.834565f,
0.839400f, 0.844177f, 0.848895f, 0.853553f, 0.858151f, 0.862687f, 0.867161f, 0.871572f,
0.875920f, 0.880203f, 0.884421f, 0.888573f, 0.892658f, 0.896677f, 0.900627f, 0.904508f,
0.908321f, 0.912063f, 0.915735f, 0.919335f, 0.922864f, 0.926320f, 0.929703f, 0.933013f,
0.936248f, 0.939409f, 0.942494f, 0.945503f, 0.948436f, 0.951293f, 0.954072f, 0.956773f,
0.959396f, 0.961940f, 0.964405f, 0.966790f, 0.969096f, 0.971321f, 0.973465f, 0.975528f,
0.977510f, 0.979410f, 0.981228f, 0.982963f, 0.984615f, 0.986185f, 0.987671f, 0.989074f,
0.990393f, 0.991627f, 0.992778f, 0.993844f, 0.994826f, 0.995722f, 0.996534f, 0.997261f,
0.997902f, 0.998459f, 0.998929f, 0.999315f, 0.999615f, 0.999829f, 0.999957f, 1.000000f,
};
static const int tbands[NB_TBANDS+1] = {
4, 8, 12, 16, 20, 24, 28, 32, 40, 48, 56, 64, 80, 96, 112, 136, 160, 192, 240
};
#define NB_TONAL_SKIP_BANDS 9
static opus_val32 silk_resampler_down2_hp(
opus_val32 *S, /* I/O State vector [ 2 ] */
opus_val32 *out, /* O Output signal [ floor(len/2) ] */
const opus_val32 *in, /* I Input signal [ len ] */
int inLen /* I Number of input samples */
)
{
int k, len2 = inLen/2;
opus_val32 in32, out32, out32_hp, Y, X;
opus_val64 hp_ener = 0;
/* Internal variables and state are in Q10 format */
for( k = 0; k < len2; k++ ) {
/* Convert to Q10 */
in32 = in[ 2 * k ];
/* All-pass section for even input sample */
Y = SUB32( in32, S[ 0 ] );
X = MULT16_32_Q15(QCONST16(0.6074371f, 15), Y);
out32 = ADD32( S[ 0 ], X );
S[ 0 ] = ADD32( in32, X );
out32_hp = out32;
/* Convert to Q10 */
in32 = in[ 2 * k + 1 ];
/* All-pass section for odd input sample, and add to output of previous section */
Y = SUB32( in32, S[ 1 ] );
X = MULT16_32_Q15(QCONST16(0.15063f, 15), Y);
out32 = ADD32( out32, S[ 1 ] );
out32 = ADD32( out32, X );
S[ 1 ] = ADD32( in32, X );
Y = SUB32( -in32, S[ 2 ] );
X = MULT16_32_Q15(QCONST16(0.15063f, 15), Y);
out32_hp = ADD32( out32_hp, S[ 2 ] );
out32_hp = ADD32( out32_hp, X );
S[ 2 ] = ADD32( -in32, X );
/* len2 can be up to 480, so we shift by 8 to make it fit. */
hp_ener += SHR64(out32_hp*(opus_val64)out32_hp, 8);
/* Add, convert back to int16 and store to output */
out[ k ] = HALF32(out32);
}
#ifdef FIXED_POINT
/* Fitting in 32 bits. */
hp_ener = hp_ener >> (2*SIG_SHIFT);
if (hp_ener > 2147483647) hp_ener = 2147483647;
#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);
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;
}
else if (Fs != 24000) celt_assert(0);
ALLOC(tmp, subframe, opus_val32);
downmix(_x, tmp, subframe, offset, c1, c2, C);
if ((c2==-2 && C==2) || c2>-1) {
for (j=0;j<subframe;j++) {
tmp[j] = HALF32(tmp[j]);
}
}
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;
#ifndef FIXED_POINT
ret *= 1.f/32768/32768;
#endif
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) ((1.f/32768/32768)*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.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 struct.
*
* 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
+672
View File
@@ -0,0 +1,672 @@
/* 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 "config.h"
#endif
#include "opus_types.h"
#include "opus_defines.h"
#include "arch.h"
#include "os_support.h"
#include "opus_private.h"
/* Given an extension payload (i.e., excluding the initial ID byte), advance
data to the next extension and return the length of the remaining
extensions.
N.B., a "Repeat These Extensions" extension (ID==2) does not advance past
the repeated extension payloads.
That requires higher-level logic. */
static opus_int32 skip_extension_payload(const unsigned char **pdata,
opus_int32 len, opus_int32 *pheader_size, int id_byte,
opus_int32 trailing_short_len)
{
const unsigned char *data;
opus_int32 header_size;
int id, L;
data = *pdata;
header_size = 0;
id = id_byte>>1;
L = id_byte&1;
if ((id == 0 && L == 1) || id == 2)
{
/* Nothing to do. */
} else if (id > 0 && id < 32)
{
if (len < L)
return -1;
data += L;
len -= L;
} else {
if (L==0)
{
if (len < trailing_short_len) return -1;
data += len - trailing_short_len;
len = trailing_short_len;
} else {
opus_int32 bytes=0;
opus_int32 lacing;
do {
if (len < 1)
return -1;
lacing = *data++;
bytes += lacing;
header_size++;
len -= lacing + 1;
} while (lacing == 255);
if (len < 0)
return -1;
data += bytes;
}
}
*pdata = data;
*pheader_size = header_size;
return len;
}
/* Given an extension, advance data to the next extension and return the
length of the remaining extensions.
N.B., a "Repeat These Extensions" extension (ID==2) only advances past the
extension ID byte.
Higher-level logic is required to skip the extension payloads that come
after it.*/
static opus_int32 skip_extension(const unsigned char **pdata, opus_int32 len,
opus_int32 *pheader_size)
{
const unsigned char *data;
int id_byte;
if (len == 0) {
*pheader_size = 0;
return 0;
}
if (len < 1)
return -1;
data = *pdata;
id_byte = *data++;
len--;
len = skip_extension_payload(&data, len, pheader_size, id_byte, 0);
if (len >= 0) {
*pdata = data;
(*pheader_size)++;
}
return len;
}
void opus_extension_iterator_init(OpusExtensionIterator *iter,
const unsigned char *data, opus_int32 len, opus_int32 nb_frames) {
celt_assert(len >= 0);
celt_assert(data != NULL || len == 0);
celt_assert(nb_frames >= 0 && nb_frames <= 48);
iter->repeat_data = iter->curr_data = iter->data = data;
iter->last_long = iter->src_data = NULL;
iter->curr_len = iter->len = len;
iter->repeat_len = iter->src_len = 0;
iter->trailing_short_len = 0;
iter->frame_max = iter->nb_frames = nb_frames;
iter->repeat_frame = iter->curr_frame = 0;
iter->repeat_l = 0;
}
/* Reset the iterator so it can start iterating again from the first
extension. */
void opus_extension_iterator_reset(OpusExtensionIterator *iter) {
iter->repeat_data = iter->curr_data = iter->data;
iter->last_long = NULL;
iter->curr_len = iter->len;
iter->repeat_frame = iter->curr_frame = 0;
iter->trailing_short_len = 0;
}
/* Tell the iterator not to return any extensions for frames of index
frame_max or larger.
This can allow it to stop iterating early if these extensions are not
needed. */
void opus_extension_iterator_set_frame_max(OpusExtensionIterator *iter,
int frame_max) {
iter->frame_max = frame_max;
}
/* Return the next repeated extension.
The return value is non-zero if one is found, negative on error, or 0 if we
have finished repeating extensions. */
static int opus_extension_iterator_next_repeat(OpusExtensionIterator *iter,
opus_extension_data *ext) {
opus_int32 header_size;
celt_assert(iter->repeat_frame > 0);
for (;iter->repeat_frame < iter->nb_frames; iter->repeat_frame++) {
while (iter->src_len > 0) {
const unsigned char *curr_data0;
int repeat_id_byte;
repeat_id_byte = *iter->src_data;
iter->src_len = skip_extension(&iter->src_data, iter->src_len,
&header_size);
/* We skipped this extension earlier, so it should not fail now. */
celt_assert(iter->src_len >= 0);
/* Don't repeat padding or frame separators with a 0 increment. */
if (repeat_id_byte <= 3) continue;
/* If the "Repeat These Extensions" extension had L == 0 and this
is the last repeated long extension, then force decoding the
payload with L = 0. */
if (iter->repeat_l == 0
&& iter->repeat_frame + 1 >= iter->nb_frames
&& iter->src_data == iter->last_long) {
repeat_id_byte &= ~1;
}
curr_data0 = iter->curr_data;
iter->curr_len = skip_extension_payload(&iter->curr_data,
iter->curr_len, &header_size, repeat_id_byte,
iter->trailing_short_len);
if (iter->curr_len < 0) {
return OPUS_INVALID_PACKET;
}
celt_assert(iter->curr_data - iter->data
== iter->len - iter->curr_len);
/* If we were asked to stop at frame_max, skip extensions for later
frames. */
if (iter->repeat_frame >= iter->frame_max) {
continue;
}
if (ext != NULL) {
ext->id = repeat_id_byte >> 1;
ext->frame = iter->repeat_frame;
ext->data = curr_data0 + header_size;
ext->len = iter->curr_data - curr_data0 - header_size;
}
return 1;
}
/* We finished repeating the extensions for this frame. */
iter->src_data = iter->repeat_data;
iter->src_len = iter->repeat_len;
}
/* We finished repeating extensions. */
iter->repeat_data = iter->curr_data;
iter->last_long = NULL;
/* If L == 0, advance the frame number to handle the case where we did
not consume all of the data with an L == 0 long extension. */
if (iter->repeat_l == 0) {
iter->curr_frame++;
/* Ignore additional padding if this was already the last frame. */
if (iter->curr_frame >= iter->nb_frames) {
iter->curr_len = 0;
}
}
iter->repeat_frame = 0;
return 0;
}
/* Return the next extension (excluding real padding, separators, and repeat
indicators, but including the repeated extensions) in bitstream order.
Due to the extension repetition mechanism, extensions are not necessarily
returned in frame order. */
int opus_extension_iterator_next(OpusExtensionIterator *iter,
opus_extension_data *ext) {
opus_int32 header_size;
if (iter->curr_len < 0) {
return OPUS_INVALID_PACKET;
}
if (iter->repeat_frame > 0) {
int ret;
/* We are in the process of repeating some extensions. */
ret = opus_extension_iterator_next_repeat(iter, ext);
if (ret) return ret;
}
/* Checking this here allows opus_extension_iterator_set_frame_max() to be
called at any point. */
if (iter->curr_frame >= iter->frame_max) {
return 0;
}
while (iter->curr_len > 0) {
const unsigned char *curr_data0;
int id;
int L;
curr_data0 = iter->curr_data;
id = *curr_data0>>1;
L = *curr_data0&1;
iter->curr_len = skip_extension(&iter->curr_data, iter->curr_len,
&header_size);
if (iter->curr_len < 0) {
return OPUS_INVALID_PACKET;
}
celt_assert(iter->curr_data - iter->data == iter->len - iter->curr_len);
if (id == 1) {
if (L == 0) {
iter->curr_frame++;
}
else {
/* A frame increment of 0 is a no-op. */
if (!curr_data0[1]) continue;
iter->curr_frame += curr_data0[1];
}
if (iter->curr_frame >= iter->nb_frames) {
iter->curr_len = -1;
return OPUS_INVALID_PACKET;
}
/* If we were asked to stop at frame_max, skip extensions for later
frames. */
if (iter->curr_frame >= iter->frame_max) {
iter->curr_len = 0;
}
iter->repeat_data = iter->curr_data;
iter->last_long = NULL;
iter->trailing_short_len = 0;
}
else if (id == 2) {
int ret;
iter->repeat_l = L;
iter->repeat_frame = iter->curr_frame + 1;
iter->repeat_len = curr_data0 - iter->repeat_data;
iter->src_data = iter->repeat_data;
iter->src_len = iter->repeat_len;
ret = opus_extension_iterator_next_repeat(iter, ext);
if (ret) return ret;
}
else if (id > 2) {
/* Update the location of the last long extension.
This lets us know when we need to modify the last L flag if we
repeat these extensions with L=0. */
if (id >= 32) {
iter->last_long = iter->curr_data;
iter->trailing_short_len = 0;
}
/* Otherwise, keep track of how many payload bytes follow the last
long extension. */
else iter->trailing_short_len += L;
if (ext != NULL) {
ext->id = id;
ext->frame = iter->curr_frame;
ext->data = curr_data0 + header_size;
ext->len = iter->curr_data - curr_data0 - header_size;
}
return 1;
}
}
return 0;
}
int opus_extension_iterator_find(OpusExtensionIterator *iter,
opus_extension_data *ext, int id) {
opus_extension_data curr_ext;
int ret;
for(;;) {
ret = opus_extension_iterator_next(iter, &curr_ext);
if (ret <= 0) {
return ret;
}
if (curr_ext.id == id) {
*ext = curr_ext;
return ret;
}
}
}
/* Count the number of extensions, excluding real padding, separators, and
repeat indicators, but including the repeated extensions. */
opus_int32 opus_packet_extensions_count(const unsigned char *data,
opus_int32 len, int nb_frames)
{
OpusExtensionIterator iter;
int count;
opus_extension_iterator_init(&iter, data, len, nb_frames);
for (count=0; opus_extension_iterator_next(&iter, NULL) > 0; count++);
return count;
}
/* Count the number of extensions for each frame, excluding real padding and
separators and repeat indicators, but including the repeated extensions. */
opus_int32 opus_packet_extensions_count_ext(const unsigned char *data,
opus_int32 len, opus_int32 *nb_frame_exts, int nb_frames) {
OpusExtensionIterator iter;
opus_extension_data ext;
int count;
opus_extension_iterator_init(&iter, data, len, nb_frames);
OPUS_CLEAR(nb_frame_exts, nb_frames);
for (count=0; opus_extension_iterator_next(&iter, &ext) > 0; count++) {
nb_frame_exts[ext.frame]++;
}
return count;
}
/* Extract extensions from Opus padding (excluding real padding, separators,
and repeat indicators, but including the repeated extensions) in bitstream
order.
Due to the extension repetition mechanism, extensions are not necessarily
returned in frame order. */
opus_int32 opus_packet_extensions_parse(const unsigned char *data,
opus_int32 len, opus_extension_data *extensions, opus_int32 *nb_extensions,
int nb_frames) {
OpusExtensionIterator iter;
int count;
int ret;
celt_assert(nb_extensions != NULL);
celt_assert(extensions != NULL || *nb_extensions == 0);
opus_extension_iterator_init(&iter, data, len, nb_frames);
for (count=0;; count++) {
opus_extension_data ext;
ret = opus_extension_iterator_next(&iter, &ext);
if (ret <= 0) break;
if (count == *nb_extensions) {
return OPUS_BUFFER_TOO_SMALL;
}
extensions[count] = ext;
}
*nb_extensions = count;
return ret;
}
/* Extract extensions from Opus padding (excluding real padding, separators,
and repeat indicators, but including the repeated extensions) in frame
order.
nb_frame_exts must be filled with the output of
opus_packet_extensions_count_ext(). */
opus_int32 opus_packet_extensions_parse_ext(const unsigned char *data,
opus_int32 len, opus_extension_data *extensions, opus_int32 *nb_extensions,
const opus_int32 *nb_frame_exts, int nb_frames) {
OpusExtensionIterator iter;
opus_extension_data ext;
opus_int32 nb_frames_cum[49];
int count;
int prev_total;
int ret;
celt_assert(nb_extensions != NULL);
celt_assert(extensions != NULL || *nb_extensions == 0);
celt_assert(nb_frames <= 48);
/* Convert the frame extension count array to a cumulative sum. */
prev_total = 0;
for (count=0; count<nb_frames; count++) {
int total;
total = nb_frame_exts[count] + prev_total;
nb_frames_cum[count] = prev_total;
prev_total = total;
}
nb_frames_cum[count] = prev_total;
opus_extension_iterator_init(&iter, data, len, nb_frames);
for (count=0;; count++) {
opus_int32 idx;
ret = opus_extension_iterator_next(&iter, &ext);
if (ret <= 0) break;
idx = nb_frames_cum[ext.frame]++;
if (idx >= *nb_extensions) {
return OPUS_BUFFER_TOO_SMALL;
}
celt_assert(idx < nb_frames_cum[ext.frame + 1]);
extensions[idx] = ext;
}
*nb_extensions = count;
return ret;
}
static int write_extension_payload(unsigned char *data, opus_int32 len,
opus_int32 pos, const opus_extension_data *ext, int last) {
celt_assert(ext->id >= 3 && ext->id <= 127);
if (ext->id < 32)
{
if (ext->len < 0 || ext->len > 1)
return OPUS_BAD_ARG;
if (ext->len > 0) {
if (len-pos < ext->len)
return OPUS_BUFFER_TOO_SMALL;
if (data) data[pos] = ext->data[0];
pos++;
}
} else {
opus_int32 length_bytes;
if (ext->len < 0)
return OPUS_BAD_ARG;
length_bytes = 1 + ext->len/255;
if (last)
length_bytes = 0;
if (len-pos < length_bytes + ext->len)
return OPUS_BUFFER_TOO_SMALL;
if (!last)
{
opus_int32 j;
for (j=0;j<ext->len/255;j++) {
if (data) data[pos] = 255;
pos++;
}
if (data) data[pos] = ext->len % 255;
pos++;
}
if (data) OPUS_COPY(&data[pos], ext->data, ext->len);
pos += ext->len;
}
return pos;
}
static int write_extension(unsigned char *data, opus_int32 len, opus_int32 pos,
const opus_extension_data *ext, int last) {
if (len-pos < 1)
return OPUS_BUFFER_TOO_SMALL;
celt_assert(ext->id >= 3 && ext->id <= 127);
if (data) data[pos] = (ext->id<<1) + (ext->id < 32 ? ext->len : !last);
pos++;
return write_extension_payload(data, len, pos, ext, last);
}
opus_int32 opus_packet_extensions_generate(unsigned char *data, opus_int32 len,
const opus_extension_data *extensions, opus_int32 nb_extensions,
int nb_frames, int pad)
{
opus_int32 frame_min_idx[48];
opus_int32 frame_max_idx[48];
opus_int32 frame_repeat_idx[48];
opus_int32 i;
int f;
int curr_frame = 0;
opus_int32 pos = 0;
opus_int32 written = 0;
celt_assert(len >= 0);
if (nb_frames > 48) return OPUS_BAD_ARG;
/* Do a little work up-front to make this O(nb_extensions) instead of
O(nb_extensions*nb_frames) so long as the extensions are in frame
order (without requiring that they be in frame order). */
for (f=0;f<nb_frames;f++) frame_min_idx[f] = nb_extensions;
OPUS_CLEAR(frame_max_idx, nb_frames);
for (i=0;i<nb_extensions;i++)
{
f = extensions[i].frame;
if (f < 0 || f >= nb_frames) return OPUS_BAD_ARG;
if (extensions[i].id < 3 || extensions[i].id > 127) return OPUS_BAD_ARG;
frame_min_idx[f] = IMIN(frame_min_idx[f], i);
frame_max_idx[f] = IMAX(frame_max_idx[f], i+1);
}
for (f=0;f<nb_frames;f++) frame_repeat_idx[f] = frame_min_idx[f];
for (f=0;f<nb_frames;f++)
{
opus_int32 last_long_idx;
int repeat_count;
repeat_count = 0;
last_long_idx = -1;
if (f + 1 < nb_frames)
{
for (i=frame_min_idx[f];i<frame_max_idx[f];i++)
{
if (extensions[i].frame == f)
{
int g;
/* Test if we can repeat this extension in future frames. */
for (g=f+1;g<nb_frames;g++)
{
if (frame_repeat_idx[g] >= frame_max_idx[g]) break;
celt_assert(extensions[frame_repeat_idx[g]].frame == g);
if (extensions[frame_repeat_idx[g]].id != extensions[i].id)
{
break;
}
if (extensions[frame_repeat_idx[g]].id < 32
&& extensions[frame_repeat_idx[g]].len
!= extensions[i].len)
{
break;
}
}
if (g < nb_frames) break;
/* We can! */
/* If this is a long extension, save the index of the last
instance, so we can modify its L flag. */
if (extensions[i].id >= 32) {
last_long_idx = frame_repeat_idx[nb_frames-1];
}
/* Using the repeat mechanism almost always makes the
encoding smaller (or at least no larger).
However, there's one case where that might not be true: if
the last repeated long extension in the last frame was
previously the last extension, but using the repeat
mechanism makes that no longer true (because there are other
non-repeated extensions in earlier frames that must now be
coded after it), and coding its length requires more bytes
than the repeat mechanism saves.
This can only be true if its length is at least 255 bytes
(although sometimes it requires even more).
Currently we do not check for that, and just always use the
repeat mechanism if we can.
See git history for code that does the check. */
/* Advance the repeat pointers. */
for (g=f+1; g<nb_frames; g++)
{
int j;
for (j=frame_repeat_idx[g]+1; j<frame_max_idx[g]
&& extensions[j].frame != g; j++);
frame_repeat_idx[g] = j;
}
repeat_count++;
/* Point the repeat pointer for this frame to the current
extension, so we know when to trigger the repeats. */
frame_repeat_idx[f] = i;
}
}
}
for (i=frame_min_idx[f];i<frame_max_idx[f];i++)
{
if (extensions[i].frame == f)
{
/* Insert separator when needed. */
if (f != curr_frame) {
int diff = f - 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 = f;
}
pos = write_extension(data, len, pos, extensions + i,
written == nb_extensions - 1);
if (pos < 0) return pos;
written++;
if (repeat_count > 0 && frame_repeat_idx[f] == i) {
int nb_repeated;
int last;
int g;
/* Add the repeat indicator. */
nb_repeated = repeat_count*(nb_frames - (f + 1));
last = written + nb_repeated == nb_extensions
|| (last_long_idx < 0 && i+1 >= frame_max_idx[f]);
if (len-pos < 1)
return OPUS_BUFFER_TOO_SMALL;
if (data) data[pos] = 0x04 + !last;
pos++;
for (g=f+1;g<nb_frames;g++)
{
int j;
for (j=frame_min_idx[g];j<frame_repeat_idx[g];j++)
{
if (extensions[j].frame == g)
{
pos = write_extension_payload(data, len, pos,
extensions + j, last && j == last_long_idx);
if (pos < 0) return pos;
written++;
}
}
frame_min_idx[g] = j;
}
if (last) curr_frame++;
}
}
}
}
celt_assert(written == nb_extensions);
/* 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 extension 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
+997
View File
@@ -0,0 +1,997 @@
/* Copyright (c) 2017 Google Inc.
Written by Andrew Allen */
/*
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "arch.h"
#include "float_cast.h"
#include "opus_private.h"
#include "opus_defines.h"
#include "mapping_matrix.h"
#define MATRIX_INDEX(nb_rows, row, col) (nb_rows * col + row)
opus_int32 mapping_matrix_get_size(int rows, int cols)
{
opus_int32 size;
/* Mapping Matrix must only support up to 255 channels in or out.
* Additionally, the total cell count must be <= 65004 octets in order
* for the matrix to be stored in an OGG header.
*/
if (rows > 255 || cols > 255)
return 0;
size = rows * (opus_int32)cols * sizeof(opus_int16);
if (size > 65004)
return 0;
return align(sizeof(MappingMatrix)) + align(size);
}
opus_int16 *mapping_matrix_get_data(const MappingMatrix *matrix)
{
/* void* cast avoids clang -Wcast-align warning */
return (opus_int16*)(void*)((char*)matrix + align(sizeof(MappingMatrix)));
}
void mapping_matrix_init(MappingMatrix * const matrix,
int rows, int cols, int gain, const opus_int16 *data, opus_int32 data_size)
{
int i;
opus_int16 *ptr;
#if !defined(ENABLE_ASSERTIONS)
(void)data_size;
#endif
celt_assert(align(data_size) == align(rows * cols * sizeof(opus_int16)));
matrix->rows = rows;
matrix->cols = cols;
matrix->gain = gain;
ptr = mapping_matrix_get_data(matrix);
for (i = 0; i < rows * cols; i++)
{
ptr[i] = data[i];
}
}
#ifndef DISABLE_FLOAT_API
void mapping_matrix_multiply_channel_in_float(
const MappingMatrix *matrix,
const float *input,
int input_rows,
opus_res *output,
int output_row,
int output_rows,
int frame_size)
{
/* Matrix data is ordered col-wise. */
opus_int16* matrix_data;
int i, col;
celt_assert(input_rows <= matrix->cols && output_rows <= matrix->rows);
matrix_data = mapping_matrix_get_data(matrix);
for (i = 0; i < frame_size; i++)
{
float tmp = 0;
for (col = 0; col < input_rows; col++)
{
tmp +=
matrix_data[MATRIX_INDEX(matrix->rows, output_row, col)] *
input[MATRIX_INDEX(input_rows, col, i)];
}
output[output_rows * i] = FLOAT2RES((1/32768.f)*tmp);
}
}
void mapping_matrix_multiply_channel_out_float(
const MappingMatrix *matrix,
const opus_res *input,
int input_row,
int input_rows,
float *output,
int output_rows,
int frame_size
)
{
/* Matrix data is ordered col-wise. */
opus_int16* matrix_data;
int i, row;
float input_sample;
celt_assert(input_rows <= matrix->cols && output_rows <= matrix->rows);
matrix_data = mapping_matrix_get_data(matrix);
for (i = 0; i < frame_size; i++)
{
input_sample = RES2FLOAT(input[input_rows * i]);
for (row = 0; row < output_rows; row++)
{
float tmp =
(1/32768.f)*matrix_data[MATRIX_INDEX(matrix->rows, row, input_row)] *
input_sample;
output[MATRIX_INDEX(output_rows, row, i)] += tmp;
}
}
}
#endif /* DISABLE_FLOAT_API */
void mapping_matrix_multiply_channel_in_short(
const MappingMatrix *matrix,
const opus_int16 *input,
int input_rows,
opus_res *output,
int output_row,
int output_rows,
int frame_size)
{
/* Matrix data is ordered col-wise. */
opus_int16* matrix_data;
int i, col;
celt_assert(input_rows <= matrix->cols && output_rows <= matrix->rows);
matrix_data = mapping_matrix_get_data(matrix);
for (i = 0; i < frame_size; i++)
{
opus_val32 tmp = 0;
for (col = 0; col < input_rows; col++)
{
#if defined(FIXED_POINT)
tmp +=
((opus_int32)matrix_data[MATRIX_INDEX(matrix->rows, output_row, col)] *
(opus_int32)input[MATRIX_INDEX(input_rows, col, i)]) >> 8;
#else
tmp +=
matrix_data[MATRIX_INDEX(matrix->rows, output_row, col)] *
input[MATRIX_INDEX(input_rows, col, i)];
#endif
}
#if defined(FIXED_POINT)
#ifdef ENABLE_RES24
output[output_rows * i] = SHL32(tmp, RES_SHIFT-7);
#else
output[output_rows * i] = SATURATE16((tmp + 64) >> 7);
#endif
#else
output[output_rows * i] = (1/(32768.f*32768.f))*tmp;
#endif
}
}
void mapping_matrix_multiply_channel_out_short(
const MappingMatrix *matrix,
const opus_res *input,
int input_row,
int input_rows,
opus_int16 *output,
int output_rows,
int frame_size)
{
/* Matrix data is ordered col-wise. */
opus_int16* matrix_data;
int i, row;
opus_int32 input_sample;
celt_assert(input_rows <= matrix->cols && output_rows <= matrix->rows);
matrix_data = mapping_matrix_get_data(matrix);
for (i = 0; i < frame_size; i++)
{
input_sample = RES2INT16(input[input_rows * i]);
for (row = 0; row < output_rows; row++)
{
opus_int32 tmp =
(opus_int32)matrix_data[MATRIX_INDEX(matrix->rows, row, input_row)] *
input_sample;
output[MATRIX_INDEX(output_rows, row, i)] += (tmp + 16384) >> 15;
}
}
}
void mapping_matrix_multiply_channel_in_int24(
const MappingMatrix *matrix,
const opus_int32 *input,
int input_rows,
opus_res *output,
int output_row,
int output_rows,
int frame_size)
{
/* Matrix data is ordered col-wise. */
opus_int16* matrix_data;
int i, col;
celt_assert(input_rows <= matrix->cols && output_rows <= matrix->rows);
matrix_data = mapping_matrix_get_data(matrix);
for (i = 0; i < frame_size; i++)
{
opus_val64 tmp = 0;
for (col = 0; col < input_rows; col++)
{
tmp +=
matrix_data[MATRIX_INDEX(matrix->rows, output_row, col)] *
(opus_val64)input[MATRIX_INDEX(input_rows, col, i)];
}
#if defined(FIXED_POINT)
output[output_rows * i] = INT24TORES((tmp + 16384) >> 15);
#else
output[output_rows * i] = INT24TORES((1/(32768.f))*tmp);
#endif
}
}
void mapping_matrix_multiply_channel_out_int24(
const MappingMatrix *matrix,
const opus_res *input,
int input_row,
int input_rows,
opus_int32 *output,
int output_rows,
int frame_size)
{
/* Matrix data is ordered col-wise. */
opus_int16* matrix_data;
int i, row;
opus_int32 input_sample;
celt_assert(input_rows <= matrix->cols && output_rows <= matrix->rows);
matrix_data = mapping_matrix_get_data(matrix);
for (i = 0; i < frame_size; i++)
{
input_sample = RES2INT24(input[input_rows * i]);
for (row = 0; row < output_rows; row++)
{
opus_int64 tmp =
(opus_int64)matrix_data[MATRIX_INDEX(matrix->rows, row, input_row)] *
input_sample;
output[MATRIX_INDEX(output_rows, row, i)] += (tmp + 16384) >> 15;
}
}
}
const MappingMatrix mapping_matrix_foa_mixing = { 6, 6, 0 };
const opus_int16 mapping_matrix_foa_mixing_data[36] = {
16384, 0, -16384, 23170, 0, 0, 16384, 23170,
16384, 0, 0, 0, 16384, 0, -16384, -23170,
0, 0, 16384, -23170, 16384, 0, 0, 0,
0, 0, 0, 0, 32767, 0, 0, 0,
0, 0, 0, 32767
};
const MappingMatrix mapping_matrix_soa_mixing = { 11, 11, 0 };
const opus_int16 mapping_matrix_soa_mixing_data[121] = {
10923, 7723, 13377, -13377, 11585, 9459, 7723, -16384,
-6689, 0, 0, 10923, 7723, 13377, 13377, -11585,
9459, 7723, 16384, -6689, 0, 0, 10923, -15447,
13377, 0, 0, -18919, 7723, 0, 13377, 0,
0, 10923, 7723, -13377, -13377, 11585, -9459, 7723,
16384, -6689, 0, 0, 10923, -7723, 0, 13377,
-16384, 0, -15447, 0, 9459, 0, 0, 10923,
-7723, 0, -13377, 16384, 0, -15447, 0, 9459,
0, 0, 10923, 15447, 0, 0, 0, 0,
-15447, 0, -18919, 0, 0, 10923, 7723, -13377,
13377, -11585, -9459, 7723, -16384, -6689, 0, 0,
10923, -15447, -13377, 0, 0, 18919, 7723, 0,
13377, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 32767, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
32767
};
const MappingMatrix mapping_matrix_toa_mixing = { 18, 18, 0 };
const opus_int16 mapping_matrix_toa_mixing_data[324] = {
8208, 0, -881, 14369, 0, 0, -8192, -4163,
13218, 0, 0, 0, 11095, -8836, -6218, 14833,
0, 0, 8208, -10161, 881, 10161, -13218, -2944,
-8192, 2944, 0, -10488, -6218, 6248, -11095, -6248,
0, -10488, 0, 0, 8208, 10161, 881, -10161,
-13218, 2944, -8192, -2944, 0, 10488, -6218, -6248,
-11095, 6248, 0, 10488, 0, 0, 8176, 5566,
-11552, 5566, 9681, -11205, 8192, -11205, 0, 4920,
-15158, 9756, -3334, 9756, 0, -4920, 0, 0,
8176, 7871, 11552, 0, 0, 15846, 8192, 0,
-9681, -6958, 0, 13797, 3334, 0, -15158, 0,
0, 0, 8176, 0, 11552, 7871, 0, 0,
8192, 15846, 9681, 0, 0, 0, 3334, 13797,
15158, 6958, 0, 0, 8176, 5566, -11552, -5566,
-9681, -11205, 8192, 11205, 0, 4920, 15158, 9756,
-3334, -9756, 0, 4920, 0, 0, 8208, 14369,
-881, 0, 0, -4163, -8192, 0, -13218, -14833,
0, -8836, 11095, 0, 6218, 0, 0, 0,
8208, 10161, 881, 10161, 13218, 2944, -8192, 2944,
0, 10488, 6218, -6248, -11095, -6248, 0, -10488,
0, 0, 8208, -14369, -881, 0, 0, 4163,
-8192, 0, -13218, 14833, 0, 8836, 11095, 0,
6218, 0, 0, 0, 8208, 0, -881, -14369,
0, 0, -8192, 4163, 13218, 0, 0, 0,
11095, 8836, -6218, -14833, 0, 0, 8176, -5566,
-11552, 5566, -9681, 11205, 8192, -11205, 0, -4920,
15158, -9756, -3334, 9756, 0, -4920, 0, 0,
8176, 0, 11552, -7871, 0, 0, 8192, -15846,
9681, 0, 0, 0, 3334, -13797, 15158, -6958,
0, 0, 8176, -7871, 11552, 0, 0, -15846,
8192, 0, -9681, 6958, 0, -13797, 3334, 0,
-15158, 0, 0, 0, 8176, -5566, -11552, -5566,
9681, 11205, 8192, 11205, 0, -4920, -15158, -9756,
-3334, -9756, 0, 4920, 0, 0, 8208, -10161,
881, -10161, 13218, -2944, -8192, -2944, 0, -10488,
6218, 6248, -11095, 6248, 0, 10488, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
32767, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 32767
};
const MappingMatrix mapping_matrix_fourthoa_mixing = { 27, 27, 0 };
const opus_int16 mapping_matrix_fourthoa_mixing_data[729] = {
9243, 0, 16010, 0, 0, 0, 20669, 0,
0, 0, 0, 0, 24456, 0, 0, 0,
0, 0, 0, 0, 27731, 0, 0, 0,
0, 0, 0, 9243, 0, 10884, 11741, 0,
0, 3995, 17849, 9626, 0, 0, 0, -5727,
14399, 17315, 7625, 0, 0, 0, 0, -11747,
2574, 18637, 15552, 5930, 0, 0, 9243, -14302,
-2682, -6677, 13337, 5357, -9464, 2501, -11170, 4770,
-5911, 11501, 5858, 5369, 4951, 17901, -19071, -2397,
-9281, -9198, 7576, -4294, 7773, -8997, -3399, 0,
0, 9243, 9940, 11991, -3705, -5144, 16647, 7057,
-6206, -5941, -2698, -10194, 16781, -1788, -6256, -11772,
4935, 3912, -6062, -13039, 9446, -9758, -3521, -15058,
11089, 565, 0, 0, 9243, -15376, 3720, 2461,
-5285, -7989, -8660, 1278, -16087, 15811, -3249, 10500,
-7757, -1680, -9890, -8153, 10884, 11022, 2847, 12828,
5137, -2053, 8666, -5684, 14776, 0, 0, 9243,
-10577, 10304, -6186, 9139, -15222, 2507, -8902, -5140,
-145, 15562, -10596, -7311, -6197, -8753, 8667, -6014,
-281, 15033, 938, -11859, 548, -8456, 16735, -3654,
0, 0, 9243, 8974, 4839, -12343, -15472, 6066,
-7501, -8343, 5015, 15920, -12374, -4559, -9400, 6271,
4011, 5191, -9932, 14438, 4828, -8768, 1909, 12059,
-1565, 4707, -13711, 0, 0, 9243, 15799, 2085,
-1534, -3386, 4602, -9808, -447, -17267, -18054, -1167,
-13525, -4644, 1313, -5951, 5397, 7485, -7056, 2584,
-8120, 8669, 788, 13177, 2109, 18349, 0, 0,
9243, 12371, -10036, 1597, 2760, -17341, 1848, -2239,
-10509, -8474, -4577, 11164, 7935, 1441, 17430, -3436,
-3713, 15936, 4184, 2647, -11730, 341, -15934, 6462,
6581, 0, 0, 9243, -8963, 2184, 13084, -16381,
-2734, -9757, 3991, 6345, -18297, -5912, 7604, -4849,
-11100, 2290, -4304, -13305, -7488, 12338, 4805, 8505,
-7014, -4779, -1761, -14597, 0, 0, 9243, 1301,
-15498, 3799, 690, -2816, 18718, -8223, 889, 255,
-1768, 4485, -19951, 13097, -2278, 167, 78, -740,
3324, -6139, 19488, -17925, 4283, -486, 20, 0,
0, 9243, -13470, -6719, 5452, -10257, 12641, -4873,
-5116, -10595, 5856, 11389, 1502, 10876, -608, 11765,
-13218, 13911, -7373, -2070, -13679, -4154, 5536, -2138,
16643, 451, 0, 0, 9243, 2455, -3679, -15387,
-5277, -1261, -8697, 7906, 16112, 8147, 3208, -1690,
7687, 10593, -9796, -15852, -10884, -5616, 2881, 2032,
5246, -12735, -8796, 10928, 14833, 0, 0, 9243,
-6849, 2775, -14202, 13586, -2655, -9402, -5505, 10809,
-18013, 6231, 5444, -6041, 11288, 4958, -4078, 18799,
-9368, -9291, 4535, 7383, 9405, -7391, -2121, -4336,
0, 0, 9243, 6423, -9040, 11548, 10359, -8109,
-450, -14580, 6431, 10857, -15475, 3569, 9707, 6416,
-9607, 521, 8528, -18391, 11049, 3815, -10423, 6860,
6860, -883, -4221, 0, 0, 9243, 11932, -5968,
-8850, -14749, -9946, -6026, 7377, -4472, 5206, 14547,
-3406, 10508, 2526, 4411, 14543, 8444, -5822, 347,
12347, -1709, -9158, 105, -16265, -12642, 0, 0,
9243, 13044, -150, 9282, 16910, -274, -10332, -194,
-5864, 5428, -420, -12196, 344, -8679, 145, -18554,
-12695, -152, -14635, 503, 10389, 358, 5076, 522,
-16100, 0, 0, 9243, -8374, -13590, -1221, 1428,
15896, 12005, 2318, -4793, 2590, -3209, -20390, -6256,
-2974, 10766, 1202, -876, -6597, 5004, 19896, -1541,
2902, -16788, -3062, 1340, 0, 0, 9243, 9879,
10267, 7300, 10073, 14167, 2416, 10469, -3094, 2899,
17092, 9762, -7400, 7214, -5250, -8238, -3989, 5578,
16392, -1050, -11848, -776, -5034, -15850, -5882, 0,
0, 9243, -4974, -9068, 12221, -8490, 6299, -388,
-15478, 8702, -9920, 12723, -2810, 9668, 6905, -13040,
4325, -9456, 16856, -9159, -2909, -10476, 7149, 9387,
-7350, 233, 0, 0, 9243, 3627, -13823, -7218,
-3656, -7002, 12776, 13935, 2719, 2446, 8352, 9252,
-7676, -18413, -6212, -429, -1272, -6335, -13356, -9510,
295, 18926, 9934, 1112, -382, 0, 0, 9243,
-6383, -9343, -11326, 10097, 8329, 223, 14780, 6114,
-10348, -15590, -4195, 9257, -7445, -9439, -323, 7902,
18117, 12101, -3142, -10944, -5577, 7327, 566, -4133,
0, 0, 9243, 2626, 865, 15769, 5783, 317,
-10244, 1905, 16884, 9144, 826, -2420, -1972, -14536,
2413, 16939, 12500, 1482, -4906, -578, 10096, -3476,
-14323, 2745, 16105, 0, 0, 9243, -8975, 12086,
5450, -6832, -15149, 7333, 9200, -3550, -362, -13645,
-15525, -1391, 9428, -7091, -5442, 3105, -820, -17685,
-9175, -9462, 5572, -9191, -12325, -2180, 0, 0,
9243, -114, 11576, -11058, 177, -185, 5875, -17880,
8539, -198, 339, -173, -3411, -16698, 16336, -6369,
193, -430, 408, -75, -10806, -7225, 19670, -13817,
4665, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 32767, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
32767
};
const MappingMatrix mapping_matrix_fifthoa_mixing = { 38, 38, 0 };
const opus_int16 mapping_matrix_fifthoa_mixing_data[1444] = {
9243, 0, 16010, 0, 0, 0, 20669, 0,
0, 0, 0, 0, 24456, 0, 0, 0,
0, 0, 0, 0, 27731, 0, 0, 0,
0, 0, 0, 0, 0, 0, 30657, 0,
0, 0, 0, 0, 0, 0, 9243, 0,
-7023, 14387, 0, 0, -4369, -14112, 14455, 0,
0, 0, 10931, -510, -16777, 14031, 0, 0,
0, 0, -5118, 14286, 4343, -18465, 13374, 0,
0, 0, 0, 0, -6494, -12221, 11761, 8513,
-19458, 12605, 0, 0, 9243, -14128, 5093, 5547,
-10946, -10050, -7197, 3945, -11790, 7142, -9213, 6529,
-9701, -2563, -9923, -14846, 16521, 6816, 2764, 14103,
1118, -5537, 2977, -14168, 1228, 4866, 17430, -528,
10639, 2641, 10437, -1037, 11460, 1098, 1296, 15737,
0, 0, 9243, 1128, -14775, 6062, 955, -2329,
16069, -12511, 2477, 579, -2333, 3440, -14197, 18478,
-6050, 940, 303, -1604, 4106, -4223, 9829, -22688,
10647, -2604, 334, 145, -927, 3203, -6017, 4507,
-3812, 24212, -15600, 5198, -1023, 110, 0, 0,
9243, 1158, 12997, 9277, 1501, 2103, 10097, 16840,
5916, 1402, 3225, 2488, 2929, 19916, 12706, 3585,
1137, 3415, 4698, 2078, -5442, 16634, 18511, 8731,
2095, 850, 3061, 5733, 5225, 960, -11728, 7689,
20588, 14659, 5642, 1187, 0, 0, 9243, -4663,
-3081, -15003, 9771, 2007, -9185, 6457, 14199, -14357,
-4976, 3554, 6625, 11434, -7231, -11297, 17760, 8291,
-6267, -3368, 6712, -10837, -9107, 6524, 6793, -19531,
-11338, 7934, 7335, -2205, -9215, -7094, 10659, 6243,
-4337, -1250, 0, 0, 9243, -13515, 7679, -3831,
7232, -14496, -3201, -4109, -11731, 8828, 9178, -1901,
-10848, -539, -14888, 9626, -10860, 12703, 3824, 12334,
-7104, 3496, -6203, 13852, 5461, -2109, -17277, 7837,
-4714, 13901, 4097, 3940, 7647, 8546, 8688, -10986,
0, 0, 9243, 8113, -9860, 9657, 10943, -11174,
1426, -13300, 1915, 8178, -17833, 6805, 8309, 8100,
-3121, -4742, 2683, -15111, 15688, 2358, -11590, 2807,
2746, 8762, -7430, -2251, -5481, 16370, -4081, -9694,
5872, -11539, -714, -9492, 15177, -6126, 0, 0,
9243, 9933, -9215, -8528, -11831, -12785, -62, 10976,
-1811, 5593, 18018, 6100, 9455, -5237, 2758, 8971,
2743, -9659, -13517, 5330, -10737, -4576, -2069, -15491,
-8749, -7226, -5237, 9191, -181, -12277, 2815, 10540,
-27, 14741, 16703, 3103, 0, 0, 9243, -10067,
-8881, -8723, 12265, 12487, -793, 10821, -1762, -6021,
-18002, -5072, 9912, -4395, 2587, 9368, -2767, 10021,
12259, -6468, -10113, -5605, -1761, -15590, -9430, 7800,
5092, -8835, 2293, 12314, 1222, 10671, -329, 13745,
17349, 3563, 0, 0, 9243, -6485, 12991, -6743,
6108, -11768, 10080, -12236, 238, -2883, 13115, -13907,
2900, -14460, 511, 2564, 186, -7019, 19094, -11597,
-5472, -12058, 744, 6243, -2384, 930, 501, -11778,
21214, -5330, -11746, -5542, 827, 10475, -6418, 1132,
0, 0, 9243, 3862, 5238, -14627, -7891, 2826,
-7015, -10701, 13900, 11410, -6831, -1679, -9861, 6359,
12032, -11660, -14041, 11199, 1713, -3895, 657, 14749,
-3017, -11445, 8380, 15575, -15236, -346, 7690, -923,
10317, 3498, -13545, 354, 9093, -4476, 0, 0,
9243, -8417, 13183, 3418, -4018, -15498, 10685, 6294,
-4132, 1419, -8755, -18818, 3926, 7642, -9001, -3235,
2125, 3506, -13037, -16570, -4337, 6729, -13404, -7991,
59, 443, 5804, 6005, -15011, -9060, -11044, 3679,
-15434, -13685, 161, 1185, 0, 0, 9243, -5288,
6773, -13508, 9977, -5002, -4784, -12780, 10790, -12942,
11168, 519, -10890, 1326, 12078, -6274, 13780, -16427,
2186, 5352, -4328, 13671, 2364, -7963, 1080, -12568,
19336, -6557, -8574, 4084, 7277, 10433, -9273, -3178,
1516, 3817, 0, 0, 9243, 9660, 7817, 10093,
13619, 10548, -2942, 11021, 597, 9663, 17594, 1736,
-10794, 1814, 771, -8469, 1041, 14155, 7891, -8597,
-7498, -8982, 346, -12407, -11848, -6809, 1686, 9181,
-8306, -10247, 3538, -10706, -364, -8047, -19188, -8493,
0, 0, 9243, -7163, -1020, 14282, -14289, 1021,
-10208, -2036, 10660, -18919, 2410, 6564, 2323, -13088,
-1798, 3365, -19498, 3619, 12022, -1858, 9978, 3705,
-8969, -643, -5794, -15523, 4123, 15113, -3949, -6265,
-3596, 12490, 2946, -2688, 1225, -14570, 0, 0,
9243, -12187, 772, -10354, 17623, -1314, -10262, -1117,
-2885, -9937, 2249, 11267, -1763, 9572, -368, 16506,
-6510, -1438, -15014, 2402, 10157, 2041, 2458, 2389,
-19346, 19860, -1041, 8067, -3704, -10931, 2743, -9286,
606, -13399, -3095, 7924, 0, 0, 9243, 15545,
-2367, -3011, -6538, -5139, -9657, 995, -16242, -15706,
2557, -12952, 5226, 2508, 6353, 10156, 13593, 6966,
4795, 8960, 8183, -1735, 11914, -4504, 14149, 11727,
-6665, 10460, -3962, 10145, -7648, -1965, -9845, -6764,
-6938, -16633, 0, 0, 9243, 3098, 12983, -8841,
-3826, 5618, 10053, -16031, 4787, 3283, -8209, 6632,
2856, -18922, 10272, -2055, -2344, 7987, -11939, 5516,
-5520, -15739, 14940, -5001, 530, 1465, -6306, 13388,
-13243, 2513, -11772, -7170, 16572, -8384, 1426, 168,
0, 0, 9243, -15767, -2008, -1916, 4220, 4422,
-9846, 537, -17105, 17650, -1400, 13589, 4481, 1651,
5677, 6701, -9241, -6642, -3252, -7827, 8792, -951,
13182, -2522, 17586, -17005, 3845, -12562, 2213, -11472,
-6688, -1394, -8970, -4769, -7316, -11753, 0, 0,
9243, -13344, -3829, 7975, -14863, 7136, -8561, -4265,
-7992, -801, 9405, 8912, 7937, -5326, 5057, -17681,
15207, 575, 7717, -11360, 4847, 6789, 4150, 12686,
-10050, 16730, -12063, 322, -12920, -3313, -10267, 1980,
-6948, 7112, 7972, 8042, 0, 0, 9243, 7791,
-1021, 13949, 15180, -1111, -10208, -1989, 9348, 19199,
-2561, -7140, 2323, -12782, -1577, 817, 18164, -3673,
-12771, 2022, 9978, 3620, -7865, -156, -9155, 11924,
-3842, -15336, 4196, 6814, -3596, 12199, 2583, -652,
1936, -17637, 0, 0, 9243, -4810, -15144, -1958,
1315, 10175, 17406, 4142, -1348, 263, -3292, -15632,
-17046, -6363, 3374, 605, -227, -748, 5997, 20334,
14481, 8277, -6146, -1717, 5, 27, 712, 1542,
-9197, -23572, -10163, -9595, 9425, 3539, -17, -72,
0, 0, 9243, -7366, 8261, 11568, -11901, -8499,
-2079, 13347, 5556, -12049, -16247, -2282, -10529, 3584,
7585, -1577, -8464, -18652, -8902, 5913, -8688, -9287,
4156, -2442, -7089, -2993, -14485, -13949, 5422, 8459,
1638, -13285, -2531, -1826, -12132, -9456, 0, 0,
9243, 11716, 698, -10889, -17818, 1143, -10275, -1062,
-1305, 12057, -2057, -10855, -1595, 10088, -150, 15043,
2978, 1578, 15225, -2090, 10201, 1943, 1115, 1969,
-20211, -17636, 430, -9826, 3391, 10572, 2485, -9826,
248, -12259, -2924, 12131, 0, 0, 9243, 4361,
-4594, -14703, -8956, -2798, -7781, 9434, 13769, 12936,
6800, -2400, 9082, 8091, -10453, -11023, -15786, -11136,
3285, 4153, 2658, -14002, -5051, 9489, 7000, 17206,
15024, -2777, -8491, -42, -10626, 141, 13053, 2366,
-6662, -2231, 0, 0, 9243, -752, -11933, -10646,
1119, 1254, 6890, 17745, 7875, -1203, -2207, -1251,
2024, -17706, -15532, -5600, 1128, 2691, 2800, 683,
-9927, 9661, 19706, 12522, 3889, -978, -2789, -3992,
-2440, 206, 12695, 2921, -17173, -18575, -9616, -2657,
0, 0, 9243, 4791, -15001, -2887, -1931, -10037,
16885, 6048, -1020, 46, 4789, 15191, -15922, -9154,
2530, 823, 252, -130, -8608, -19335, 12613, 11651,
-4549, -2314, -172, -101, -784, 265, 12975, 21741,
-7551, -13101, 6856, 4710, 535, -46, 0, 0,
9243, -12153, -10395, 754, -1281, 17644, 2735, -1095,
-10274, 8359, 2200, -12593, 7083, 782, 17650, -1573,
1685, -16282, -2164, -530, -11878, 32, -17359, 3065,
6651, -5212, -3628, 19365, 965, 13180, 8243, -818,
7746, -3645, -14323, 1670, 0, 0, 9243, -6961,
-11198, 9081, -8829, 10887, 4833, -14202, 2374, -6524,
16339, -9417, 4737, 12284, -4394, -2691, -2683, 13690,
-18539, 2830, -11438, -3692, 4985, 5648, -4628, 514,
6225, -18409, 12672, 5311, 11170, -6928, -3407, -7595,
10737, -3977, 0, 0, 9243, 12099, -10405, 1294,
2187, -17582, 2760, -1880, -10105, -8058, -3760, 12583,
7058, 1346, 17376, -2667, -2829, 15710, 3705, 468,
-11880, 50, -17123, 5201, 6230, 4698, 6098, -18716,
-1665, -13088, 8285, -1400, 7696, -6196, -13429, 2770,
0, 0, 9243, 8602, 13392, 1722, 2070, 16090,
11359, 3222, -4960, -2638, 4581, 20106, 5099, 4026,
-10978, -1778, -1314, -6620, 6988, 18701, -2965, 3745,
-16745, -4461, 1300, 584, -3646, -11588, 8350, 11847,
-10050, 2372, -20010, -7809, 3608, 887, 0, 0,
9243, 14252, -1958, 7026, 13986, -3899, -9870, -1922,
-10736, -3693, -4527, -12333, 4376, -6080, 3475, -18537,
-19222, 1355, -10843, 6913, 8869, 3408, 8323, 6804,
-5141, -13648, 7800, 2649, 7171, 10505, -6548, 5179,
-5505, 13299, 2086, 15579, 0, 0, 9243, 11323,
9021, -6835, -10810, 14267, -489, -8613, -5689, 639,
-16117, 6224, -9731, -3757, -8482, 10882, 7873, 1080,
-11447, -6791, -10388, 4099, -6025, 18396, -5407, -7536,
14714, 984, 1267, -13940, -1889, 8416, 666, 16762,
-10106, -3418, 0, 0, 9243, 871, 4833, 15238,
1855, 588, -7508, 10287, 16162, 2857, 1481, -443,
-9392, -7758, 12910, 16506, 3837, 2588, -581, -851,
1928, -14879, -5066, 14950, 16498, 4773, 3842, -425,
-1785, -82, 10578, -1435, -15554, -2459, 16520, 16250,
0, 0, 9243, 14762, 5967, 1673, 3450, 12303,
-6027, 1394, -15022, -14571, 3402, -4217, -10507, -478,
-14813, -5131, -6634, -16293, -82, -15276, -1705, -1731,
358, -5738, 13681, 12503, -8200, -3023, -3290, -7384,
9272, -837, 14328, -1064, 16913, 7915, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 32767, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 32767
};
const MappingMatrix mapping_matrix_foa_demixing = { 6, 6, 0 };
const opus_int16 mapping_matrix_foa_demixing_data[36] = {
16384, 16384, 16384, 16384, 0, 0, 0, 23170,
0, -23170, 0, 0, -16384, 16384, -16384, 16384,
0, 0, 23170, 0, -23170, 0, 0, 0,
0, 0, 0, 0, 32767, 0, 0, 0,
0, 0, 0, 32767
};
const MappingMatrix mapping_matrix_soa_demixing = { 11, 11, 3050 };
const opus_int16 mapping_matrix_soa_demixing_data[121] = {
2771, 2771, 2771, 2771, 2771, 2771, 2771, 2771,
2771, 0, 0, 10033, 10033, -20066, 10033, 14189,
14189, -28378, 10033, -20066, 0, 0, 3393, 3393,
3393, -3393, 0, 0, 0, -3393, -3393, 0,
0, -17378, 17378, 0, -17378, -24576, 24576, 0,
17378, 0, 0, 0, -14189, 14189, 0, -14189,
-28378, 28378, 0, 14189, 0, 0, 0, 2399,
2399, -4799, -2399, 0, 0, 0, -2399, 4799,
0, 0, 1959, 1959, 1959, 1959, -3918, -3918,
-3918, 1959, 1959, 0, 0, -4156, 4156, 0,
4156, 0, 0, 0, -4156, 0, 0, 0,
8192, 8192, -16384, 8192, 16384, 16384, -32768, 8192,
-16384, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 8312, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
8312
};
const MappingMatrix mapping_matrix_toa_demixing = { 18, 18, 0 };
const opus_int16 mapping_matrix_toa_demixing_data[324] = {
8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192,
8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192,
0, 0, 0, -9779, 9779, 6263, 8857, 0,
6263, 13829, 9779, -13829, 0, -6263, 0, -8857,
-6263, -9779, 0, 0, -3413, 3413, 3413, -11359,
11359, 11359, -11359, -3413, 3413, -3413, -3413, -11359,
11359, 11359, -11359, 3413, 0, 0, 13829, 9779,
-9779, 6263, 0, 8857, -6263, 0, 9779, 0,
-13829, 6263, -8857, 0, -6263, -9779, 0, 0,
0, -15617, -15617, 6406, 0, 0, -6406, 0,
15617, 0, 0, -6406, 0, 0, 6406, 15617,
0, 0, 0, -5003, 5003, -10664, 15081, 0,
-10664, -7075, 5003, 7075, 0, 10664, 0, -15081,
10664, -5003, 0, 0, -8176, -8176, -8176, 8208,
8208, 8208, 8208, -8176, -8176, -8176, -8176, 8208,
8208, 8208, 8208, -8176, 0, 0, -7075, 5003,
-5003, -10664, 0, 15081, 10664, 0, 5003, 0,
7075, -10664, -15081, 0, 10664, -5003, 0, 0,
15617, 0, 0, 0, -6406, 6406, 0, -15617,
0, -15617, 15617, 0, 6406, -6406, 0, 0,
0, 0, 0, -11393, 11393, 2993, -4233, 0,
2993, -16112, 11393, 16112, 0, -2993, 0, 4233,
-2993, -11393, 0, 0, 0, -9974, -9974, -13617,
0, 0, 13617, 0, 9974, 0, 0, 13617,
0, 0, -13617, 9974, 0, 0, 0, 5579,
-5579, 10185, 14403, 0, 10185, -7890, -5579, 7890,
0, -10185, 0, -14403, -10185, 5579, 0, 0,
11826, -11826, -11826, -901, 901, 901, -901, 11826,
-11826, 11826, 11826, -901, 901, 901, -901, -11826,
0, 0, -7890, -5579, 5579, 10185, 0, 14403,
-10185, 0, -5579, 0, 7890, 10185, -14403, 0,
-10185, 5579, 0, 0, -9974, 0, 0, 0,
-13617, 13617, 0, 9974, 0, 9974, -9974, 0,
13617, -13617, 0, 0, 0, 0, 16112, -11393,
11393, -2993, 0, 4233, 2993, 0, -11393, 0,
-16112, -2993, -4233, 0, 2993, 11393, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
32767, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 32767
};
const MappingMatrix mapping_matrix_fourthoa_demixing = { 27, 27, 0 };
const opus_int16 mapping_matrix_fourthoa_demixing_data[729] = {
4870, 4484, 4870, 4347, 4440, 4726, 4683, 4821,
4883, 4842, 4603, 4484, 4683, 4698, 4234, 4368,
4603, 4783, 4783, 4820, 4821, 4347, 4820, 4440,
4698, 0, 0, 101, 84, -7818, 4640, -7178,
-5492, 4629, 8384, 6547, -4966, 617, -6345, 1061,
-3241, 2939, 5549, 6390, -4434, 4994, -2610, 1993,
-2873, 1547, -4356, -164, 0, 0, 8797, 5074,
-1553, 5383, 1906, 5297, 2722, 1158, -5226, 1311,
-7760, -3327, -1940, 1586, -4093, -2951, -214, -6873,
5450, -4875, -7193, -4438, 558, 5593, 5607, 0,
0, -26, 5761, -3723, -1460, 1195, -3065, -6357,
-1175, 608, 6965, 2310, 2759, -8023, -7138, 5162,
-3624, 5006, -809, 3592, 6209, -4159, -4968, 8150,
2513, -5702, 0, 0, 301, 109, 7161, -2462,
-2443, 5044, -7125, -2256, 1967, -9107, 259, -4928,
-2592, 6514, 4111, -7236, 8695, 635, 5009, -4025,
-1937, 4794, 3420, -3507, -400, 0, 0, -134,
85, 2771, 7842, -3649, -8225, 2866, 2586, -9200,
-1945, -1563, 6155, -720, -1061, -3494, -4513, -487,
8389, 7317, 3348, -3721, 3806, 371, -6896, 70,
0, 0, 10919, 2072, -4867, 3472, -4429, 1721,
-4066, -5193, 1032, -5253, 9501, -2017, -3971, -5261,
-306, -2737, -5137, 5713, 1237, -8, 6387, 364,
-5423, 3364, 2888, 0, 0, -48, 8946, 1048,
-2691, 602, -4332, -4302, -514, -1730, 2459, -4328,
-2156, 3335, -2748, -6029, 4023, 155, 897, 5268,
-8380, 7625, 7395, 508, 3945, -8951, 0, 0,
39, 4151, -5965, -3398, -7006, -3534, 2697, -8989,
-5237, 2913, 46, -5540, 8196, 5766, 2711, -2520,
-3043, -2146, -948, 4965, 1806, 2472, 8988, -1266,
4840, 0, 0, -407, -189, 2179, -1627, 6516,
259, 7196, -9449, -4905, -9766, 561, 4021, 3371,
-8650, 5032, 3329, 2534, 641, 2224, -5747, 1047,
-4074, 5252, -24, 674, 0, 0, 664, 237,
-2837, -4072, -1205, 8252, -5875, -1670, -2743, -3984,
381, 5059, 1765, 2666, -8295, 7403, 1154, -2086,
7622, 7105, 3677, -6943, 1050, -6632, -694, 0,
0, 382, -133, 5699, 7650, 5154, -5713, -1645,
-6902, 6181, 4450, 1151, 410, -993, 3829, 2444,
-2405, -6618, -9514, 5366, -1896, 5844, -2886, -1524,
-7321, -1007, 0, 0, 12767, -2530, 3183, -1409,
-4015, -2894, -5155, -1710, 3841, -2107, -10274, 5119,
3979, -4010, 5550, 4822, -746, -2507, -3080, 4289,
-3675, 4333, -1416, -1230, -1122, 0, 0, 17,
8048, 2398, -2167, -73, -3606, 3125, 398, 731,
-5973, 5705, -1032, 4679, 7305, 3134, 1301, -3858,
-89, 2938, 4359, -9155, -4805, -8407, 3673, -8645,
0, 0, 187, 7355, 3145, -6719, -4432, -5939,
2541, -2810, 9723, 778, -1105, 5687, -4174, 2534,
-4461, 1017, -244, 5481, -1655, -6765, -3350, -4894,
1592, -2318, 8827, 0, 0, 196, 3588, 9631,
3063, -4564, 6043, 2683, 2595, -2488, -2186, 173,
-6059, -8270, -2386, 409, 7441, -8608, 376, -4364,
2321, -280, 97, 8331, -3022, -4721, 0, 0,
117, -748, -10833, 1533, 4200, -2875, -997, -109,
-3661, -6119, 4454, 8808, -9189, 8294, 1521, 7265,
-2348, -5094, -948, -5400, -3193, 8914, 5763, 1716,
-1070, 0, 0, 2497, 399, -5201, -2038, 7843,
-376, 7567, -5073, 7616, -5537, 2086, -3453, -5544,
-56, -11648, -1314, 3546, -3432, -117, 8694, -4245,
9621, 3098, -2582, -2351, 0, 0, 4386, -3104,
-3132, -10512, 566, 5217, 5128, 4967, 1348, 7035,
-1470, 91, -125, -3548, 8244, -3029, -10033, 2186,
9745, -6440, -2074, 3638, -1477, -7045, -562, 0,
0, 2154, 8116, -6102, 6570, 12998, -712, -4126,
-4996, 30, 1571, -6393, -12794, 425, 5036, 1190,
5763, 5653, 12933, -6671, 5197, -2964, -3316, -6354,
-10554, -2652, 0, 0, 12618, -3737, 93, -5901,
4262, -3364, 4444, 3103, -2767, 3403, 4925, -2584,
-989, 4977, -3714, -1965, 3076, 326, -2946, -2568,
1026, -2980, 3362, -6132, -5966, 0, 0, 6001,
48, -1979, -7275, 3476, -2096, 10591, 3793, 2629,
-447, -14747, -3689, -5525, 8358, 6883, -9703, -4556,
7471, 2965, 4056, 13221, -7327, -3073, -2353, -6720,
0, 0, 621, 11034, -44, -2828, 5978, -1850,
-1772, 3894, -7471, -1397, 945, -2028, -2928, -2240,
3172, 2222, 4544, -4243, -5645, 3745, 2573, 3511,
-8206, -7286, 5700, 0, 0, 321, 10818, -4982,
7813, -749, 9907, 1360, -1443, 568, -1103, 2305,
6045, 2270, -1063, -1920, -3073, 5893, -3476, -11346,
-1657, -588, 2957, -2287, -8527, -8041, 0, 0,
119, -268, 2372, -3040, 4979, -3789, -5630, 10619,
5900, -5109, -4585, -3862, 10467, -3527, -385, -10034,
-9991, 4860, 984, 2362, 2311, -6804, 6324, 433,
5291, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 32767, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
32767
};
const MappingMatrix mapping_matrix_fifthoa_demixing = { 38, 38, 0 };
const opus_int16 mapping_matrix_fifthoa_demixing_data[1444] = {
3188, 3247, 3268, 3368, 3368, 3138, 3268, 3099,
3211, 3368, 3099, 3247, 3211, 3368, 3368, 3368,
3149, 3268, 3247, 3211, 3099, 3188, 3138, 3149,
3099, 3188, 3368, 3149, 3188, 3247, 3268, 3138,
3211, 3368, 3138, 3149, 0, 0, 118, -47,
-5011, 282, 333, -1497, -4584, 2908, 3388, -3647,
-2493, 1139, -2882, -1719, 3604, -2543, -4328, 5443,
1286, -5498, -4583, 2510, -1743, -2556, 4168, 1446,
-290, 1812, -4074, -2377, 4152, 2847, 4991, 3980,
393, 5072, 0, 0, 5489, -2235, 1507, -5326,
4609, -1096, 2926, -3427, -3301, -3078, 4226, 1730,
4627, 2561, 2966, -592, 143, -677, 4617, -755,
-956, -433, -5138, 3037, 157, -1394, -4498, -4984,
-3661, -4112, -3756, 4628, -570, 3356, 1605, 1803,
0, 0, -162, 5162, 2132, 2392, 3556, -5141,
-1536, 2975, -3001, -3350, -2231, -5230, 1294, -4965,
3494, 5230, -3292, -1359, -2945, -773, 2670, 4867,
-660, 3720, -3415, -5112, -3700, -1211, 407, 3013,
763, 591, 2481, -2657, 5210, 784, 0, 0,
-156, 338, -4246, 510, 462, 3296, 2846, 3333,
-4292, 4574, 1940, -2986, -1275, 3701, 5022, -5250,
5780, -2676, -1180, 1516, -4852, 4877, 342, -3923,
-5703, -2920, 379, -657, -361, -3346, 1044, 795,
5257, -4004, 698, 1115, 0, 0, 47, -140,
-3292, -1097, 652, 855, -5260, -3691, -4470, 4521,
-3863, 1093, -5552, -2016, 3831, 334, -456, -1532,
2068, 1788, 2054, -295, 3668, -2820, 328, -994,
295, -3301, 5770, 4282, -6353, 5632, -1371, 5005,
238, 4041, 0, 0, 6764, -1659, -2730, 5726,
3715, -3216, -933, 531, -52, -345, 3022, -2818,
4005, -1617, -1189, -3748, -3403, -3592, 4040, -3553,
-2806, -3444, 6023, -711, -3298, -2503, 2548, 5564,
940, 1848, 1207, 4010, -3488, -358, -2511, -1966,
0, 0, -64, -5039, 1403, -4455, 6240, 2189,
-1716, -4348, 4183, 3951, -4042, -3606, 2399, -4563,
4050, -612, -395, 348, -5791, 391, -1440, -735,
1398, 4359, -518, 2969, 6556, 1951, -518, -4993,
-925, 998, -569, -2934, 3460, 420, 0, 0,
16, 5482, -4122, 770, 2082, 5020, -3961, 485,
-584, -793, 3, 5222, -1416, 3673, 78, 3549,
-937, -5723, 1673, -6162, -2540, 3082, -355, 1838,
-615, 4601, 2832, -359, -3346, 668, -3393, -1583,
-3774, -2206, 5754, -4961, 0, 0, -328, 299,
2470, 317, 525, -4494, 2805, 2617, 2383, -2363,
-1037, 4085, 895, -4622, 3218, -6607, -3381, -5933,
1397, 6394, -446, 5694, 14, -4510, 4329, 3690,
-334, 0, 2932, -2478, -2944, -577, -599, -230,
1553, -4736, 0, 0, -324, 142, -3252, -867,
1111, -1882, 3378, -6055, 6502, -6840, 4280, -2694,
-2876, 4190, 6454, 655, 1061, 626, -2669, -798,
3192, -985, -898, -5482, -548, 2315, -558, 1302,
900, 5747, -1325, 1599, -1384, -5749, 624, 1110,
0, 0, 321, 312, 2188, 1322, 237, 708,
-304, 2463, 1500, -1094, -5112, -1010, -6799, 646,
992, 1969, 3423, -3996, 2628, 4451, 3432, -2833,
-6101, -330, -3768, -3, -707, 5961, -4037, -3736,
4080, 7254, -4113, 2151, 54, -2150, 0, 0,
7735, 4064, -3884, -5240, 577, 2229, -3947, 2914,
3555, 4011, 774, -3519, 1985, -3701, -3824, 330,
-905, 2085, 1155, 2176, 3006, 340, -5533, -3264,
-902, 3114, 344, -5060, 1524, 1805, 1926, 2350,
1905, -3203, -2762, -4162, 0, 0, 193, -151,
-1434, 6289, 7354, 4234, 169, 2868, -1977, -1375,
-4987, 2345, 2742, 599, 939, -4837, 2688, 991,
-6907, 716, -1542, -4346, -1833, 1493, 3134, 2903,
-7019, -2835, 93, 4395, 621, 870, -2357, -975,
-2933, -127, 0, 0, -616, -5968, -3479, -1651,
4932, -2445, -5512, -1451, 691, 739, 479, 4227,
-2886, 3853, 8, -501, 188, 1990, 3842, 2270,
1662, -174, 1290, 2456, 67, -3267, -5535, 483,
5721, -1642, 6501, -3432, 1184, -3246, 4101, -4880,
0, 0, -465, 5264, -4812, 682, 1683, -4539,
2916, -1985, 2899, 3324, 1060, -4398, -745, -2137,
-3827, 1044, 6225, 3609, -532, 1980, -6001, 564,
-209, -1299, 5336, -3605, -1484, 37, 19, -1295,
-665, -385, -6773, 3651, 6153, -1291, 0, 0,
193, -415, 5166, -110, 626, 6743, -2860, 1425,
1101, -1341, 80, -4533, 249, 4231, -119, -6009,
-2970, 5170, -822, -2610, 4527, 5948, 182, -2589,
837, -5471, 371, -43, 373, -665, -1233, -626,
-7353, 2606, 1339, -1398, 0, 0, -533, 147,
2075, -672, 1043, 3503, 4402, -4971, -3287, 3731,
-2606, 3817, 1972, -5603, 5114, 1185, -1318, 1906,
3018, -1999, 343, -1943, 207, -6744, 913, -4060,
645, -349, -5667, 4766, 5575, -1733, 1116, 160,
1534, -5690, 0, 0, -137, -36, 1556, 1325,
1553, -2230, 1188, 5296, -5104, 4673, 6295, 498,
-4723, 933, 2994, 4067, -4700, 1758, -4116, -1252,
2444, -4092, 1653, -2802, 5069, 1133, 790, -2355,
-934, -6304, 1642, 2045, -4259, -3873, -213, 215,
0, 0, -364, 423, 4888, -1316, 118, -950,
4027, 114, 2961, -3136, -3012, -883, -6192, 1340,
-3210, -1193, 1376, 3128, 1596, -2994, -3194, 533,
8502, 2487, -1485, 1032, 301, -8007, -577, 887,
297, 7778, 3121, -1901, -94, -6401, 0, 0,
9260, -1845, 668, 2787, -2255, 2699, -2512, -3737,
-3675, -3601, -1803, 210, -1701, -1442, -2700, 3457,
2868, 2079, -2113, 3178, 1277, 3578, 5240, -2482,
3324, 1020, -4027, 3835, -3758, -3633, -3170, -1310,
2509, -3110, 713, 174, 0, 0, -399, 4969,
-2321, -7744, 6494, -3776, 1478, 758, -1794, -2233,
-4059, 4932, 2770, 4761, -3475, 1243, 829, -651,
-5358, -436, 2381, 1360, 2561, -3118, 858, -4366,
3933, 3646, -43, -1310, -16, 924, 1197, 1415,
-5036, -376, 0, 0, 100, 1410, 1290, 3199,
7091, -3638, -2641, 1118, 45, -441, 794, -974,
-5033, 889, 438, -3102, 895, 3555, 4672, 4795,
1129, -2408, -2153, 1742, 159, -2040, 7578, -2006,
-5737, 1986, -5568, -6413, 2428, -1387, -2441, 667,
0, 0, -37, -6031, -4434, -904, 3290, 1806,
4736, 2516, -5905, -5927, 1754, -4300, -2468, -2203,
-4836, -672, 1444, -1591, -1631, -1789, 4311, -153,
-688, -1222, 1058, 3139, 4659, -353, 1543, 1838,
2180, -1448, 2432, 6277, 5304, -1692, 0, 0,
-280, 4506, 807, -477, 823, 3550, 1427, -1856,
-3003, -3501, -1203, 2679, 933, 778, -4954, -1977,
-7458, 4687, 435, 7045, -4053, -3130, 257, -3917,
-6165, 1889, 927, 235, 1889, -1097, 1985, 630,
-2172, -2130, 7080, 4810, 0, 0, -300, 496,
2808, 279, 667, -7179, -2661, -526, -2832, 1751,
2849, 4829, -906, -4151, -1124, -3062, 8166, 5361,
-1656, -6017, 3265, 2551, -864, -432, -6966, 6295,
-168, 901, 442, -582, 269, 236, -3574, 799,
472, 565, 0, 0, 805, -2466, 6208, -4592,
-170, -6701, -5610, 3678, -4242, 4561, -724, -5534,
2415, 7354, 2761, 2699, -349, 3822, -2372, 1756,
-5523, -3445, -588, -5749, -3986, 9804, -3871, 5375,
-2308, 5504, -2766, -1651, 1472, 6832, 2705, -5104,
0, 0, -700, -1179, 4402, 400, 1383, 939,
-1342, 6013, 2577, -3472, 472, 2883, 1450, -3917,
2849, 5084, 4990, 5392, 342, -4925, -3329, -5372,
-2674, -6035, -5072, -836, 179, 2506, 7987, -3647,
-8202, -1437, 1891, 2400, 1607, -3611, 0, 0,
-4706, -4003, 9928, -379, 5557, 3738, -8789, 685,
1937, -5157, 13388, 7995, -4119, -9909, -5079, 4804,
5586, 774, -5430, 299, -9943, 3264, -3690, -3901,
-1133, -6199, 3182, 1544, 5467, 3686, -2639, 4068,
1163, -185, -1299, -506, 0, 0, 843, 1005,
-1059, 467, -1279, -2259, 6057, -1694, -5885, 5342,
-5160, -3748, -1382, 4420, -697, -2000, -3808, 3100,
2685, -4073, 531, 318, -7822, 2414, 2901, 3399,
-1340, 8449, 3685, 463, -3341, 2423, 2304, -2723,
84, -2622, 0, 0, 12088, -265, 2562, -435,
-4348, -2426, 3538, 1552, 1279, 883, -4166, 2634,
-6130, 2994, 3729, -1570, -601, -1753, -5124, -2788,
-2096, -1920, -2649, 2793, -1079, -1952, 2983, -1530,
2499, 1769, 1492, -6757, -2108, 2841, 1466, 2597,
0, 0, -3830, -4093, 2448, 12720, 7737, -665,
-832, -9257, 2971, -2400, 791, 1873, 1072, -587,
-7440, 8055, 1531, -4736, 616, -1782, -2982, 9663,
-5057, -5926, 1610, -4489, 7033, -8658, 6010, -5673,
5648, 812, -271, -1802, -4500, 4392, 0, 0,
-888, -327, 3373, -1084, 7959, 2430, 1898, -2360,
-1820, -1377, -1090, -4436, -3422, -1106, -3230, 3876,
-41, -5128, 6375, -1848, -3824, 5844, 617, -1957,
4232, 1345, -1439, -83, 3046, -214, 5458, -5566,
-4387, -3738, -5740, 8657, 0, 0, 6978, 6239,
-3686, -981, -2854, 78, 5859, -357, 4618, 7391,
-138, 971, -5799, 2135, 4478, -7004, -5949, 1668,
-6933, -1163, 7010, -5624, 2990, 6192, -8075, 3567,
-8308, 2236, -5098, -2120, -4355, -4238, 4955, 10230,
692, -5606, 0, 0, -1348, -7069, -12, -4927,
1211, 651, 1360, 7744, 3404, 5069, -2438, -105,
2332, 1494, -4686, 1336, -3628, -881, 2474, 1736,
-26, -257, 2135, -4452, 446, -641, -4704, 2605,
-6436, 6662, -4939, 990, -1100, -3782, 5028, 4753,
0, 0, -2875, 6410, 3518, 3950, 1271, 869,
-2842, -5837, 1532, -2899, 1140, -597, 1712, -1988,
-4819, -4783, 4773, -8796, 2240, -4596, 3565, -4853,
-556, -3974, 7366, -4370, 3113, -3548, 3552, -5450,
3869, 2514, 6736, -4570, 6074, 3151, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 32767, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 32767
};
+157
View File
@@ -0,0 +1,157 @@
/* Copyright (c) 2017 Google Inc.
Written by Andrew Allen */
/*
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @file mapping_matrix.h
* @brief Opus reference implementation mapping matrix API
*/
#ifndef MAPPING_MATRIX_H
#define MAPPING_MATRIX_H
#include "opus_types.h"
#include "opus_projection.h"
typedef struct MappingMatrix
{
int rows; /* number of channels outputted from matrix. */
int cols; /* number of channels inputted to matrix. */
int gain; /* in dB. S7.8-format. */
/* Matrix cell data goes here using col-wise ordering. */
} MappingMatrix;
opus_int32 mapping_matrix_get_size(int rows, int cols);
opus_int16 *mapping_matrix_get_data(const MappingMatrix *matrix);
void mapping_matrix_init(
MappingMatrix * const matrix,
int rows,
int cols,
int gain,
const opus_int16 *data,
opus_int32 data_size
);
#ifndef DISABLE_FLOAT_API
void mapping_matrix_multiply_channel_in_float(
const MappingMatrix *matrix,
const float *input,
int input_rows,
opus_res *output,
int output_row,
int output_rows,
int frame_size
);
void mapping_matrix_multiply_channel_out_float(
const MappingMatrix *matrix,
const opus_res *input,
int input_row,
int input_rows,
float *output,
int output_rows,
int frame_size
);
#endif /* DISABLE_FLOAT_API */
void mapping_matrix_multiply_channel_in_short(
const MappingMatrix *matrix,
const opus_int16 *input,
int input_rows,
opus_res *output,
int output_row,
int output_rows,
int frame_size
);
void mapping_matrix_multiply_channel_out_short(
const MappingMatrix *matrix,
const opus_res *input,
int input_row,
int input_rows,
opus_int16 *output,
int output_rows,
int frame_size
);
void mapping_matrix_multiply_channel_in_int24(
const MappingMatrix *matrix,
const opus_int32 *input,
int input_rows,
opus_res *output,
int output_row,
int output_rows,
int frame_size
);
void mapping_matrix_multiply_channel_out_int24(
const MappingMatrix *matrix,
const opus_res *input,
int input_row,
int input_rows,
opus_int32 *output,
int output_rows,
int frame_size
);
/* Pre-computed mixing and demixing matrices for 1st to 3rd-order ambisonics.
* foa: first-order ambisonics
* soa: second-order ambisonics
* toa: third-order ambisonics
*/
extern const MappingMatrix mapping_matrix_foa_mixing;
extern const opus_int16 mapping_matrix_foa_mixing_data[36];
extern const MappingMatrix mapping_matrix_soa_mixing;
extern const opus_int16 mapping_matrix_soa_mixing_data[121];
extern const MappingMatrix mapping_matrix_toa_mixing;
extern const opus_int16 mapping_matrix_toa_mixing_data[324];
extern const MappingMatrix mapping_matrix_fourthoa_mixing;
extern const opus_int16 mapping_matrix_fourthoa_mixing_data[729];
extern const MappingMatrix mapping_matrix_fifthoa_mixing;
extern const opus_int16 mapping_matrix_fifthoa_mixing_data[1444];
extern const MappingMatrix mapping_matrix_foa_demixing;
extern const opus_int16 mapping_matrix_foa_demixing_data[36];
extern const MappingMatrix mapping_matrix_soa_demixing;
extern const opus_int16 mapping_matrix_soa_demixing_data[121];
extern const MappingMatrix mapping_matrix_toa_demixing;
extern const opus_int16 mapping_matrix_toa_demixing_data[324];
extern const MappingMatrix mapping_matrix_fourthoa_demixing;
extern const opus_int16 mapping_matrix_fourthoa_demixing_data[729];
extern const MappingMatrix mapping_matrix_fifthoa_demixing;
extern const opus_int16 mapping_matrix_fifthoa_demixing_data[1444];
#endif /* MAPPING_MATRIX_H */
+131
View File
@@ -0,0 +1,131 @@
/* Copyright (c) 2008-2011 Octasic Inc.
2012-2017 Jean-Marc Valin */
/*
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <math.h>
#include "opus_types.h"
#include "opus_defines.h"
#include "arch.h"
#include "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 "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_ */
+671
View File
@@ -0,0 +1,671 @@
/*This file is automatically generated from a Keras model*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "mlp.h"
static const opus_int8 layer0_weights[800] = {
-30, -9, 2, -12, 5, -1, 8, 9,
9, 8, -13, 18, -17, -34, -5, 17,
-11, 0, -4, 10, 2, 10, 15, -8,
2, -1, 0, 5, 13, -3, -16, 1,
-5, 3, 7, -28, -13, 6, 36, -3,
19, -60, -17, -28, 7, -11, -30, -7,
2, -42, -21, -3, 6, -22, 33, -9,
7, -30, 21, -14, 24, -11, -20, -18,
-5, -12, 12, -49, -50, -49, 16, 9,
-37, -1, 9, 34, -13, -31, -31, 12,
16, 44, -42, 2, -9, 8, -18, -6,
9, 36, 19, 11, 13, 12, -21, 3,
-28, -12, 3, 33, 25, -14, 11, 1,
-94, -39, 18, -12, -11, -15, -7, 49,
52, 10, -43, 9, 57, 8, 21, -6,
14, -15, 44, -8, 7, -30, -13, -2,
-9, 25, -2, -127, 18, -11, -52, 26,
-27, 27, 10, -10, 7, 43, 6, -24,
41, 10, -18, -27, 10, 17, 9, 10,
-17, -10, 20, -6, 22, 55, 35, -80,
36, 25, -24, -36, 15, 9, -19, 88,
19, 64, -51, -35, 17, 0, -7, 41,
-16, 27, 4, 15, -1, 18, -16, 47,
-39, -54, -8, 13, -25, -20, 102, -18,
-5, 44, 11, -28, 71, 2, -51, -5,
5, 2, -83, -9, -29, 8, 21, -53,
58, -37, -7, 13, 38, 9, 34, -1,
-41, 21, 4, -24, -36, -33, -21, 32,
75, -2, 1, -68, -1, 47, -29, 32,
20, 12, -65, -87, 5, 16, -12, 24,
40, 15, 7, 19, -26, -17, 17, 6,
-2, -37, -30, -9, 32, -127, -39, 0,
-31, -27, 4, -22, 23, -6, -77, 35,
-61, 32, -37, -24, 13, -11, -1, -40,
-3, 17, -7, 13, 11, 59, -19, 10,
6, -18, 0, 13, 3, -6, -23, 19,
11, -17, 13, -1, -80, 40, -53, 69,
-29, -54, 0, -4, 33, -25, -2, 38,
35, 36, -15, 46, 2, -13, -16, -8,
-8, 12, -24, -9, -55, -5, -9, 32,
11, 7, 12, -18, -10, -86, -38, 54,
37, -25, 18, -43, 7, -27, -27, -54,
13, 9, 22, 70, 6, 35, -7, 23,
-15, -44, -6, 7, -66, -85, 32, 40,
-19, -9, -7, 12, -15, 7, 2, 6,
-35, 11, 28, 0, 26, 14, 1, 1,
4, 12, 18, 35, 22, -18, -3, 14,
-1, 7, 14, -8, -14, -3, 4, -3,
-19, -7, -1, -25, -27, 25, -26, -2,
33, -22, -27, -25, 4, -9, 7, 21,
26, -30, 10, -9, -20, 11, 27, 10,
5, -18, 14, -4, 2, -17, -5, -7,
-9, -13, 15, 29, 1, -10, -16, -10,
35, 36, -7, -22, -44, 17, 30, 22,
21, -1, 22, -11, 32, -8, -7, 5,
-10, 5, 30, -20, 29, -20, -34, 12,
-4, -6, 6, -13, 10, -5, -68, -1,
24, 9, 19, -24, -64, 31, 19, 27,
-26, 75, -45, 41, 39, -42, 8, 6,
23, -30, 16, -25, 30, 34, 8, -38,
-3, 18, 16, -31, 22, -4, -9, 1,
20, 9, 38, -32, 0, -45, 0, -6,
-13, 11, -25, -32, -22, 31, -24, -11,
-11, -4, -4, 20, -34, 22, 20, 9,
-25, 27, -5, 28, -29, 29, 6, 21,
-6, -18, 54, 4, -46, 23, 21, -14,
-31, 36, -41, -24, 4, 22, 10, 11,
7, 36, -32, -13, -52, -17, 24, 28,
-37, -36, -1, 24, 9, -38, 35, 48,
18, 2, -1, 45, 10, 39, 24, -38,
13, 8, -16, 8, 25, 11, 7, -29,
-11, 7, 20, -30, -38, -45, 14, -18,
-28, -9, 65, 61, 22, -53, -38, -16,
36, 46, 20, -39, 32, -61, -6, -6,
-36, -33, -18, -28, 56, 101, 45, 11,
-28, -23, -29, -61, 20, -47, 2, 48,
27, -17, 1, 40, 1, 3, -51, 15,
35, 28, 22, 35, 53, -61, -29, 12,
-6, -21, 10, 3, -20, 2, -25, 1,
-6, 31, 11, -3, 1, -10, -52, 6,
126, -105, 122, 127, -128, 127, 127, -128,
127, 108, 12, 127, 48, -128, -36, -128,
127, 127, -128, -128, 127, 89, -128, 127,
-128, -128, -128, 127, 127, -128, -128, -93,
-82, 20, 125, 65, -82, 127, 38, -74,
81, 88, -88, 79, 51, -47, -111, -26,
14, 83, -88, -112, 24, 35, -101, 98,
-99, -48, -45, 46, 83, -60, -79, 45,
-20, -41, 9, 4, 52, 54, 93, -10,
4, 13, 3, 123, 6, 94, -111, -69,
-14, -31, 10, 12, 53, -79, -11, -21,
-2, -44, -72, 92, 65, -57, 56, -38,
127, -56, -128, 127, 127, -128, 86, 117,
-75, -128, 127, -19, -99, -112, 127, -128,
127, -48, 114, 118, -128, -128, 117, -17,
-6, 121, -128, 127, -128, 82, 54, -106,
127, 127, -33, 100, -39, -23, 18, -78,
-34, -29, -1, -30, 127, -26, 127, -128,
126, -128, 27, -23, -79, -120, -127, 127,
72, 66, 29, 7, -66, -56, -117, -128
};
static const opus_int8 layer0_bias[32] = {
51, -16, 1, 13, -5, -6, -16, -7,
11, -6, 106, 26, 28, -14, 21, -29,
7, 18, -18, -17, 21, -17, -9, 20,
-25, -3, -34, 48, 11, -13, -31, -20
};
static const opus_int8 layer1_weights[2304] = {
22, -1, -7, 7, 29, -27, -31, -17,
-13, 33, 44, -8, 11, 33, 24, 78,
15, 19, 30, -2, -24, 5, 49, 5,
36, 29, -14, -11, -48, -33, 21, -42,
-38, -12, 55, -37, 54, -8, 1, 36,
17, 0, 51, 31, 59, 7, -12, 53,
4, 32, -14, 48, 5, -10, -16, -8,
1, -16, -56, -24, -6, 18, -2, 23,
6, 46, -6, -10, 20, 35, -44, -15,
-49, 36, 16, 5, -7, -79, -67, 12,
70, -3, -79, -54, -85, -24, 47, -22,
33, 21, 69, -1, 11, 22, 14, -16,
-16, -22, -28, -11, 11, -41, 31, -26,
-33, -19, -4, 27, 32, -50, 5, -10,
-38, -22, -8, 35, -31, 1, -41, -15,
-11, 44, 28, -17, -41, -23, 17, 2,
-23, -26, -13, -13, -17, 6, 14, -31,
-25, 9, -19, 39, -8, 4, 31, -1,
-45, -11, -28, -92, -46, -15, 21, 118,
-22, 45, -51, 11, -20, -20, -15, 13,
-21, -97, -29, -32, -23, -42, 94, 1,
23, -8, 63, -3, -46, 19, -26, 32,
-40, -74, -26, 26, -4, -13, 30, -20,
-30, -25, -14, -31, -45, -43, 4, -60,
-48, -12, -34, 2, 2, 3, 13, 15,
11, 16, 5, 46, -9, -55, -16, -57,
29, 14, 38, -50, -2, -44, -11, -8,
52, -27, -38, -7, 20, 47, 17, -59,
0, 47, 46, -63, 35, -17, 19, 33,
68, -19, 2, 15, -16, 28, -16, -103,
26, -35, 47, -39, -60, 30, 31, -23,
-52, -13, 116, 47, -25, 30, 40, 30,
-22, 2, 12, -27, -18, 31, -10, 27,
-8, -66, 12, 14, 4, -26, -28, -13,
3, 13, -26, -51, 37, 5, 2, -21,
47, 3, 13, 25, -41, -27, -8, -4,
5, -76, -33, 28, 10, 9, -46, -74,
19, 28, 25, 31, 54, -55, 68, 38,
-24, -32, 2, 4, 68, 11, -1, 99,
5, 16, -2, -74, 40, 26, -26, 33,
31, -1, -68, 14, -6, 25, 9, 29,
60, 61, 7, -7, 0, -24, 7, 77,
4, -1, 16, -7, 13, -15, -19, 28,
-31, -24, -16, 37, 24, 13, 30, 10,
-30, 11, 11, -10, 22, 60, 28, 45,
-3, -40, -62, -5, -102, 9, -32, -27,
-54, 21, 15, -5, 37, -43, -11, 37,
-19, 47, -64, -128, -27, -114, 21, -66,
59, 46, -3, -12, -87, -9, 4, 19,
-113, -36, 78, 57, -26, -38, -77, -10,
6, 6, -75, 25, -97, -11, 33, -46,
1, 13, -21, -33, -20, 16, -6, -3,
-11, -4, -27, 38, 8, -41, -2, -33,
18, 19, -26, 1, -29, -22, -4, -14,
-55, -11, -80, -3, 11, 34, 90, 51,
11, 17, 43, 36, 127, -32, 29, 103,
9, 27, 13, 64, 56, 70, -14, 3,
-12, 10, 37, 3, 12, -22, -10, 46,
28, 10, 20, 26, -24, 18, 9, 7,
14, 34, -5, -7, 31, -14, -56, 11,
-18, -8, -17, -7, -10, -40, 10, -33,
-32, -43, 5, 9, 11, -4, 10, 50,
-12, -5, 46, 9, 7, 1, 11, 15,
91, -17, 7, -50, 23, 6, -30, -99,
0, -17, 14, 8, -10, -25, -30, -69,
-62, 31, 127, 114, -23, 101, -5, -54,
-6, -22, 7, -56, 39, 18, -29, 0,
46, 8, -79, 4, -21, 18, -32, 62,
-12, -8, -12, -58, 31, -32, 17, 6,
-24, 25, 24, 9, -4, -19, 45, 6,
17, -14, 5, -27, 16, -4, -41, 25,
-36, 5, 15, 12, 50, 27, 25, 23,
-44, -69, -9, -19, -48, -8, 4, 12,
-6, 13, -19, -30, -36, 26, 37, -1,
-3, -30, -42, -14, -10, -20, 26, -54,
-27, -44, 4, 73, -26, 90, 32, -69,
-29, -16, 3, 103, 15, -17, 37, 24,
-23, -31, 33, -37, -64, 25, 13, -81,
-28, -32, 27, 5, -35, -23, 15, -22,
19, -7, 9, 30, 19, -23, 27, -13,
43, 29, -29, -6, 9, -40, -33, -33,
-32, 9, 11, -48, -8, -23, -52, 46,
17, -22, -42, 35, -15, -41, 16, 34,
31, -42, -19, -11, 55, 7, -39, 89,
-11, -33, 20, -14, 22, 32, 3, -17,
-6, 14, 34, 1, 55, -21, -90, -8,
18, 27, 13, -29, 21, 15, -33, -51,
-9, -11, 4, -16, -18, 23, -4, -4,
48, 1, 7, 29, -14, -12, -16, 17,
35, 8, 0, -7, -2, 9, 8, 17,
-6, 53, -32, -21, -50, 5, 99, -60,
-5, -53, 10, -31, 12, -5, 7, 80,
36, 18, -31, 9, 98, 36, -63, -35,
4, -13, -28, -24, 28, -13, 18, 16,
-1, -18, -34, 10, 20, 7, 4, 29,
11, 25, -7, 36, 14, 45, 24, 1,
-16, 30, 6, 35, -6, -11, -24, 13,
-1, 27, 39, 20, 48, -11, -4, -13,
28, 11, -31, -18, 31, -29, 22, -2,
-20, -16, 5, 30, -12, -28, -3, 93,
-16, 23, 18, -29, 6, -54, -37, 28,
-3, -3, -47, -3, -36, -55, -3, 41,
-10, 47, -2, 23, 42, -7, -71, -27,
83, -64, 7, -24, 8, 26, -17, 15,
12, 31, -30, -38, -13, -33, -56, 4,
-17, 20, 18, 1, -30, -5, -6, -31,
-14, -37, 0, 22, 10, -30, 37, -17,
18, 6, 5, 23, -36, -32, 14, 18,
-13, -61, -52, -69, 44, -30, 16, 18,
-4, -25, 14, 81, 26, -8, -23, -59,
52, -104, 17, 119, -32, 26, 17, 1,
23, 45, 29, -64, -57, -14, 73, 21,
-13, -13, 9, -68, -7, -52, 3, 24,
-39, 44, -15, 27, 14, 19, -9, -28,
-11, 5, 3, -34, -2, 2, 22, -6,
-23, 4, 3, 13, -22, -13, -10, -18,
29, 6, 44, -13, -24, -8, 2, 30,
14, 43, 6, 17, -73, -6, -7, 20,
-80, -7, -7, -28, 15, -69, -38, -5,
-100, -35, 15, -79, 23, 29, -18, -27,
21, -66, -37, 8, -22, -39, 48, 4,
-13, 1, -9, 11, -29, 22, 6, -49,
32, -14, 47, -18, -4, 44, -52, -74,
43, 30, 23, -14, 5, 0, -27, 4,
-7, 10, -4, 10, 1, -16, 11, -18,
-2, -5, 2, -11, 0, -20, -4, 38,
74, 59, 39, 64, -10, 26, -3, -40,
-68, 3, -30, -51, 8, -19, -27, -46,
51, 52, 54, 36, 90, 92, 14, 13,
-5, 0, 16, -62, 16, 11, -47, -37,
-6, -5, 21, 54, -57, 32, 42, -6,
62, -9, 16, 21, 24, 9, -10, -4,
33, 50, 13, -15, 1, -35, -48, 18,
-11, -17, -67, -13, 21, 38, -44, 36,
-16, 29, 17, 5, -10, 18, 17, -32,
2, 8, 22, -56, -15, -32, 40, 43,
19, 46, -7, -100, -96, 19, 53, 24,
21, -26, -48, -101, -82, 61, 38, -85,
-28, -34, -1, 63, -5, -5, 39, 39,
-38, 32, -12, -28, 20, 40, -8, 2,
31, 12, -35, -13, 20, -25, 30, 8,
3, -13, -9, -20, 2, -13, 24, 37,
-10, 33, 6, 20, -16, -24, -6, -6,
-19, -5, 22, 21, 10, 11, -4, -39,
-1, 6, 49, 41, -15, -57, 21, -62,
77, -69, -13, 0, -74, 1, -7, -38,
-8, 6, 63, 28, 4, 26, -52, 82,
63, 13, 45, -33, 44, -52, -65, -21,
-46, -49, 64, -17, 32, 24, 68, -39,
-16, -5, -26, 28, 5, -61, -28, 2,
24, 11, -12, -33, 9, -37, -3, -28,
22, -37, -12, 19, 0, -18, -2, 14,
1, 4, 8, -9, -2, 43, -17, -2,
-66, -31, 56, -40, -87, -36, -2, -4,
-42, -45, -1, 31, -43, -15, 27, 63,
-11, 32, -10, -33, 27, -19, 4, 15,
-26, -34, 29, -4, -39, -65, 14, -20,
-21, -17, -36, 13, 59, 47, -38, -33,
13, -37, -8, -37, -7, -6, -76, -31,
-12, -46, 7, 24, -21, -30, -14, 9,
15, -12, -13, 47, -27, -25, -1, -39,
0, 20, -9, 6, 7, 4, 3, 7,
39, 50, 22, -7, 14, -20, 1, 70,
-28, 29, -41, 10, -16, -5, -28, -2,
-37, 32, -18, 17, 62, -11, -20, -50,
36, 21, -62, -12, -56, 52, 50, 17,
3, 48, 44, -41, -25, 3, 16, -3,
0, 33, -6, 15, 27, 34, -25, 22,
9, 17, -11, 36, 16, -2, 12, 21,
-52, 45, -2, -10, 46, 21, -18, 67,
-28, -13, 30, 37, 42, 16, -9, 11,
75, 7, -64, -40, -10, 29, 57, -23,
5, 53, -77, 3, -17, -5, 47, -55,
-35, -36, -13, 52, -53, -71, 52, -111,
-23, -26, -28, 29, -43, 55, -19, 43,
-19, 54, -12, -33, -44, -39, -19, -10,
-31, -10, 21, 38, -57, -20, 2, -25,
8, -6, 50, 12, 15, 25, -25, 15,
-30, -6, 9, 25, 37, 19, -4, 31,
-22, 2, 4, 2, 36, 7, 3, -34,
-80, 36, -10, -2, -5, 31, -36, 49,
-70, 20, -36, 21, 24, 25, -46, -51,
36, -58, -48, -40, -10, 55, 71, 47,
10, -1, 1, 2, -46, -68, 16, 13,
0, -74, -29, 73, -52, -18, -11, 7,
-44, -82, -32, -70, -28, -1, -39, -68,
-6, -41, 12, -22, -16, 40, -11, -25,
51, -9, 21, 4, 4, -34, 7, -78,
16, 6, -38, -30, -2, -44, 32, 0,
22, 64, 5, -72, -2, -14, -10, -16,
-8, -25, 12, 102, -58, 37, -10, -23,
15, 49, 7, -7, 2, -20, -32, 45,
-6, 48, 28, 30, 33, -1, 22, -6,
30, 65, -17, 29, 74, 37, -26, -10,
15, -24, 19, -66, 22, -10, -31, -1,
-18, -9, 11, 37, -4, 45, 5, 41,
17, 1, 1, 24, -58, 41, 5, -51,
14, 8, 43, 16, -10, -1, 45, 32,
-64, 3, -33, -25, -3, -27, -68, 12,
23, -11, -13, -37, -40, 4, -21, -12,
32, -23, -19, 76, 41, -23, -24, -44,
-65, -1, -15, 1, 71, 63, 5, 20,
-3, 21, -23, 31, -32, 18, -2, 27,
31, 46, -5, -39, -5, -35, 18, -18,
-40, -10, 3, 12, 2, -2, -22, 40,
5, -6, 60, 36, 3, 29, -27, 10,
25, -54, 5, 26, 39, 35, -24, -37,
30, -91, 28, -4, -21, -27, -39, -6,
5, 12, -128, 38, -16, 29, -95, -29,
82, -2, 35, 2, 12, 8, -22, 10,
80, -47, 2, -25, -73, -79, 16, -30,
-32, -66, 48, 21, -45, -11, -47, 14,
-27, -17, -7, 15, -44, -14, -44, -26,
-32, 26, -23, 17, -7, -28, 26, -6,
28, 6, -26, 2, 13, -14, -23, -14,
19, 46, 16, 2, -33, -21, 28, -17,
-42, 44, -37, 1, -39, 28, 84, -46,
15, 10, 13, -44, 72, -26, 26, 32,
-28, -12, -83, 2, 10, -30, -44, -10,
-28, 53, 45, 65, 0, -25, 57, 36,
-33, 6, 29, 44, -53, 11, 19, -2,
-27, 35, 32, 49, 4, 23, 38, 36,
24, 10, 51, -39, 4, -7, 26, 37,
-35, 11, -47, -18, 28, 16, -35, 42,
17, -21, -41, 28, 14, -12, 11, -45,
7, -43, -15, 18, -5, 38, -40, -50,
-30, -21, 9, -98, 13, 12, 23, 75,
-56, -7, -3, -4, -1, -34, 12, -49,
11, 26, -18, -28, -17, 33, 13, -14,
40, 24, -72, -37, 10, 17, -6, 22,
16, 16, -6, -12, -30, -14, 10, 40,
-23, 12, 15, -3, -15, 13, -56, -4,
-30, 1, -3, -17, 27, 50, -5, 64,
-36, -19, 7, 29, 22, 25, 9, -16,
-58, -69, -40, -61, -71, -14, 42, 93,
26, 11, -6, -58, -11, 70, -52, 19,
9, -30, -33, 11, -37, -47, -21, -22,
-40, 10, 47, 4, -23, 17, 48, 41,
-48, 14, 10, 15, 34, -23, -2, -47,
23, -32, -13, -10, -26, -26, -4, 16,
38, -14, 0, -12, -7, -7, 20, 44,
-1, -32, -27, -16, 4, -6, -18, 14,
5, 4, -29, 28, 7, -7, 15, -11,
-20, -45, -36, 16, 84, 34, -59, -30,
22, 126, 8, 68, 79, -17, 21, -68,
37, 5, 15, 63, 49, 127, -90, 85,
43, 7, 16, 9, 6, -45, -57, -43,
57, 11, -23, -11, -29, 60, -26, 0,
7, 42, -24, 10, 23, -25, 8, -7,
-40, 19, -17, 35, 4, 27, -39, -91,
27, -36, 34, 2, 16, -24, 25, 7,
-21, 5, 17, 10, -22, -30, 9, -17,
-61, -26, 33, 21, 58, -51, -14, 69,
-38, 20, 7, 80, -4, -65, -6, -27,
53, -12, 47, -1, -15, 1, 60, 102,
-79, -4, 12, 9, 22, 37, -8, -4,
37, 2, -3, -15, -16, -11, -5, 19,
-6, -43, 20, -25, -18, 10, -27, 0,
-28, -27, -11, 10, -18, -2, -4, -16,
26, 14, -6, 7, -6, 1, 53, -2,
-29, 23, 9, -30, -6, -4, -6, 56,
70, 0, -33, -20, -17, -9, -24, 46,
-5, -105, 47, -46, -51, 20, 20, -53,
-81, -1, -7, 75, -5, -21, -65, 12,
-52, 22, -50, -12, 49, 54, 76, -81,
10, 45, -41, -59, 18, -19, 25, 14,
-31, -53, -5, 12, 31, 84, -23, 2,
7, 2, 10, -32, 39, -2, -12, 1,
-9, 0, -10, -11, 9, 15, -8, -2,
2, -1, 10, 14, -5, -40, 19, -7,
-7, 26, -4, 2, 1, -27, 35, 32,
21, -31, 26, 43, -9, 4, -32, 40,
-62, -52, 36, 22, 38, 22, 36, -96,
6, -10, -23, -49, 15, -33, -18, -3,
0, 41, 21, -19, 21, 23, -39, -23,
-6, 6, 47, 56, 4, 74, 0, -98,
29, -47, -14, -36, 21, -22, 22, 16,
13, 12, 16, -5, 13, 17, -13, -15,
1, -34, -26, 26, 12, 32, 27, 13,
-67, 27, 2, 8, 10, 18, 16, 20,
-17, -17, 57, -64, 5, 14, 19, 31,
-18, -44, -46, -16, 4, -25, 17, -126,
-24, 39, 4, 8, 55, -25, -34, 39,
-16, 3, 9, 71, 72, -31, -55, 6,
10, -25, 32, -85, -21, 18, -8, 15,
12, -27, -7, 1, -21, -2, -5, 48,
-16, 18, 1, -22, -26, 16, 14, -31,
27, -6, -15, -21, 4, -14, 18, -36
};
static const opus_int8 layer1_recur_weights[1728] = {
20, 67, -99, 12, 41, -25, 49, -44,
35, 81, 110, 47, 34, -66, -14, 14,
-60, 34, 29, -73, 10, 41, 35, 89,
7, -35, 22, 7, 27, -20, -6, 56,
26, 66, 6, 33, -55, 53, 1, -21,
14, 17, 68, 55, 59, 0, 18, -9,
5, -41, 6, -5, -114, -12, 29, 42,
-23, 10, 81, -27, 20, -53, -30, -62,
40, 95, 25, -4, 3, 18, -8, -15,
-29, -82, 2, -57, -3, -61, -29, -29,
49, 2, -55, 5, -69, -99, -49, -51,
6, -25, 12, 89, 44, -33, 5, 41,
1, 23, -37, -37, -28, -48, 3, 4,
-41, -30, -57, -35, -39, -1, -13, -56,
-5, 50, 49, 41, -4, -4, 33, -22,
-1, 33, 34, 18, 40, -42, 12, 1,
-6, -2, 18, 17, 39, 44, 11, 65,
-60, -45, 10, 91, 21, 9, -62, -11,
8, 69, 37, 24, -30, 21, 26, -27,
1, -28, 24, 66, -8, 6, -71, 34,
24, 44, 58, -78, -19, 57, 17, -60,
1, 12, -3, -1, -40, 22, 11, -5,
25, 12, 1, 72, 79, 7, -50, 23,
18, 13, 21, -11, -20, 5, 77, -94,
24, 15, 57, -51, 3, 36, 53, -1,
4, 14, 30, -31, 22, 40, 32, -11,
-34, -36, -59, 58, 25, 21, -54, -23,
40, 46, 18, 0, 12, 54, -96, -99,
-59, 5, 119, -38, 50, 55, 12, -16,
67, 0, 34, 35, 39, 35, -1, 69,
24, 27, -30, -35, -4, -70, 2, -44,
-7, -6, 19, -9, 60, 44, -21, -10,
37, 43, -16, -3, 30, -15, -65, 31,
-55, 18, -98, 76, 64, 25, 24, -18,
-7, -68, -10, 38, 27, -60, 36, 33,
16, 30, 34, -39, -37, 31, 12, 53,
-54, 14, -26, -49, -128, -13, -5, -22,
-11, -85, 55, -8, -51, -11, -33, -10,
-31, -76, -41, 23, 44, -40, -54, -127,
-101, 19, -23, -15, 15, 27, 58, -60,
8, 14, -33, 1, 48, -9, -11, -123,
3, 53, 23, 4, -28, 22, 2, -29,
-67, 36, 12, 7, 55, -21, 88, 20,
-1, -21, -17, 3, 41, 32, -10, -14,
-5, -57, 67, 57, 21, 23, -2, -27,
-73, -24, 120, 21, 18, -35, 42, -7,
3, -45, -25, 76, -34, 50, 11, -54,
-91, 3, -113, -20, -5, 47, 15, -47,
17, 27, -3, -26, -7, 10, 7, 74,
-40, 64, -7, -5, -24, -49, -24, -3,
-10, 27, -17, -8, -3, 14, -27, 33,
13, 39, 28, -7, -38, 29, 16, 44,
19, 55, -3, 9, -13, -57, 43, 43,
31, 0, -93, -17, 19, -56, 4, -12,
-25, 37, -85, -13, -118, 33, -17, 56,
71, -80, -4, 6, -11, -18, 47, -52,
25, 9, 48, -107, 1, 21, 20, -3,
10, -16, -4, 24, 17, 31, -61, -18,
-50, 24, -10, 12, 71, 26, 11, -3,
4, 1, 0, -7, -40, 18, 38, -34,
38, 17, 8, -34, 2, 21, 123, -32,
-26, 43, 14, -34, -1, -9, 37, -16,
6, -17, -62, 68, 22, 17, 11, -75,
33, -80, 62, -9, -75, 76, 36, -41,
-8, -40, -11, -71, 40, -39, 62, -49,
-81, 16, -9, -52, 52, 61, 17, -103,
-27, -10, -8, -54, -57, 21, 23, -16,
-52, 36, 18, 10, -5, 8, 15, -29,
5, -19, -37, 8, -53, 6, 19, -37,
38, -17, 48, 10, 0, 81, 46, 70,
-29, 101, 11, 44, -44, -3, 24, 11,
3, 14, -9, 11, 14, -45, 13, 46,
-3, -57, 68, 44, 63, 98, 25, -28,
-23, 15, 32, -10, 53, -6, -2, -9,
-6, 16, -107, -11, -11, -28, 59, 57,
-22, 38, 42, 83, 27, 5, 29, -30,
12, -21, -13, 31, 38, -21, 58, -10,
-10, -15, -2, -5, 11, 12, -73, -28,
-38, 22, 2, -25, 73, -52, -12, -55,
32, -63, 21, 51, 33, 52, -26, 55,
-26, -26, 57, -32, -4, -52, -61, 21,
-33, -91, -51, 69, -90, -53, -38, -44,
12, -76, -20, 77, -45, -7, 86, 43,
-109, -33, -105, -40, -121, -10, 0, -72,
45, -51, -75, -49, -38, -1, -62, 18,
-1, 30, -44, -14, -10, -67, 40, -10,
-34, 46, -64, -32, 29, -13, 33, 3,
-32, -5, 28, -27, -25, 93, 24, 68,
-40, 57, 23, -3, -21, -58, 17, -39,
-17, -22, -89, 11, 18, -46, 27, 24,
46, 127, 61, 87, 31, 127, -36, 47,
-23, 47, 127, -24, 110, 122, 30, 100,
0, 96, -12, 6, 50, 44, -13, 73,
4, 55, -11, -15, 49, 42, -6, 20,
-35, 58, 18, 38, 42, 72, 19, -21,
11, 9, -37, 7, 29, 31, 16, -17,
13, -50, 19, 5, -23, 51, -16, -5,
4, -24, 76, 10, -53, -28, -7, -65,
74, 40, -16, -29, 32, -16, -49, -35,
-3, 59, -96, -50, -43, -43, -61, -15,
-8, -36, -34, -33, -14, 11, -3, -39,
4, -114, -123, -11, -49, -21, 14, -56,
1, 43, -63, 26, 40, 18, -10, -26,
-14, -15, -35, -35, -11, 32, -44, -67,
2, 22, 7, 3, -9, -30, -51, -28,
28, 6, -22, 16, 34, -25, -52, -54,
-8, -6, 5, 8, 20, -16, -17, -44,
27, 3, 31, -5, -48, -1, -3, 116,
11, 71, -31, -47, 109, 50, -22, -12,
-57, 32, 66, 8, -25, -93, -54, -10,
19, -76, -34, 97, 48, -36, -18, -30,
-39, -26, -12, 28, 14, 12, -12, -31,
38, 2, 10, 4, -40, 20, 16, -61,
2, 64, 39, 5, 15, 33, 40, -61,
-49, 93, -10, 33, 28, -11, -27, -18,
39, -62, -6, -6, 62, 11, -8, 38,
-67, 12, 27, 39, -27, 123, -18, -6,
-65, 83, -64, 20, 19, -11, 33, 24,
17, 56, 78, 7, -15, 54, -101, -9,
115, -96, 50, 51, 35, 34, 27, 37,
-40, -11, 8, -36, 42, -45, 2, -23,
0, 67, -8, -9, -13, 50, -14, -27,
4, 0, -8, -14, 30, -9, 29, 15,
9, -38, 37, -8, 50, -46, 54, 41,
-11, -8, -11, -26, 39, 45, 14, -26,
-17, -27, 69, 38, 39, 98, 66, 0,
42, 123, -101, -19, -83, 117, -32, 56,
10, 12, -88, 79, -53, 56, 63, 95,
-62, 9, 36, -13, -79, -16, 37, -46,
35, -34, 14, 17, -54, 5, 21, -7,
7, 63, 56, 15, 27, -76, -25, 4,
-26, -63, 28, -67, -52, 43, -47, -70,
40, -12, 40, -66, -37, 0, 35, 37,
-53, 4, -17, -51, 11, 21, 14, -34,
-4, 24, -42, 29, 22, 7, 28, 12,
37, 39, -39, -19, 65, -60, -50, -2,
1, 82, 39, 19, -23, -43, -22, -67,
-35, -34, 32, 102, 81, 127, 36, 67,
-45, 1, -67, -52, -4, 35, 20, 28,
71, 86, -35, -9, -83, -34, 12, 9,
-23, 2, 14, 28, -23, 7, -25, 45,
7, 17, -37, 0, -19, 31, 26, 40,
-27, -16, 17, 5, -21, 23, 24, 96,
-55, 52, -19, -14, -6, 1, 50, -34,
86, -53, 38, 2, -52, -36, -13, 60,
-85, -120, 32, 7, -12, 22, 70, -7,
-94, 38, -76, -31, -20, 15, -28, 7,
6, 40, 53, 88, 3, 38, 18, -8,
-22, -23, 51, 37, -9, 13, -32, 25,
-21, 27, 31, 20, 18, -9, -13, 1,
21, -24, -13, 39, 15, -11, -29, -36,
18, 15, 8, 27, 21, -94, -1, -22,
49, 66, -1, 6, -3, -40, -18, 6,
28, 12, 33, -59, 62, 60, -48, 90,
-1, 108, 9, 18, -2, 27, 77, -65,
82, -48, -38, -19, -11, 127, 50, 66,
18, -13, -22, 60, -38, 40, -14, -26,
-13, 38, 67, 57, 30, 33, 26, 36,
38, -17, 27, -28, 20, 12, -64, 18,
5, -33, -27, 13, -26, 32, 35, -5,
-48, -14, 92, 43, -47, -14, 40, 11,
51, 66, 22, -63, -16, -61, 4, -28,
27, 20, -33, -30, -21, -29, -53, 31,
-40, 24, 43, -4, -19, 21, 67, 20,
100, -16, -93, 78, -6, -18, -52, -37,
-9, 66, -31, -8, 26, 18, 4, 24,
-22, 17, -2, -13, 27, 0, 8, -18,
-25, 5, -21, -24, -7, 18, -93, 21,
7, 2, -75, 69, 50, -5, -15, -17,
60, -42, 55, 1, -4, 3, 10, 46,
16, -13, 45, -7, -10, -44, -108, 49,
2, -15, -64, -12, -72, 32, -38, -45,
10, -54, 13, -13, -27, -36, -64, 58,
-62, -101, 88, -86, -71, -39, -9, -128,
32, 15, -4, 54, -16, -39, -26, -36,
46, 48, -64, -10, 19, 30, -13, 34,
-8, 50, 60, -22, -6, -11, -30, 5,
50, 32, 56, 0, 25, 6, 68, 11,
-29, 45, -9, -12, 4, 1, 18, -49,
0, -38, -19, 90, 29, 35, 51, 8,
-48, 96, -1, -12, -9, -32, -63, -65,
-7, 38, 89, 28, -85, -28, -23, -25,
-128, 56, 79, -36, 99, -6, -37, 7,
-13, -69, -46, -29, 25, 64, -21, 17,
1, 42, -66, 1, 80, 26, -32, 21,
15, 15, 6, 6, -10, 15, 127, 5,
38, 27, 87, -57, -25, 11, 72, -21,
-5, 11, -13, -66, 78, 36, -3, 41,
-21, 8, -33, 23, 73, 28, 57, -25,
-5, 4, -22, -47, 15, 4, -57, -72,
33, 1, 18, 2, 53, -71, -99, -21,
-3, -111, 108, 71, -14, 82, 25, 61,
-48, 5, 9, -51, -20, -25, -3, 14,
-33, 14, -3, -34, 22, 12, -19, -38,
-16, 2, 21, 16, 26, -31, 75, 44,
-31, 16, 26, 66, 17, -9, -22, -22,
22, -44, 22, 27, 2, 58, -14, 10,
-73, -42, 55, -25, -61, 72, -1, 30,
-58, -25, 63, 26, -48, -40, 26, -30,
60, 8, -17, -1, -18, -20, 43, -20,
-4, -28, 127, -106, 29, 70, 64, -27,
39, -33, -5, -88, -40, -52, 26, 44,
-17, 23, 2, -49, 22, -9, -8, 86,
49, -43, -60, 1, 10, 45, 36, -53,
-4, 33, 38, 48, -72, 1, 19, 21,
-65, 4, -5, -62, 27, -25, 17, -6,
6, -45, -39, -46, 4, 26, 127, -9,
18, -33, -18, -3, 33, 2, -5, 15,
-26, -22, -117, -63, -17, -59, 61, -74,
7, -47, -58, -128, -67, 15, -16, -128,
12, 2, 20, 9, -48, -40, 43, 3,
-40, -16, -38, -6, -22, -28, -16, -59,
-22, 6, -5, 11, -12, -66, -40, 27,
-62, -44, -19, 38, -3, 39, -8, 40,
-24, 13, 21, 50, -60, -22, 53, -29,
-6, 1, 22, -59, 0, 17, -39, 115
};
static const opus_int8 layer1_bias[72] = {
-42, 20, 16, 0, 105, 60, 1, -97,
24, 60, 18, 13, 62, 25, 127, 34,
79, 55, 118, 127, 95, 31, -4, 87,
21, 12, 2, -14, 18, 23, 8, 17,
-1, -8, 5, 4, 24, 37, 21, 13,
36, 13, 17, 18, 37, 30, 33, 1,
8, -16, -11, -5, -31, -3, -5, 0,
6, 3, 58, -7, -1, -16, 5, -13,
16, 10, -2, -14, 11, -4, 3, -11
};
static const opus_int8 layer2_weights[48] = {
-113, -88, 31, -128, -126, -61, 85, -35,
118, -128, -61, 127, -128, -17, -128, 127,
104, -9, -128, 33, 45, 127, 5, 83,
84, -128, -85, -128, -45, 48, -53, -128,
46, 127, -17, 125, 117, -41, -117, -91,
-127, -68, -1, -89, -80, 32, 106, 7
};
static const opus_int8 layer2_bias[2] = {
14, 117
};
const 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
};
+398
View File
@@ -0,0 +1,398 @@
/* Copyright (c) 2011 Xiph.Org Foundation, Skype Limited
Copyright (c) 2024 Arm 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 "config.h"
#endif
#include "opus.h"
#include "mathops.h"
#include "opus_private.h"
#ifndef DISABLE_FLOAT_API
void opus_pcm_soft_clip_impl(float *_x, int N, int C, float *declip_mem, int arch)
{
int c;
int i;
float *x;
int all_within_neg1pos1;
if (C<1 || N<1 || !_x || !declip_mem) return;
/* Clamp everything within the range [-2, +2] which is the domain of the soft
clipping non-linearity. Outside the defined range the derivative will be zero,
therefore there is no discontinuity introduced here. The implementation
might provide a hint if all input samples are within the [-1, +1] range.
`opus_limit2_checkwithin1()`:
- Clamps all samples within the valid range [-2, +2].
- Generic C implementation:
* Does not attempt early detection whether samples are within hinted range.
* Always returns 0.
- Architecture specific implementation:
* Uses SIMD instructions to efficiently detect if all samples are
within the hinted range [-1, +1].
* Returns 1 if no samples exceed the hinted range, 0 otherwise.
`all_within_neg1pos1`:
- Optimization hint to skip per-sample out-of-bound checks.
If true, the check can be skipped. */
all_within_neg1pos1 = opus_limit2_checkwithin1(_x, N*C, arch);
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;
/* Detection for early exit can be skipped if hinted by `all_within_neg1pos1` */
if (all_within_neg1pos1)
{
i = N;
} else {
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;
}
}
OPUS_EXPORT void opus_pcm_soft_clip(float *_x, int N, int C, float *declip_mem)
{
opus_pcm_soft_clip_impl(_x, N, C, declip_mem, 0);
}
#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;
/* Make sure we return NULL/0 on error. */
if (padding != NULL)
{
*padding = NULL;
*padding_len = 0;
}
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
+91
View File
@@ -0,0 +1,91 @@
/* 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 "config.h"
#endif
#include "opus_multistream.h"
#include "opus.h"
#include "opus_private.h"
#include "stack_alloc.h"
#include <stdarg.h>
#include "float_cast.h"
#include "os_support.h"
int validate_layout(const ChannelLayout *layout)
{
int i, max_channel;
max_channel = layout->nb_streams+layout->nb_coupled_streams;
if (max_channel>255)
return 0;
for (i=0;i<layout->nb_channels;i++)
{
if (layout->mapping[i] >= max_channel && layout->mapping[i] != 255)
return 0;
}
return 1;
}
int get_left_channel(const ChannelLayout *layout, int stream_id, int prev)
{
int i;
i = (prev<0) ? 0 : prev+1;
for (;i<layout->nb_channels;i++)
{
if (layout->mapping[i]==stream_id*2)
return i;
}
return -1;
}
int get_right_channel(const ChannelLayout *layout, int stream_id, int prev)
{
int i;
i = (prev<0) ? 0 : prev+1;
for (;i<layout->nb_channels;i++)
{
if (layout->mapping[i]==stream_id*2+1)
return i;
}
return -1;
}
int get_mono_channel(const ChannelLayout *layout, int stream_id, int prev)
{
int i;
i = (prev<0) ? 0 : prev+1;
for (;i<layout->nb_channels;i++)
{
if (layout->mapping[i]==stream_id+layout->nb_coupled_streams)
return i;
}
return -1;
}
+565
View File
@@ -0,0 +1,565 @@
/* 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 "config.h"
#endif
#include "opus_multistream.h"
#include "opus.h"
#include "opus_private.h"
#include "stack_alloc.h"
#include <stdarg.h>
#include "float_cast.h"
#include "os_support.h"
/* DECODER */
#if defined(ENABLE_HARDENING) || defined(ENABLE_ASSERTIONS)
static void validate_ms_decoder(OpusMSDecoder *st)
{
validate_layout(&st->layout);
}
#define VALIDATE_MS_DECODER(st) validate_ms_decoder(st)
#else
#define VALIDATE_MS_DECODER(st)
#endif
opus_int32 opus_multistream_decoder_get_size(int nb_streams, int nb_coupled_streams)
{
int coupled_size;
int mono_size;
if(nb_streams<1||nb_coupled_streams>nb_streams||nb_coupled_streams<0)return 0;
coupled_size = opus_decoder_get_size(2);
mono_size = opus_decoder_get_size(1);
return align(sizeof(OpusMSDecoder))
+ nb_coupled_streams * align(coupled_size)
+ (nb_streams-nb_coupled_streams) * align(mono_size);
}
int opus_multistream_decoder_init(
OpusMSDecoder *st,
opus_int32 Fs,
int channels,
int streams,
int coupled_streams,
const unsigned char *mapping
)
{
int coupled_size;
int mono_size;
int i, ret;
char *ptr;
if ((channels>255) || (channels<1) || (coupled_streams>streams) ||
(streams<1) || (coupled_streams<0) || (streams>255-coupled_streams))
return OPUS_BAD_ARG;
st->layout.nb_channels = channels;
st->layout.nb_streams = streams;
st->layout.nb_coupled_streams = coupled_streams;
for (i=0;i<st->layout.nb_channels;i++)
st->layout.mapping[i] = mapping[i];
if (!validate_layout(&st->layout))
return OPUS_BAD_ARG;
ptr = (char*)st + align(sizeof(OpusMSDecoder));
coupled_size = opus_decoder_get_size(2);
mono_size = opus_decoder_get_size(1);
for (i=0;i<st->layout.nb_coupled_streams;i++)
{
ret=opus_decoder_init((OpusDecoder*)ptr, Fs, 2);
if(ret!=OPUS_OK)return ret;
ptr += align(coupled_size);
}
for (;i<st->layout.nb_streams;i++)
{
ret=opus_decoder_init((OpusDecoder*)ptr, Fs, 1);
if(ret!=OPUS_OK)return ret;
ptr += align(mono_size);
}
return OPUS_OK;
}
OpusMSDecoder *opus_multistream_decoder_create(
opus_int32 Fs,
int channels,
int streams,
int coupled_streams,
const unsigned char *mapping,
int *error
)
{
int ret;
OpusMSDecoder *st;
if ((channels>255) || (channels<1) || (coupled_streams>streams) ||
(streams<1) || (coupled_streams<0) || (streams>255-coupled_streams))
{
if (error)
*error = OPUS_BAD_ARG;
return NULL;
}
st = (OpusMSDecoder *)opus_alloc(opus_multistream_decoder_get_size(streams, coupled_streams));
if (st==NULL)
{
if (error)
*error = OPUS_ALLOC_FAIL;
return NULL;
}
ret = opus_multistream_decoder_init(st, Fs, channels, streams, coupled_streams, mapping);
if (error)
*error = ret;
if (ret != OPUS_OK)
{
opus_free(st);
st = NULL;
}
return st;
}
static int opus_multistream_packet_validate(const unsigned char *data,
opus_int32 len, int nb_streams, opus_int32 Fs)
{
int s;
int count;
unsigned char toc;
opus_int16 size[48];
int samples=0;
opus_int32 packet_offset;
for (s=0;s<nb_streams;s++)
{
int tmp_samples;
if (len<=0)
return OPUS_INVALID_PACKET;
count = opus_packet_parse_impl(data, len, s!=nb_streams-1, &toc, NULL,
size, NULL, &packet_offset, NULL, NULL);
if (count<0)
return count;
tmp_samples = opus_packet_get_nb_samples(data, packet_offset, Fs);
if (s!=0 && samples != tmp_samples)
return OPUS_INVALID_PACKET;
samples = tmp_samples;
data += packet_offset;
len -= packet_offset;
}
return samples;
}
int opus_multistream_decode_native(
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 Fs;
int coupled_size;
int mono_size;
int s, c;
char *ptr;
int do_plc=0;
VARDECL(opus_res, buf);
ALLOC_STACK;
VALIDATE_MS_DECODER(st);
if (frame_size <= 0)
{
RESTORE_STACK;
return OPUS_BAD_ARG;
}
/* Limit frame_size to avoid excessive stack allocations. */
MUST_SUCCEED(opus_multistream_decoder_ctl(st, OPUS_GET_SAMPLE_RATE(&Fs)));
frame_size = IMIN(frame_size, Fs/25*3);
ALLOC(buf, 2*frame_size, opus_res);
ptr = (char*)st + align(sizeof(OpusMSDecoder));
coupled_size = opus_decoder_get_size(2);
mono_size = opus_decoder_get_size(1);
if (len==0)
do_plc = 1;
if (len < 0)
{
RESTORE_STACK;
return OPUS_BAD_ARG;
}
if (!do_plc && len < 2*st->layout.nb_streams-1)
{
RESTORE_STACK;
return OPUS_INVALID_PACKET;
}
if (!do_plc)
{
int ret = opus_multistream_packet_validate(data, len, st->layout.nb_streams, Fs);
if (ret < 0)
{
RESTORE_STACK;
return ret;
} else if (ret > frame_size)
{
RESTORE_STACK;
return OPUS_BUFFER_TOO_SMALL;
}
}
for (s=0;s<st->layout.nb_streams;s++)
{
OpusDecoder *dec;
opus_int32 packet_offset;
int ret;
dec = (OpusDecoder*)ptr;
ptr += (s < st->layout.nb_coupled_streams) ? align(coupled_size) : align(mono_size);
if (!do_plc && len<=0)
{
RESTORE_STACK;
return OPUS_INTERNAL_ERROR;
}
packet_offset = 0;
ret = opus_decode_native(dec, data, len, buf, frame_size, decode_fec, s!=st->layout.nb_streams-1, &packet_offset, soft_clip, NULL, 0);
if (!do_plc)
{
data += packet_offset;
len -= packet_offset;
}
if (ret <= 0)
{
RESTORE_STACK;
return ret;
}
frame_size = ret;
if (s < st->layout.nb_coupled_streams)
{
int chan, prev;
prev = -1;
/* Copy "left" audio to the channel(s) where it belongs */
while ( (chan = get_left_channel(&st->layout, s, prev)) != -1)
{
(*copy_channel_out)(pcm, st->layout.nb_channels, chan,
buf, 2, frame_size, user_data);
prev = chan;
}
prev = -1;
/* Copy "right" audio to the channel(s) where it belongs */
while ( (chan = get_right_channel(&st->layout, s, prev)) != -1)
{
(*copy_channel_out)(pcm, st->layout.nb_channels, chan,
buf+1, 2, frame_size, user_data);
prev = chan;
}
} else {
int chan, prev;
prev = -1;
/* Copy audio to the channel(s) where it belongs */
while ( (chan = get_mono_channel(&st->layout, s, prev)) != -1)
{
(*copy_channel_out)(pcm, st->layout.nb_channels, chan,
buf, 1, frame_size, user_data);
prev = chan;
}
}
}
/* Handle muted channels */
for (c=0;c<st->layout.nb_channels;c++)
{
if (st->layout.mapping[c] == 255)
{
(*copy_channel_out)(pcm, st->layout.nb_channels, c,
NULL, 0, frame_size, user_data);
}
}
RESTORE_STACK;
return frame_size;
}
#if !defined(DISABLE_FLOAT_API)
static void opus_copy_channel_out_float(
void *dst,
int dst_stride,
int dst_channel,
const opus_res *src,
int src_stride,
int frame_size,
void *user_data
)
{
float *float_dst;
opus_int32 i;
(void)user_data;
float_dst = (float*)dst;
if (src != NULL)
{
for (i=0;i<frame_size;i++)
float_dst[i*dst_stride+dst_channel] = RES2FLOAT(src[i*src_stride]);
}
else
{
for (i=0;i<frame_size;i++)
float_dst[i*dst_stride+dst_channel] = 0;
}
}
#endif
static void opus_copy_channel_out_short(
void *dst,
int dst_stride,
int dst_channel,
const opus_res *src,
int src_stride,
int frame_size,
void *user_data
)
{
opus_int16 *short_dst;
opus_int32 i;
(void)user_data;
short_dst = (opus_int16*)dst;
if (src != NULL)
{
for (i=0;i<frame_size;i++)
short_dst[i*dst_stride+dst_channel] = RES2INT16(src[i*src_stride]);
}
else
{
for (i=0;i<frame_size;i++)
short_dst[i*dst_stride+dst_channel] = 0;
}
}
static void opus_copy_channel_out_int24(
void *dst,
int dst_stride,
int dst_channel,
const opus_res *src,
int src_stride,
int frame_size,
void *user_data
)
{
opus_int32 *short_dst;
opus_int32 i;
(void)user_data;
short_dst = (opus_int32*)dst;
if (src != NULL)
{
for (i=0;i<frame_size;i++)
short_dst[i*dst_stride+dst_channel] = RES2INT24(src[i*src_stride]);
}
else
{
for (i=0;i<frame_size;i++)
short_dst[i*dst_stride+dst_channel] = 0;
}
}
#ifdef FIXED_POINT
#define OPTIONAL_CLIP 0
#else
#define OPTIONAL_CLIP 1
#endif
int opus_multistream_decode(
OpusMSDecoder *st,
const unsigned char *data,
opus_int32 len,
opus_int16 *pcm,
int frame_size,
int decode_fec
)
{
return opus_multistream_decode_native(st, data, len,
pcm, opus_copy_channel_out_short, frame_size, decode_fec, OPTIONAL_CLIP, NULL);
}
int opus_multistream_decode24(
OpusMSDecoder *st,
const unsigned char *data,
opus_int32 len,
opus_int32 *pcm,
int frame_size,
int decode_fec
)
{
return opus_multistream_decode_native(st, data, len,
pcm, opus_copy_channel_out_int24, frame_size, decode_fec, 0, NULL);
}
#ifndef DISABLE_FLOAT_API
int opus_multistream_decode_float(OpusMSDecoder *st, const unsigned char *data,
opus_int32 len, float *pcm, int frame_size, int decode_fec)
{
return opus_multistream_decode_native(st, data, len,
pcm, opus_copy_channel_out_float, frame_size, decode_fec, 0, NULL);
}
#endif
int opus_multistream_decoder_ctl_va_list(OpusMSDecoder *st, int request,
va_list ap)
{
int coupled_size, mono_size;
char *ptr;
int ret = OPUS_OK;
coupled_size = opus_decoder_get_size(2);
mono_size = opus_decoder_get_size(1);
ptr = (char*)st + align(sizeof(OpusMSDecoder));
switch (request)
{
case OPUS_GET_BANDWIDTH_REQUEST:
case OPUS_GET_SAMPLE_RATE_REQUEST:
case OPUS_GET_GAIN_REQUEST:
case OPUS_GET_LAST_PACKET_DURATION_REQUEST:
case OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST:
case OPUS_GET_COMPLEXITY_REQUEST:
{
OpusDecoder *dec;
/* For int32* GET params, just query the first stream */
opus_int32 *value = va_arg(ap, opus_int32*);
dec = (OpusDecoder*)ptr;
ret = opus_decoder_ctl(dec, request, value);
}
break;
case OPUS_GET_FINAL_RANGE_REQUEST:
{
int s;
opus_uint32 *value = va_arg(ap, opus_uint32*);
opus_uint32 tmp;
if (!value)
{
goto bad_arg;
}
*value = 0;
for (s=0;s<st->layout.nb_streams;s++)
{
OpusDecoder *dec;
dec = (OpusDecoder*)ptr;
if (s < st->layout.nb_coupled_streams)
ptr += align(coupled_size);
else
ptr += align(mono_size);
ret = opus_decoder_ctl(dec, request, &tmp);
if (ret != OPUS_OK) break;
*value ^= tmp;
}
}
break;
case OPUS_RESET_STATE:
{
int s;
for (s=0;s<st->layout.nb_streams;s++)
{
OpusDecoder *dec;
dec = (OpusDecoder*)ptr;
if (s < st->layout.nb_coupled_streams)
ptr += align(coupled_size);
else
ptr += align(mono_size);
ret = opus_decoder_ctl(dec, OPUS_RESET_STATE);
if (ret != OPUS_OK)
break;
}
}
break;
case OPUS_MULTISTREAM_GET_DECODER_STATE_REQUEST:
{
int s;
opus_int32 stream_id;
OpusDecoder **value;
stream_id = va_arg(ap, opus_int32);
if (stream_id<0 || stream_id >= st->layout.nb_streams)
goto bad_arg;
value = va_arg(ap, OpusDecoder**);
if (!value)
{
goto bad_arg;
}
for (s=0;s<stream_id;s++)
{
if (s < st->layout.nb_coupled_streams)
ptr += align(coupled_size);
else
ptr += align(mono_size);
}
*value = (OpusDecoder*)ptr;
}
break;
case OPUS_SET_GAIN_REQUEST:
case OPUS_SET_COMPLEXITY_REQUEST:
case OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST:
{
int s;
/* This works for int32 params */
opus_int32 value = va_arg(ap, opus_int32);
for (s=0;s<st->layout.nb_streams;s++)
{
OpusDecoder *dec;
dec = (OpusDecoder*)ptr;
if (s < st->layout.nb_coupled_streams)
ptr += align(coupled_size);
else
ptr += align(mono_size);
ret = opus_decoder_ctl(dec, request, value);
if (ret != OPUS_OK)
break;
}
}
break;
default:
ret = OPUS_UNIMPLEMENTED;
break;
}
return ret;
bad_arg:
return OPUS_BAD_ARG;
}
int opus_multistream_decoder_ctl(OpusMSDecoder *st, int request, ...)
{
int ret;
va_list ap;
va_start(ap, request);
ret = opus_multistream_decoder_ctl_va_list(st, request, ap);
va_end(ap);
return ret;
}
void opus_multistream_decoder_destroy(OpusMSDecoder *st)
{
opus_free(st);
}
File diff suppressed because it is too large. Load diff
+266
View File
@@ -0,0 +1,266 @@
/* 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 "arch.h"
#include "opus.h"
#include "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];
unsigned char padding_nb_frames[48];
};
typedef struct OpusExtensionIterator {
const unsigned char *data;
const unsigned char *curr_data;
const unsigned char *repeat_data;
const unsigned char *last_long;
const unsigned char *src_data;
opus_int32 len;
opus_int32 curr_len;
opus_int32 repeat_len;
opus_int32 src_len;
opus_int32 trailing_short_len;
int nb_frames;
int frame_max;
int curr_frame;
int repeat_frame;
unsigned char repeat_l;
} OpusExtensionIterator;
typedef struct {
int id;
int frame;
const unsigned char *data;
opus_int32 len;
} opus_extension_data;
void opus_extension_iterator_init(OpusExtensionIterator *iter,
const unsigned char *data, opus_int32 len, opus_int32 nb_frames);
void opus_extension_iterator_reset(OpusExtensionIterator *iter);
void opus_extension_iterator_set_frame_max(OpusExtensionIterator *iter,
int frame_max);
int opus_extension_iterator_next(OpusExtensionIterator *iter,
opus_extension_data *ext);
int opus_extension_iterator_find(OpusExtensionIterator *iter,
opus_extension_data *ext, int id);
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;
opus_int32 Fs;
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_res *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_res *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);
void downmix_int24(const void *_x, opus_val32 *sub, int subframe, int offset, int c1, int c2, int C);
int is_digital_silence(const opus_res* pcm, int frame_size, int channels, int lsb_depth);
void opus_pcm_soft_clip_impl(float *_x, int N, int C, float *declip_mem, int arch);
int encode_size(int size, unsigned char *data);
opus_int32 frame_size_select(int application, opus_int32 frame_size, int variable_duration, opus_int32 Fs);
opus_int32 opus_encode_native(OpusEncoder *st, const opus_res *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_res *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;
}
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,
int nb_frames);
opus_int32 opus_packet_extensions_parse_ext(const unsigned char *data,
opus_int32 len, opus_extension_data *extensions, opus_int32 *nb_extensions,
const opus_int32 *nb_frame_exts, int nb_frames);
opus_int32 opus_packet_extensions_generate(unsigned char *data, opus_int32 len,
const opus_extension_data *extensions, opus_int32 nb_extensions,
int nb_frames, int pad);
opus_int32 opus_packet_extensions_count(const unsigned char *data,
opus_int32 len, int nb_frames);
opus_int32 opus_packet_extensions_count_ext(const unsigned char *data,
opus_int32 len, opus_int32 *nb_frame_exts, int nb_frames);
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 */
+282
View File
@@ -0,0 +1,282 @@
/* Copyright (c) 2017 Google Inc.
Written by Andrew Allen */
/*
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "mathops.h"
#include "os_support.h"
#include "opus_private.h"
#include "opus_defines.h"
#include "opus_projection.h"
#include "opus_multistream.h"
#include "mapping_matrix.h"
#include "stack_alloc.h"
struct OpusProjectionDecoder
{
opus_int32 demixing_matrix_size_in_bytes;
/* Encoder states go here */
};
#if !defined(DISABLE_FLOAT_API)
static void opus_projection_copy_channel_out_float(
void *dst,
int dst_stride,
int dst_channel,
const opus_res *src,
int src_stride,
int frame_size,
void *user_data)
{
float *float_dst;
const MappingMatrix *matrix;
float_dst = (float *)dst;
matrix = (const MappingMatrix *)user_data;
if (dst_channel == 0)
OPUS_CLEAR(float_dst, frame_size * dst_stride);
if (src != NULL)
mapping_matrix_multiply_channel_out_float(matrix, src, dst_channel,
src_stride, float_dst, dst_stride, frame_size);
}
#endif
static void opus_projection_copy_channel_out_short(
void *dst,
int dst_stride,
int dst_channel,
const opus_res *src,
int src_stride,
int frame_size,
void *user_data)
{
opus_int16 *short_dst;
const MappingMatrix *matrix;
short_dst = (opus_int16 *)dst;
matrix = (const MappingMatrix *)user_data;
if (dst_channel == 0)
OPUS_CLEAR(short_dst, frame_size * dst_stride);
if (src != NULL)
mapping_matrix_multiply_channel_out_short(matrix, src, dst_channel,
src_stride, short_dst, dst_stride, frame_size);
}
static void opus_projection_copy_channel_out_int24(
void *dst,
int dst_stride,
int dst_channel,
const opus_res *src,
int src_stride,
int frame_size,
void *user_data)
{
opus_int32 *short_dst;
const MappingMatrix *matrix;
short_dst = (opus_int32 *)dst;
matrix = (const MappingMatrix *)user_data;
if (dst_channel == 0)
OPUS_CLEAR(short_dst, frame_size * dst_stride);
if (src != NULL)
mapping_matrix_multiply_channel_out_int24(matrix, src, dst_channel,
src_stride, short_dst, dst_stride, frame_size);
}
static MappingMatrix *get_dec_demixing_matrix(OpusProjectionDecoder *st)
{
/* void* cast avoids clang -Wcast-align warning */
return (MappingMatrix*)(void*)((char*)st +
align(sizeof(OpusProjectionDecoder)));
}
static OpusMSDecoder *get_multistream_decoder(OpusProjectionDecoder *st)
{
/* void* cast avoids clang -Wcast-align warning */
return (OpusMSDecoder*)(void*)((char*)st +
align(sizeof(OpusProjectionDecoder) +
st->demixing_matrix_size_in_bytes));
}
opus_int32 opus_projection_decoder_get_size(int channels, int streams,
int coupled_streams)
{
opus_int32 matrix_size;
opus_int32 decoder_size;
matrix_size =
mapping_matrix_get_size(streams + coupled_streams, channels);
if (!matrix_size)
return 0;
decoder_size = opus_multistream_decoder_get_size(streams, coupled_streams);
if (!decoder_size)
return 0;
return align(sizeof(OpusProjectionDecoder)) + matrix_size + decoder_size;
}
int opus_projection_decoder_init(OpusProjectionDecoder *st, opus_int32 Fs,
int channels, int streams, int coupled_streams,
unsigned char *demixing_matrix, opus_int32 demixing_matrix_size)
{
int nb_input_streams;
opus_int32 expected_matrix_size;
int i, ret;
unsigned char mapping[255];
VARDECL(opus_int16, buf);
ALLOC_STACK;
/* Verify supplied matrix size. */
nb_input_streams = streams + coupled_streams;
expected_matrix_size = nb_input_streams * channels * sizeof(opus_int16);
if (expected_matrix_size != demixing_matrix_size)
{
RESTORE_STACK;
return OPUS_BAD_ARG;
}
/* Convert demixing matrix input into internal format. */
ALLOC(buf, nb_input_streams * channels, opus_int16);
for (i = 0; i < nb_input_streams * channels; i++)
{
int s = demixing_matrix[2*i + 1] << 8 | demixing_matrix[2*i];
s = ((s & 0xFFFF) ^ 0x8000) - 0x8000;
buf[i] = (opus_int16)s;
}
/* Assign demixing matrix. */
st->demixing_matrix_size_in_bytes =
mapping_matrix_get_size(channels, nb_input_streams);
if (!st->demixing_matrix_size_in_bytes)
{
RESTORE_STACK;
return OPUS_BAD_ARG;
}
mapping_matrix_init(get_dec_demixing_matrix(st), channels, nb_input_streams, 0,
buf, demixing_matrix_size);
/* Set trivial mapping so each input channel pairs with a matrix column. */
for (i = 0; i < channels; i++)
mapping[i] = i;
ret = opus_multistream_decoder_init(
get_multistream_decoder(st), Fs, channels, streams, coupled_streams, mapping);
RESTORE_STACK;
return ret;
}
OpusProjectionDecoder *opus_projection_decoder_create(
opus_int32 Fs, int channels, int streams, int coupled_streams,
unsigned char *demixing_matrix, opus_int32 demixing_matrix_size, int *error)
{
int size;
int ret;
OpusProjectionDecoder *st;
/* Allocate space for the projection decoder. */
size = opus_projection_decoder_get_size(channels, streams, coupled_streams);
if (!size) {
if (error)
*error = OPUS_ALLOC_FAIL;
return NULL;
}
st = (OpusProjectionDecoder *)opus_alloc(size);
if (!st)
{
if (error)
*error = OPUS_ALLOC_FAIL;
return NULL;
}
/* Initialize projection decoder with provided settings. */
ret = opus_projection_decoder_init(st, Fs, channels, streams, coupled_streams,
demixing_matrix, demixing_matrix_size);
if (ret != OPUS_OK)
{
opus_free(st);
st = NULL;
}
if (error)
*error = ret;
return st;
}
#ifdef FIXED_POINT
#define OPTIONAL_CLIP 0
#else
#define OPTIONAL_CLIP 1
#endif
int opus_projection_decode(OpusProjectionDecoder *st, const unsigned char *data,
opus_int32 len, opus_int16 *pcm, int frame_size,
int decode_fec)
{
return opus_multistream_decode_native(get_multistream_decoder(st), data, len,
pcm, opus_projection_copy_channel_out_short, frame_size, decode_fec, OPTIONAL_CLIP,
get_dec_demixing_matrix(st));
}
int opus_projection_decode24(OpusProjectionDecoder *st, const unsigned char *data,
opus_int32 len, opus_int32 *pcm, int frame_size,
int decode_fec)
{
return opus_multistream_decode_native(get_multistream_decoder(st), data, len,
pcm, opus_projection_copy_channel_out_int24, frame_size, decode_fec, 0,
get_dec_demixing_matrix(st));
}
#ifndef DISABLE_FLOAT_API
int opus_projection_decode_float(OpusProjectionDecoder *st, const unsigned char *data,
opus_int32 len, float *pcm, int frame_size, int decode_fec)
{
return opus_multistream_decode_native(get_multistream_decoder(st), data, len,
pcm, opus_projection_copy_channel_out_float, frame_size, decode_fec, 0,
get_dec_demixing_matrix(st));
}
#endif
int opus_projection_decoder_ctl(OpusProjectionDecoder *st, int request, ...)
{
va_list ap;
int ret = OPUS_OK;
va_start(ap, request);
ret = opus_multistream_decoder_ctl_va_list(get_multistream_decoder(st),
request, ap);
va_end(ap);
return ret;
}
void opus_projection_decoder_destroy(OpusProjectionDecoder *st)
{
opus_free(st);
}
+521
View File
@@ -0,0 +1,521 @@
/* Copyright (c) 2017 Google Inc.
Written by Andrew Allen */
/*
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "mathops.h"
#include "os_support.h"
#include "opus_private.h"
#include "opus_defines.h"
#include "opus_projection.h"
#include "opus_multistream.h"
#include "stack_alloc.h"
#include "mapping_matrix.h"
struct OpusProjectionEncoder
{
opus_int32 mixing_matrix_size_in_bytes;
opus_int32 demixing_matrix_size_in_bytes;
/* Encoder states go here */
};
#if !defined(DISABLE_FLOAT_API)
static void opus_projection_copy_channel_in_float(
opus_res *dst,
int dst_stride,
const void *src,
int src_stride,
int src_channel,
int frame_size,
void *user_data
)
{
mapping_matrix_multiply_channel_in_float((const MappingMatrix*)user_data,
(const float*)src, src_stride, dst, src_channel, dst_stride, frame_size);
}
#endif
static void opus_projection_copy_channel_in_short(
opus_res *dst,
int dst_stride,
const void *src,
int src_stride,
int src_channel,
int frame_size,
void *user_data
)
{
mapping_matrix_multiply_channel_in_short((const MappingMatrix*)user_data,
(const opus_int16*)src, src_stride, dst, src_channel, dst_stride, frame_size);
}
static void opus_projection_copy_channel_in_int24(
opus_res *dst,
int dst_stride,
const void *src,
int src_stride,
int src_channel,
int frame_size,
void *user_data
)
{
mapping_matrix_multiply_channel_in_int24((const MappingMatrix*)user_data,
(const opus_int32*)src, src_stride, dst, src_channel, dst_stride, frame_size);
}
static int get_order_plus_one_from_channels(int channels, int *order_plus_one)
{
int order_plus_one_;
int acn_channels;
int nondiegetic_channels;
/* Allowed numbers of channels:
* (1 + n)^2 + 2j, for n = 0...14 and j = 0 or 1.
*/
if (channels < 1 || channels > 227)
return OPUS_BAD_ARG;
order_plus_one_ = isqrt32(channels);
acn_channels = order_plus_one_ * order_plus_one_;
nondiegetic_channels = channels - acn_channels;
if (nondiegetic_channels != 0 && nondiegetic_channels != 2)
return OPUS_BAD_ARG;
if (order_plus_one)
*order_plus_one = order_plus_one_;
return OPUS_OK;
}
static int get_streams_from_channels(int channels, int mapping_family,
int *streams, int *coupled_streams,
int *order_plus_one)
{
if (mapping_family == 3)
{
if (get_order_plus_one_from_channels(channels, order_plus_one) != OPUS_OK)
return OPUS_BAD_ARG;
if (streams)
*streams = (channels + 1) / 2;
if (coupled_streams)
*coupled_streams = channels / 2;
return OPUS_OK;
}
return OPUS_BAD_ARG;
}
static MappingMatrix *get_mixing_matrix(OpusProjectionEncoder *st)
{
/* void* cast avoids clang -Wcast-align warning */
return (MappingMatrix *)(void*)((char*)st +
align(sizeof(OpusProjectionEncoder)));
}
static MappingMatrix *get_enc_demixing_matrix(OpusProjectionEncoder *st)
{
/* void* cast avoids clang -Wcast-align warning */
return (MappingMatrix *)(void*)((char*)st +
align(sizeof(OpusProjectionEncoder) +
st->mixing_matrix_size_in_bytes));
}
static OpusMSEncoder *get_multistream_encoder(OpusProjectionEncoder *st)
{
/* void* cast avoids clang -Wcast-align warning */
return (OpusMSEncoder *)(void*)((char*)st +
align(sizeof(OpusProjectionEncoder) +
st->mixing_matrix_size_in_bytes +
st->demixing_matrix_size_in_bytes));
}
opus_int32 opus_projection_ambisonics_encoder_get_size(int channels,
int mapping_family)
{
int nb_streams;
int nb_coupled_streams;
int order_plus_one;
int mixing_matrix_rows, mixing_matrix_cols;
int demixing_matrix_rows, demixing_matrix_cols;
opus_int32 mixing_matrix_size, demixing_matrix_size;
opus_int32 encoder_size;
int ret;
ret = get_streams_from_channels(channels, mapping_family, &nb_streams,
&nb_coupled_streams, &order_plus_one);
if (ret != OPUS_OK)
return 0;
if (order_plus_one == 2)
{
mixing_matrix_rows = mapping_matrix_foa_mixing.rows;
mixing_matrix_cols = mapping_matrix_foa_mixing.cols;
demixing_matrix_rows = mapping_matrix_foa_demixing.rows;
demixing_matrix_cols = mapping_matrix_foa_demixing.cols;
}
else if (order_plus_one == 3)
{
mixing_matrix_rows = mapping_matrix_soa_mixing.rows;
mixing_matrix_cols = mapping_matrix_soa_mixing.cols;
demixing_matrix_rows = mapping_matrix_soa_demixing.rows;
demixing_matrix_cols = mapping_matrix_soa_demixing.cols;
}
else if (order_plus_one == 4)
{
mixing_matrix_rows = mapping_matrix_toa_mixing.rows;
mixing_matrix_cols = mapping_matrix_toa_mixing.cols;
demixing_matrix_rows = mapping_matrix_toa_demixing.rows;
demixing_matrix_cols = mapping_matrix_toa_demixing.cols;
}
else if (order_plus_one == 5)
{
mixing_matrix_rows = mapping_matrix_fourthoa_mixing.rows;
mixing_matrix_cols = mapping_matrix_fourthoa_mixing.cols;
demixing_matrix_rows = mapping_matrix_fourthoa_demixing.rows;
demixing_matrix_cols = mapping_matrix_fourthoa_demixing.cols;
}
else if (order_plus_one == 6)
{
mixing_matrix_rows = mapping_matrix_fifthoa_mixing.rows;
mixing_matrix_cols = mapping_matrix_fifthoa_mixing.cols;
demixing_matrix_rows = mapping_matrix_fifthoa_demixing.rows;
demixing_matrix_cols = mapping_matrix_fifthoa_demixing.cols;
}
else
return 0;
mixing_matrix_size =
mapping_matrix_get_size(mixing_matrix_rows, mixing_matrix_cols);
if (!mixing_matrix_size)
return 0;
demixing_matrix_size =
mapping_matrix_get_size(demixing_matrix_rows, demixing_matrix_cols);
if (!demixing_matrix_size)
return 0;
encoder_size =
opus_multistream_encoder_get_size(nb_streams, nb_coupled_streams);
if (!encoder_size)
return 0;
return align(sizeof(OpusProjectionEncoder)) +
mixing_matrix_size + demixing_matrix_size + encoder_size;
}
int opus_projection_ambisonics_encoder_init(OpusProjectionEncoder *st, opus_int32 Fs,
int channels, int mapping_family,
int *streams, int *coupled_streams,
int application)
{
MappingMatrix *mixing_matrix;
MappingMatrix *demixing_matrix;
OpusMSEncoder *ms_encoder;
int i;
int ret;
int order_plus_one;
unsigned char mapping[255];
if (streams == NULL || coupled_streams == NULL) {
return OPUS_BAD_ARG;
}
if (get_streams_from_channels(channels, mapping_family, streams,
coupled_streams, &order_plus_one) != OPUS_OK)
return OPUS_BAD_ARG;
if (mapping_family == 3)
{
/* Assign mixing matrix based on available pre-computed matrices. */
mixing_matrix = get_mixing_matrix(st);
if (order_plus_one == 2)
{
mapping_matrix_init(mixing_matrix, mapping_matrix_foa_mixing.rows,
mapping_matrix_foa_mixing.cols, mapping_matrix_foa_mixing.gain,
mapping_matrix_foa_mixing_data,
sizeof(mapping_matrix_foa_mixing_data));
}
else if (order_plus_one == 3)
{
mapping_matrix_init(mixing_matrix, mapping_matrix_soa_mixing.rows,
mapping_matrix_soa_mixing.cols, mapping_matrix_soa_mixing.gain,
mapping_matrix_soa_mixing_data,
sizeof(mapping_matrix_soa_mixing_data));
}
else if (order_plus_one == 4)
{
mapping_matrix_init(mixing_matrix, mapping_matrix_toa_mixing.rows,
mapping_matrix_toa_mixing.cols, mapping_matrix_toa_mixing.gain,
mapping_matrix_toa_mixing_data,
sizeof(mapping_matrix_toa_mixing_data));
}
else if (order_plus_one == 5)
{
mapping_matrix_init(mixing_matrix, mapping_matrix_fourthoa_mixing.rows,
mapping_matrix_fourthoa_mixing.cols, mapping_matrix_fourthoa_mixing.gain,
mapping_matrix_fourthoa_mixing_data,
sizeof(mapping_matrix_fourthoa_mixing_data));
}
else if (order_plus_one == 6)
{
mapping_matrix_init(mixing_matrix, mapping_matrix_fifthoa_mixing.rows,
mapping_matrix_fifthoa_mixing.cols, mapping_matrix_fifthoa_mixing.gain,
mapping_matrix_fifthoa_mixing_data,
sizeof(mapping_matrix_fifthoa_mixing_data));
}
else
return OPUS_BAD_ARG;
st->mixing_matrix_size_in_bytes = mapping_matrix_get_size(
mixing_matrix->rows, mixing_matrix->cols);
if (!st->mixing_matrix_size_in_bytes)
return OPUS_BAD_ARG;
/* Assign demixing matrix based on available pre-computed matrices. */
demixing_matrix = get_enc_demixing_matrix(st);
if (order_plus_one == 2)
{
mapping_matrix_init(demixing_matrix, mapping_matrix_foa_demixing.rows,
mapping_matrix_foa_demixing.cols, mapping_matrix_foa_demixing.gain,
mapping_matrix_foa_demixing_data,
sizeof(mapping_matrix_foa_demixing_data));
}
else if (order_plus_one == 3)
{
mapping_matrix_init(demixing_matrix, mapping_matrix_soa_demixing.rows,
mapping_matrix_soa_demixing.cols, mapping_matrix_soa_demixing.gain,
mapping_matrix_soa_demixing_data,
sizeof(mapping_matrix_soa_demixing_data));
}
else if (order_plus_one == 4)
{
mapping_matrix_init(demixing_matrix, mapping_matrix_toa_demixing.rows,
mapping_matrix_toa_demixing.cols, mapping_matrix_toa_demixing.gain,
mapping_matrix_toa_demixing_data,
sizeof(mapping_matrix_toa_demixing_data));
}
else if (order_plus_one == 5)
{
mapping_matrix_init(demixing_matrix, mapping_matrix_fourthoa_demixing.rows,
mapping_matrix_fourthoa_demixing.cols, mapping_matrix_fourthoa_demixing.gain,
mapping_matrix_fourthoa_demixing_data,
sizeof(mapping_matrix_fourthoa_demixing_data));
}
else if (order_plus_one == 6)
{
mapping_matrix_init(demixing_matrix, mapping_matrix_fifthoa_demixing.rows,
mapping_matrix_fifthoa_demixing.cols, mapping_matrix_fifthoa_demixing.gain,
mapping_matrix_fifthoa_demixing_data,
sizeof(mapping_matrix_fifthoa_demixing_data));
}
else
return OPUS_BAD_ARG;
st->demixing_matrix_size_in_bytes = mapping_matrix_get_size(
demixing_matrix->rows, demixing_matrix->cols);
if (!st->demixing_matrix_size_in_bytes)
return OPUS_BAD_ARG;
}
else
return OPUS_UNIMPLEMENTED;
/* Ensure matrices are large enough for desired coding scheme. */
if (*streams + *coupled_streams > mixing_matrix->rows ||
channels > mixing_matrix->cols ||
channels > demixing_matrix->rows ||
*streams + *coupled_streams > demixing_matrix->cols)
return OPUS_BAD_ARG;
/* Set trivial mapping so each input channel pairs with a matrix column. */
for (i = 0; i < channels; i++)
mapping[i] = i;
/* Initialize multistream encoder with provided settings. */
ms_encoder = get_multistream_encoder(st);
ret = opus_multistream_encoder_init(ms_encoder, Fs, channels, *streams,
*coupled_streams, mapping, application);
return ret;
}
OpusProjectionEncoder *opus_projection_ambisonics_encoder_create(
opus_int32 Fs, int channels, int mapping_family, int *streams,
int *coupled_streams, int application, int *error)
{
int size;
int ret;
OpusProjectionEncoder *st;
/* Allocate space for the projection encoder. */
size = opus_projection_ambisonics_encoder_get_size(channels, mapping_family);
if (!size) {
if (error)
*error = OPUS_ALLOC_FAIL;
return NULL;
}
st = (OpusProjectionEncoder *)opus_alloc(size);
if (!st)
{
if (error)
*error = OPUS_ALLOC_FAIL;
return NULL;
}
/* Initialize projection encoder with provided settings. */
ret = opus_projection_ambisonics_encoder_init(st, Fs, channels,
mapping_family, streams, coupled_streams, application);
if (ret != OPUS_OK)
{
opus_free(st);
st = NULL;
}
if (error)
*error = ret;
return st;
}
int opus_projection_encode(OpusProjectionEncoder *st, const opus_int16 *pcm,
int frame_size, unsigned char *data,
opus_int32 max_data_bytes)
{
return opus_multistream_encode_native(get_multistream_encoder(st),
opus_projection_copy_channel_in_short, pcm, frame_size, data,
max_data_bytes, 16, downmix_int, 0, get_mixing_matrix(st));
}
int opus_projection_encode24(OpusProjectionEncoder *st, const opus_int32 *pcm,
int frame_size, unsigned char *data,
opus_int32 max_data_bytes)
{
return opus_multistream_encode_native(get_multistream_encoder(st),
opus_projection_copy_channel_in_int24, pcm, frame_size, data,
max_data_bytes, MAX_ENCODING_DEPTH, downmix_int, 0, get_mixing_matrix(st));
}
#ifndef DISABLE_FLOAT_API
int opus_projection_encode_float(OpusProjectionEncoder *st, const float *pcm,
int frame_size, unsigned char *data,
opus_int32 max_data_bytes)
{
return opus_multistream_encode_native(get_multistream_encoder(st),
opus_projection_copy_channel_in_float, pcm, frame_size, data,
max_data_bytes, MAX_ENCODING_DEPTH, downmix_float, 1, get_mixing_matrix(st));
}
#endif
void opus_projection_encoder_destroy(OpusProjectionEncoder *st)
{
opus_free(st);
}
int opus_projection_encoder_ctl(OpusProjectionEncoder *st, int request, ...)
{
va_list ap;
MappingMatrix *demixing_matrix;
OpusMSEncoder *ms_encoder;
int ret = OPUS_OK;
ms_encoder = get_multistream_encoder(st);
demixing_matrix = get_enc_demixing_matrix(st);
va_start(ap, request);
switch(request)
{
case OPUS_PROJECTION_GET_DEMIXING_MATRIX_SIZE_REQUEST:
{
opus_int32 *value = va_arg(ap, opus_int32*);
if (!value)
{
goto bad_arg;
}
*value =
ms_encoder->layout.nb_channels * (ms_encoder->layout.nb_streams
+ ms_encoder->layout.nb_coupled_streams) * sizeof(opus_int16);
}
break;
case OPUS_PROJECTION_GET_DEMIXING_MATRIX_GAIN_REQUEST:
{
opus_int32 *value = va_arg(ap, opus_int32*);
if (!value)
{
goto bad_arg;
}
*value = demixing_matrix->gain;
}
break;
case OPUS_PROJECTION_GET_DEMIXING_MATRIX_REQUEST:
{
int i, j, k, l;
int nb_input_streams;
int nb_output_streams;
unsigned char *external_char;
opus_int16 *internal_short;
opus_int32 external_size;
opus_int32 internal_size;
/* (I/O is in relation to the decoder's perspective). */
nb_input_streams = ms_encoder->layout.nb_streams +
ms_encoder->layout.nb_coupled_streams;
nb_output_streams = ms_encoder->layout.nb_channels;
external_char = va_arg(ap, unsigned char *);
external_size = va_arg(ap, opus_int32);
if (!external_char)
{
goto bad_arg;
}
internal_short = mapping_matrix_get_data(demixing_matrix);
internal_size = nb_input_streams * nb_output_streams * sizeof(opus_int16);
if (external_size != internal_size)
{
goto bad_arg;
}
/* Copy demixing matrix subset to output destination. */
l = 0;
for (i = 0; i < nb_input_streams; i++) {
for (j = 0; j < nb_output_streams; j++) {
k = demixing_matrix->rows * i + j;
external_char[2*l] = (unsigned char)internal_short[k];
external_char[2*l+1] = (unsigned char)(internal_short[k] >> 8);
l++;
}
}
}
break;
default:
{
ret = opus_multistream_encoder_ctl_va_list(ms_encoder, request, ap);
}
break;
}
va_end(ap);
return ret;
bad_arg:
va_end(ap);
return OPUS_BAD_ARG;
}
+468
View File
@@ -0,0 +1,468 @@
/* 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 "config.h"
#endif
#include "opus.h"
#include "opus_private.h"
#include "os_support.h"
#include "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;
rp->padding_nb_frames[rp->nb_frames]=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->padding_nb_frames[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],
rp->padding_nb_frames[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 j, ret;
opus_int32 frame_ext_count;
frame_ext_count = total_ext_count - ext_count;
ret = opus_packet_extensions_parse(rp->paddings[i], rp->padding_len[i],
&all_extensions[ext_count], &frame_ext_count, rp->padding_nb_frames[i]);
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, count, 0);
if (ext_len < 0) return ext_len;
if (!pad)
pad_amount = ext_len + (ext_len ? (ext_len+253)/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, 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;
}
+45
View File
@@ -0,0 +1,45 @@
/* This file is auto-generated by gen_tables */
static const float tansig_table[201] = {
0.000000f, 0.039979f, 0.079830f, 0.119427f, 0.158649f,
0.197375f, 0.235496f, 0.272905f, 0.309507f, 0.345214f,
0.379949f, 0.413644f, 0.446244f, 0.477700f, 0.507977f,
0.537050f, 0.564900f, 0.591519f, 0.616909f, 0.641077f,
0.664037f, 0.685809f, 0.706419f, 0.725897f, 0.744277f,
0.761594f, 0.777888f, 0.793199f, 0.807569f, 0.821040f,
0.833655f, 0.845456f, 0.856485f, 0.866784f, 0.876393f,
0.885352f, 0.893698f, 0.901468f, 0.908698f, 0.915420f,
0.921669f, 0.927473f, 0.932862f, 0.937863f, 0.942503f,
0.946806f, 0.950795f, 0.954492f, 0.957917f, 0.961090f,
0.964028f, 0.966747f, 0.969265f, 0.971594f, 0.973749f,
0.975743f, 0.977587f, 0.979293f, 0.980869f, 0.982327f,
0.983675f, 0.984921f, 0.986072f, 0.987136f, 0.988119f,
0.989027f, 0.989867f, 0.990642f, 0.991359f, 0.992020f,
0.992631f, 0.993196f, 0.993718f, 0.994199f, 0.994644f,
0.995055f, 0.995434f, 0.995784f, 0.996108f, 0.996407f,
0.996682f, 0.996937f, 0.997172f, 0.997389f, 0.997590f,
0.997775f, 0.997946f, 0.998104f, 0.998249f, 0.998384f,
0.998508f, 0.998623f, 0.998728f, 0.998826f, 0.998916f,
0.999000f, 0.999076f, 0.999147f, 0.999213f, 0.999273f,
0.999329f, 0.999381f, 0.999428f, 0.999472f, 0.999513f,
0.999550f, 0.999585f, 0.999617f, 0.999646f, 0.999673f,
0.999699f, 0.999722f, 0.999743f, 0.999763f, 0.999781f,
0.999798f, 0.999813f, 0.999828f, 0.999841f, 0.999853f,
0.999865f, 0.999875f, 0.999885f, 0.999893f, 0.999902f,
0.999909f, 0.999916f, 0.999923f, 0.999929f, 0.999934f,
0.999939f, 0.999944f, 0.999948f, 0.999952f, 0.999956f,
0.999959f, 0.999962f, 0.999965f, 0.999968f, 0.999970f,
0.999973f, 0.999975f, 0.999977f, 0.999978f, 0.999980f,
0.999982f, 0.999983f, 0.999984f, 0.999986f, 0.999987f,
0.999988f, 0.999989f, 0.999990f, 0.999990f, 0.999991f,
0.999992f, 0.999992f, 0.999993f, 0.999994f, 0.999994f,
0.999994f, 0.999995f, 0.999995f, 0.999996f, 0.999996f,
0.999996f, 0.999997f, 0.999997f, 0.999997f, 0.999997f,
0.999997f, 0.999998f, 0.999998f, 0.999998f, 0.999998f,
0.999998f, 0.999998f, 0.999999f, 0.999999f, 0.999999f,
0.999999f, 0.999999f, 0.999999f, 0.999999f, 0.999999f,
0.999999f, 0.999999f, 0.999999f, 0.999999f, 0.999999f,
1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f,
1.000000f,
};