Rename (already updated) opus-1.1 to opus-1.1.4

This commit is contained in:
Zack Middleton 2017-05-23 10:53:22 -05:00
parent 853110d5d4
commit ef8ad54421
279 changed files with 140 additions and 140 deletions

View file

@ -0,0 +1,672 @@
/* 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
#include "kiss_fft.h"
#include "celt.h"
#include "modes.h"
#include "arch.h"
#include "quant_bands.h"
#include <stdio.h>
#include "analysis.h"
#include "mlp.h"
#include "stack_alloc.h"
#ifndef M_PI
#define M_PI 3.141592653
#endif
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] = {
2, 4, 6, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, 68, 80, 96, 120
};
static const int extra_bands[NB_TOT_BANDS+1] = {
1, 2, 4, 6, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, 68, 80, 96, 120, 160, 200
};
/*static const float tweight[NB_TBANDS+1] = {
.3, .4, .5, .6, .7, .8, .9, 1., 1., 1., 1., 1., 1., 1., .8, .7, .6, .5
};*/
#define NB_TONAL_SKIP_BANDS 9
#define cA 0.43157974f
#define cB 0.67848403f
#define cC 0.08595542f
#define cE ((float)M_PI/2)
static OPUS_INLINE float fast_atan2f(float y, float x) {
float x2, y2;
/* Should avoid underflow on the values we'll get */
if (ABS16(x)+ABS16(y)<1e-9f)
{
x*=1e12f;
y*=1e12f;
}
x2 = x*x;
y2 = y*y;
if(x2<y2){
float den = (y2 + cB*x2) * (y2 + cC*x2);
if (den!=0)
return -x*y*(y2 + cA*x2) / den + (y<0 ? -cE : cE);
else
return (y<0 ? -cE : cE);
}else{
float den = (x2 + cB*y2) * (x2 + cC*y2);
if (den!=0)
return x*y*(x2 + cA*y2) / den + (y<0 ? -cE : cE) - (x*y<0 ? -cE : cE);
else
return (y<0 ? -cE : cE) - (x*y<0 ? -cE : cE);
}
}
void tonality_analysis_init(TonalityAnalysisState *tonal)
{
/* Initialize reusable fields. */
tonal->arch = opus_select_arch();
/* 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 psum;
int i;
pos = tonal->read_pos;
curr_lookahead = tonal->write_pos-tonal->read_pos;
if (curr_lookahead<0)
curr_lookahead += DETECT_SIZE;
if (len > 480 && pos != tonal->write_pos)
{
pos++;
if (pos==DETECT_SIZE)
pos=0;
}
if (pos == tonal->write_pos)
pos--;
if (pos<0)
pos = DETECT_SIZE-1;
OPUS_COPY(info_out, &tonal->info[pos], 1);
tonal->read_subframe += len/120;
while (tonal->read_subframe>=4)
{
tonal->read_subframe -= 4;
tonal->read_pos++;
}
if (tonal->read_pos>=DETECT_SIZE)
tonal->read_pos-=DETECT_SIZE;
/* Compensate for the delay in the features themselves.
FIXME: Need a better estimate the 10 I just made up */
curr_lookahead = IMAX(curr_lookahead-10, 0);
psum=0;
/* Summing the probability of transition patterns that involve music at
time (DETECT_SIZE-curr_lookahead-1) */
for (i=0;i<DETECT_SIZE-curr_lookahead;i++)
psum += tonal->pmusic[i];
for (;i<DETECT_SIZE;i++)
psum += tonal->pspeech[i];
psum = psum*tonal->music_confidence + (1-psum)*tonal->speech_confidence;
/*printf("%f %f %f\n", psum, info_out->music_prob, info_out->tonality);*/
info_out->music_prob = psum;
}
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 bandwidth=0;
float maxE = 0;
float noise_floor;
int remaining;
AnalysisInfo *info;
SAVE_STACK;
tonal->last_transition++;
alpha = 1.f/IMIN(20, 1+tonal->count);
alphaE = 1.f/IMIN(50, 1+tonal->count);
alphaE2 = 1.f/IMIN(1000, 1+tonal->count);
if (tonal->count<4)
tonal->music_prob = .5;
kfft = celt_mode->mdct.kfft[0];
if (tonal->count==0)
tonal->mem_fill = 240;
downmix(x, &tonal->inmem[tonal->mem_fill], IMIN(len, ANALYSIS_BUF_SIZE-tonal->mem_fill), offset, c1, c2, C);
if (tonal->mem_fill+len < ANALYSIS_BUF_SIZE)
{
tonal->mem_fill += len;
/* Don't have enough to update the analysis */
RESTORE_STACK;
return;
}
info = &tonal->info[tonal->write_pos++];
if (tonal->write_pos>=DETECT_SIZE)
tonal->write_pos-=DETECT_SIZE;
ALLOC(in, 480, kiss_fft_cpx);
ALLOC(out, 480, kiss_fft_cpx);
ALLOC(tonality, 240, float);
ALLOC(noisiness, 240, float);
for (i=0;i<N2;i++)
{
float w = analysis_window[i];
in[i].r = (kiss_fft_scalar)(w*tonal->inmem[i]);
in[i].i = (kiss_fft_scalar)(w*tonal->inmem[N2+i]);
in[N-i-1].r = (kiss_fft_scalar)(w*tonal->inmem[N-i-1]);
in[N-i-1].i = (kiss_fft_scalar)(w*tonal->inmem[N+N2-i-1]);
}
OPUS_MOVE(tonal->inmem, tonal->inmem+ANALYSIS_BUF_SIZE-240, 240);
remaining = len - (ANALYSIS_BUF_SIZE-tonal->mem_fill);
downmix(x, &tonal->inmem[240], remaining, offset+ANALYSIS_BUF_SIZE-tonal->mem_fill, c1, c2, C);
tonal->mem_fill = 240 + remaining;
opus_fft(kfft, in, out, tonal->arch);
#ifndef FIXED_POINT
/* If there's any NaN on the input, the entire output will be NaN, so we only need to check one value. */
if (celt_isnan(out[0].r))
{
info->valid = 0;
RESTORE_STACK;
return;
}
#endif
for (i=1;i<N2;i++)
{
float X1r, X2r, X1i, X2i;
float angle, d_angle, d2_angle;
float angle2, d_angle2, d2_angle2;
float mod1, mod2, avg_mod;
X1r = (float)out[i].r+out[N-i].r;
X1i = (float)out[i].i-out[N-i].i;
X2r = (float)out[i].i+out[N-i].i;
X2i = (float)out[N-i].r-out[i].r;
angle = (float)(.5f/M_PI)*fast_atan2f(X1i, X1r);
d_angle = angle - A[i];
d2_angle = d_angle - dA[i];
angle2 = (float)(.5f/M_PI)*fast_atan2f(X2i, X2r);
d_angle2 = angle2 - angle;
d2_angle2 = d_angle2 - d_angle;
mod1 = d2_angle - (float)floor(.5+d2_angle);
noisiness[i] = ABS16(mod1);
mod1 *= mod1;
mod1 *= mod1;
mod2 = d2_angle2 - (float)floor(.5+d2_angle2);
noisiness[i] += ABS16(mod2);
mod2 *= mod2;
mod2 *= mod2;
avg_mod = .25f*(d2A[i]+2.f*mod1+mod2);
tonality[i] = 1.f/(1.f+40.f*16.f*pi4*avg_mod)-.015f;
A[i] = angle2;
dA[i] = d_angle2;
d2A[i] = mod2;
}
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;
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;
#ifdef FIXED_POINT
/* FIXME: It's probably best to change the BFCC filter initial state instead */
binE *= 5.55e-17f;
#endif
E += binE;
tE += binE*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);
tonal->lowE[b] = MIN32(logE[b], tonal->lowE[b]+.01f);
tonal->highE[b] = MAX32(logE[b], tonal->highE[b]-.1f);
if (tonal->highE[b] < tonal->lowE[b]+1.f)
{
tonal->highE[b]+=.5f;
tonal->lowE[b]-=.5f;
}
relativeE += (logE[b]-tonal->lowE[b])/(1e-15f+tonal->highE[b]-tonal->lowE[b]);
L1=L2=0;
for (i=0;i<NB_FRAMES;i++)
{
L1 += (float)sqrt(tonal->E[i][b]);
L2 += tonal->E[i][b];
}
stationarity = MIN16(0.99f,L1/(float)sqrt(1e-15+NB_FRAMES*L2));
stationarity *= stationarity;
stationarity *= stationarity;
frame_stationarity += stationarity;
/*band_tonality[b] = tE/(1e-15+E)*/;
band_tonality[b] = MAX16(tE/(1e-15f+E), stationarity*tonal->prev_band_tonality[b]);
#if 0
if (b>=NB_TONAL_SKIP_BANDS)
{
frame_tonality += tweight[b]*band_tonality[b];
tw_sum += tweight[b];
}
#else
frame_tonality += band_tonality[b];
if (b>=NB_TBANDS-NB_TONAL_SKIP_BANDS)
frame_tonality -= band_tonality[b-NB_TBANDS+NB_TONAL_SKIP_BANDS];
#endif
max_frame_tonality = MAX16(max_frame_tonality, (1.f+.03f*(b-NB_TBANDS))*frame_tonality);
slope += band_tonality[b]*(b-8);
/*printf("%f %f ", band_tonality[b], stationarity);*/
tonal->prev_band_tonality[b] = band_tonality[b];
}
bandwidth_mask = 0;
bandwidth = 0;
maxE = 0;
noise_floor = 5.7e-4f/(1<<(IMAX(0,lsb_depth-8)));
#ifdef FIXED_POINT
noise_floor *= 1<<(15+SIG_SHIFT);
#endif
noise_floor *= noise_floor;
for (b=0;b<NB_TOT_BANDS;b++)
{
float E=0;
int band_start, band_end;
/* Keep a margin of 300 Hz for aliasing */
band_start = extra_bands[b];
band_end = extra_bands[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;
}
maxE = MAX32(maxE, E);
tonal->meanE[b] = MAX32((1-alphaE2)*tonal->meanE[b], E);
E = MAX32(E, tonal->meanE[b]);
/* Use a simple follower with 13 dB/Bark slope for spreading function */
bandwidth_mask = MAX32(.05f*bandwidth_mask, E);
/* Consider the band "active" only if all these conditions are met:
1) less than 10 dB below the simple follower
2) less than 90 dB below the peak band (maximal masking possible considering
both the ATH and the loudness-dependent slope of the spreading function)
3) above the PCM quantization noise floor
*/
if (E>.1*bandwidth_mask && E*1e9f > maxE && E > noise_floor*(band_end-band_start))
bandwidth = b;
}
if (tonal->count<=2)
bandwidth = 20;
frame_loudness = 20*(float)log10(frame_loudness);
tonal->Etracker = MAX32(tonal->Etracker-.03f, 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;
}
frame_stationarity /= NB_TBANDS;
relativeE /= NB_TBANDS;
if (tonal->count<10)
relativeE = .5;
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++;
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<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]);
features[20] = info->tonality;
features[21] = info->activity;
features[22] = frame_stationarity;
features[23] = info->tonality_slope;
features[24] = tonal->lowECount;
#ifndef DISABLE_FLOAT_API
mlp_process(&net, features, frame_probs);
frame_probs[0] = .5f*(frame_probs[0]+1);
/* Curve fitting between the MLP probability and the actual probability */
frame_probs[0] = .01f + 1.21f*frame_probs[0]*frame_probs[0] - .23f*(float)pow(frame_probs[0], 10);
/* Probability of active audio (as opposed to silence) */
frame_probs[1] = .5f*frame_probs[1]+.5f;
/* Consider that silence has a 50-50 probability. */
frame_probs[0] = frame_probs[1]*frame_probs[0] + (1-frame_probs[1])*.5f;
/*printf("%f %f ", frame_probs[0], frame_probs[1]);*/
{
/* Probability of state transition */
float tau;
/* Represents independence of the MLP probabilities, where
beta=1 means fully independent. */
float beta;
/* Denormalized probability of speech (p0) and music (p1) after update */
float p0, p1;
/* Probabilities for "all speech" and "all music" */
float s0, m0;
/* Probability sum for renormalisation */
float psum;
/* Instantaneous probability of speech and music, with beta pre-applied. */
float speech0;
float music0;
float p, q;
/* One transition every 3 minutes of active audio */
tau = .00005f*frame_probs[1];
/* Adapt beta based on how "unexpected" the new prob is */
p = MAX16(.05f,MIN16(.95f,frame_probs[0]));
q = MAX16(.05f,MIN16(.95f,tonal->music_prob));
beta = .01f+.05f*ABS16(p-q)/(p*(1-q)+q*(1-p));
/* p0 and p1 are the probabilities of speech and music at this frame
using only information from previous frame and applying the
state transition model */
p0 = (1-tonal->music_prob)*(1-tau) + tonal->music_prob *tau;
p1 = tonal->music_prob *(1-tau) + (1-tonal->music_prob)*tau;
/* We apply the current probability with exponent beta to work around
the fact that the probability estimates aren't independent. */
p0 *= (float)pow(1-frame_probs[0], beta);
p1 *= (float)pow(frame_probs[0], beta);
/* Normalise the probabilities to get the Marokv probability of music. */
tonal->music_prob = p1/(p0+p1);
info->music_prob = tonal->music_prob;
/* This chunk of code deals with delayed decision. */
psum=1e-20f;
/* Instantaneous probability of speech and music, with beta pre-applied. */
speech0 = (float)pow(1-frame_probs[0], beta);
music0 = (float)pow(frame_probs[0], beta);
if (tonal->count==1)
{
tonal->pspeech[0]=.5;
tonal->pmusic [0]=.5;
}
/* Updated probability of having only speech (s0) or only music (m0),
before considering the new observation. */
s0 = tonal->pspeech[0] + tonal->pspeech[1];
m0 = tonal->pmusic [0] + tonal->pmusic [1];
/* Updates s0 and m0 with instantaneous probability. */
tonal->pspeech[0] = s0*(1-tau)*speech0;
tonal->pmusic [0] = m0*(1-tau)*music0;
/* Propagate the transition probabilities */
for (i=1;i<DETECT_SIZE-1;i++)
{
tonal->pspeech[i] = tonal->pspeech[i+1]*speech0;
tonal->pmusic [i] = tonal->pmusic [i+1]*music0;
}
/* Probability that the latest frame is speech, when all the previous ones were music. */
tonal->pspeech[DETECT_SIZE-1] = m0*tau*speech0;
/* Probability that the latest frame is music, when all the previous ones were speech. */
tonal->pmusic [DETECT_SIZE-1] = s0*tau*music0;
/* Renormalise probabilities to 1 */
for (i=0;i<DETECT_SIZE;i++)
psum += tonal->pspeech[i] + tonal->pmusic[i];
psum = 1.f/psum;
for (i=0;i<DETECT_SIZE;i++)
{
tonal->pspeech[i] *= psum;
tonal->pmusic [i] *= psum;
}
psum = tonal->pmusic[0];
for (i=1;i<DETECT_SIZE;i++)
psum += tonal->pspeech[i];
/* Estimate our confidence in the speech/music decisions */
if (frame_probs[1]>.75)
{
if (tonal->music_prob>.9)
{
float adapt;
adapt = 1.f/(++tonal->music_confidence_count);
tonal->music_confidence_count = IMIN(tonal->music_confidence_count, 500);
tonal->music_confidence += adapt*MAX16(-.2f,frame_probs[0]-tonal->music_confidence);
}
if (tonal->music_prob<.1)
{
float adapt;
adapt = 1.f/(++tonal->speech_confidence_count);
tonal->speech_confidence_count = IMIN(tonal->speech_confidence_count, 500);
tonal->speech_confidence += adapt*MIN16(.2f,frame_probs[0]-tonal->speech_confidence);
}
} else {
if (tonal->music_confidence_count==0)
tonal->music_confidence = .9f;
if (tonal->speech_confidence_count==0)
tonal->speech_confidence = .1f;
}
}
if (tonal->last_music != (tonal->music_prob>.5f))
tonal->last_transition=0;
tonal->last_music = tonal->music_prob>.5f;
#else
info->music_prob = 0;
#endif
/*for (i=0;i<25;i++)
printf("%f ", features[i]);
printf("\n");*/
info->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;
if (analysis_pcm != NULL)
{
/* Avoid overflow/wrap-around of the analysis buffer */
analysis_frame_size = IMIN((DETECT_SIZE-5)*Fs/100, analysis_frame_size);
pcm_len = analysis_frame_size - analysis->analysis_offset;
offset = analysis->analysis_offset;
do {
tonality_analysis(analysis, celt_mode, analysis_pcm, IMIN(480, pcm_len), offset, c1, c2, C, lsb_depth, downmix);
offset += 480;
pcm_len -= 480;
} while (pcm_len>0);
analysis->analysis_offset = analysis_frame_size;
analysis->analysis_offset -= frame_size;
}
analysis_info->valid = 0;
tonality_get_info(analysis, analysis_info, frame_size);
}

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"
#define NB_FRAMES 8
#define NB_TBANDS 18
#define NB_TOT_BANDS 21
#define ANALYSIS_BUF_SIZE 720 /* 15 ms at 48 kHz */
#define DETECT_SIZE 200
typedef struct {
int arch;
#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;
float E[NB_FRAMES][NB_TBANDS];
float lowE[NB_TBANDS];
float highE[NB_TBANDS];
float meanE[NB_TOT_BANDS];
float mem[32];
float cmean[8];
float std[9];
float music_prob;
float Etracker;
float lowECount;
int E_count;
int last_music;
int last_transition;
int count;
float subframe_mem[3];
int analysis_offset;
/** Probability of having speech for time i to DETECT_SIZE-1 (and music before).
pspeech[0] is the probability that all frames in the window are speech. */
float pspeech[DETECT_SIZE];
/** Probability of having music for time i to DETECT_SIZE-1 (and speech before).
pmusic[0] is the probability that all frames in the window are music. */
float pmusic[DETECT_SIZE];
float speech_confidence;
float music_confidence;
int speech_confidence_count;
int music_confidence_count;
int write_pos;
int read_pos;
int read_subframe;
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);
/** Reset a TonalityAnalysisState stuct.
*
* Call this when there's a discontinuity in the data.
*/
void tonality_analysis_reset(TonalityAnalysisState *analysis);
void tonality_get_info(TonalityAnalysisState *tonal, AnalysisInfo *info_out, int len);
void run_analysis(TonalityAnalysisState *analysis, const CELTMode *celt_mode, const void *analysis_pcm,
int analysis_frame_size, int frame_size, int c1, int c2, int C, opus_int32 Fs,
int lsb_depth, downmix_func downmix, AnalysisInfo *analysis_info);
#endif

145
code/opus-1.1.4/src/mlp.c Normal file
View file

@ -0,0 +1,145 @@
/* Copyright (c) 2008-2011 Octasic Inc.
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
#include "opus_types.h"
#include "opus_defines.h"
#include <math.h>
#include "mlp.h"
#include "arch.h"
#include "tansig_table.h"
#define MAX_NEURONS 100
#if 0
static OPUS_INLINE opus_val16 tansig_approx(opus_val32 _x) /* Q19 */
{
int i;
opus_val16 xx; /* Q11 */
/*double x, y;*/
opus_val16 dy, yy; /* Q14 */
/*x = 1.9073e-06*_x;*/
if (_x>=QCONST32(8,19))
return QCONST32(1.,14);
if (_x<=-QCONST32(8,19))
return -QCONST32(1.,14);
xx = EXTRACT16(SHR32(_x, 8));
/*i = lrint(25*x);*/
i = SHR32(ADD32(1024,MULT16_16(25, xx)),11);
/*x -= .04*i;*/
xx -= EXTRACT16(SHR32(MULT16_16(20972,i),8));
/*x = xx*(1./2048);*/
/*y = tansig_table[250+i];*/
yy = tansig_table[250+i];
/*y = yy*(1./16384);*/
dy = 16384-MULT16_16_Q14(yy,yy);
yy = yy + MULT16_16_Q14(MULT16_16_Q11(xx,dy),(16384 - MULT16_16_Q11(yy,xx)));
return yy;
}
#else
/*extern const float tansig_table[501];*/
static OPUS_INLINE float tansig_approx(float x)
{
int i;
float y, dy;
float sign=1;
/* Tests are reversed to catch NaNs */
if (!(x<8))
return 1;
if (!(x>-8))
return -1;
#ifndef FIXED_POINT
/* Another check in case of -ffast-math */
if (celt_isnan(x))
return 0;
#endif
if (x<0)
{
x=-x;
sign=-1;
}
i = (int)floor(.5f+25*x);
x -= .04f*i;
y = tansig_table[i];
dy = 1-y*y;
y = y + x*dy*(1 - y*x);
return sign*y;
}
#endif
#if 0
void mlp_process(const MLP *m, const opus_val16 *in, opus_val16 *out)
{
int j;
opus_val16 hidden[MAX_NEURONS];
const opus_val16 *W = m->weights;
/* Copy to tmp_in */
for (j=0;j<m->topo[1];j++)
{
int k;
opus_val32 sum = SHL32(EXTEND32(*W++),8);
for (k=0;k<m->topo[0];k++)
sum = MAC16_16(sum, in[k],*W++);
hidden[j] = tansig_approx(sum);
}
for (j=0;j<m->topo[2];j++)
{
int k;
opus_val32 sum = SHL32(EXTEND32(*W++),14);
for (k=0;k<m->topo[1];k++)
sum = MAC16_16(sum, hidden[k], *W++);
out[j] = tansig_approx(EXTRACT16(PSHR32(sum,17)));
}
}
#else
void mlp_process(const MLP *m, const float *in, float *out)
{
int j;
float hidden[MAX_NEURONS];
const float *W = m->weights;
/* Copy to tmp_in */
for (j=0;j<m->topo[1];j++)
{
int k;
float sum = *W++;
for (k=0;k<m->topo[0];k++)
sum = sum + in[k]**W++;
hidden[j] = tansig_approx(sum);
}
for (j=0;j<m->topo[2];j++)
{
int k;
float sum = *W++;
for (k=0;k<m->topo[1];k++)
sum = sum + hidden[k]**W++;
out[j] = tansig_approx(sum);
}
}
#endif

43
code/opus-1.1.4/src/mlp.h Normal file
View file

@ -0,0 +1,43 @@
/* Copyright (c) 2008-2011 Octasic Inc.
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 _MLP_H_
#define _MLP_H_
#include "arch.h"
typedef struct {
int layers;
const int *topo;
const float *weights;
} MLP;
extern const MLP net;
void mlp_process(const MLP *m, const float *in, float *out);
#endif /* _MLP_H_ */

View file

@ -0,0 +1,109 @@
/* The contents of this file was automatically generated by mlp_train.c
It contains multi-layer perceptron (MLP) weights. */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "mlp.h"
/* RMS error was 0.138320, seed was 1361535663 */
static const float weights[422] = {
/* hidden layer */
-0.0941125f, -0.302976f, -0.603555f, -0.19393f, -0.185983f,
-0.601617f, -0.0465317f, -0.114563f, -0.103599f, -0.618938f,
-0.317859f, -0.169949f, -0.0702885f, 0.148065f, 0.409524f,
0.548432f, 0.367649f, -0.494393f, 0.764306f, -1.83957f,
0.170849f, 12.786f, -1.08848f, -1.27284f, -16.2606f,
24.1773f, -5.57454f, -0.17276f, -0.163388f, -0.224421f,
-0.0948944f, -0.0728695f, -0.26557f, -0.100283f, -0.0515459f,
-0.146142f, -0.120674f, -0.180655f, 0.12857f, 0.442138f,
-0.493735f, 0.167767f, 0.206699f, -0.197567f, 0.417999f,
1.50364f, -0.773341f, -10.0401f, 0.401872f, 2.97966f,
15.2165f, -1.88905f, -1.19254f, 0.0285397f, -0.00405139f,
0.0707565f, 0.00825699f, -0.0927269f, -0.010393f, -0.00428882f,
-0.00489743f, -0.0709731f, -0.00255992f, 0.0395619f, 0.226424f,
0.0325231f, 0.162175f, -0.100118f, 0.485789f, 0.12697f,
0.285937f, 0.0155637f, 0.10546f, 3.05558f, 1.15059f,
-1.00904f, -1.83088f, 3.31766f, -3.42516f, -0.119135f,
-0.0405654f, 0.00690068f, 0.0179877f, -0.0382487f, 0.00597941f,
-0.0183611f, 0.00190395f, -0.144322f, -0.0435671f, 0.000990594f,
0.221087f, 0.142405f, 0.484066f, 0.404395f, 0.511955f,
-0.237255f, 0.241742f, 0.35045f, -0.699428f, 10.3993f,
2.6507f, -2.43459f, -4.18838f, 1.05928f, 1.71067f,
0.00667811f, -0.0721335f, -0.0397346f, 0.0362704f, -0.11496f,
-0.0235776f, 0.0082161f, -0.0141741f, -0.0329699f, -0.0354253f,
0.00277404f, -0.290654f, -1.14767f, -0.319157f, -0.686544f,
0.36897f, 0.478899f, 0.182579f, -0.411069f, 0.881104f,
-4.60683f, 1.4697f, 0.335845f, -1.81905f, -30.1699f,
5.55225f, 0.0019508f, -0.123576f, -0.0727332f, -0.0641597f,
-0.0534458f, -0.108166f, -0.0937368f, -0.0697883f, -0.0275475f,
-0.192309f, -0.110074f, 0.285375f, -0.405597f, 0.0926724f,
-0.287881f, -0.851193f, -0.099493f, -0.233764f, -1.2852f,
1.13611f, 3.12168f, -0.0699f, -1.86216f, 2.65292f,
-7.31036f, 2.44776f, -0.00111802f, -0.0632786f, -0.0376296f,
-0.149851f, 0.142963f, 0.184368f, 0.123433f, 0.0756158f,
0.117312f, 0.0933395f, 0.0692163f, 0.0842592f, 0.0704683f,
0.0589963f, 0.0942205f, -0.448862f, 0.0262677f, 0.270352f,
-0.262317f, 0.172586f, 2.00227f, -0.159216f, 0.038422f,
10.2073f, 4.15536f, -2.3407f, -0.0550265f, 0.00964792f,
-0.141336f, 0.0274501f, 0.0343921f, -0.0487428f, 0.0950172f,
-0.00775017f, -0.0372492f, -0.00548121f, -0.0663695f, 0.0960506f,
-0.200008f, -0.0412827f, 0.58728f, 0.0515787f, 0.337254f,
0.855024f, 0.668371f, -0.114904f, -3.62962f, -0.467477f,
-0.215472f, 2.61537f, 0.406117f, -1.36373f, 0.0425394f,
0.12208f, 0.0934502f, 0.123055f, 0.0340935f, -0.142466f,
0.035037f, -0.0490666f, 0.0733208f, 0.0576672f, 0.123984f,
-0.0517194f, -0.253018f, 0.590565f, 0.145849f, 0.315185f,
0.221534f, -0.149081f, 0.216161f, -0.349575f, 24.5664f,
-0.994196f, 0.614289f, -18.7905f, -2.83277f, -0.716801f,
-0.347201f, 0.479515f, -0.246027f, 0.0758683f, 0.137293f,
-0.17781f, 0.118751f, -0.00108329f, -0.237334f, 0.355732f,
-0.12991f, -0.0547627f, -0.318576f, -0.325524f, 0.180494f,
-0.0625604f, 0.141219f, 0.344064f, 0.37658f, -0.591772f,
5.8427f, -0.38075f, 0.221894f, -1.41934f, -1.87943e+06f,
1.34114f, 0.0283355f, -0.0447856f, -0.0211466f, -0.0256927f,
0.0139618f, 0.0207934f, -0.0107666f, 0.0110969f, 0.0586069f,
-0.0253545f, -0.0328433f, 0.11872f, -0.216943f, 0.145748f,
0.119808f, -0.0915211f, -0.120647f, -0.0787719f, -0.143644f,
-0.595116f, -1.152f, -1.25335f, -1.17092f, 4.34023f,
-975268.f, -1.37033f, -0.0401123f, 0.210602f, -0.136656f,
0.135962f, -0.0523293f, 0.0444604f, 0.0143928f, 0.00412666f,
-0.0193003f, 0.218452f, -0.110204f, -2.02563f, 0.918238f,
-2.45362f, 1.19542f, -0.061362f, -1.92243f, 0.308111f,
0.49764f, 0.912356f, 0.209272f, -2.34525f, 2.19326f,
-6.47121f, 1.69771f, -0.725123f, 0.0118929f, 0.0377944f,
0.0554003f, 0.0226452f, -0.0704421f, -0.0300309f, 0.0122978f,
-0.0041782f, -0.0686612f, 0.0313115f, 0.039111f, 0.364111f,
-0.0945548f, 0.0229876f, -0.17414f, 0.329795f, 0.114714f,
0.30022f, 0.106997f, 0.132355f, 5.79932f, 0.908058f,
-0.905324f, -3.3561f, 0.190647f, 0.184211f, -0.673648f,
0.231807f, -0.0586222f, 0.230752f, -0.438277f, 0.245857f,
-0.17215f, 0.0876383f, -0.720512f, 0.162515f, 0.0170571f,
0.101781f, 0.388477f, 1.32931f, 1.08548f, -0.936301f,
-2.36958f, -6.71988f, -3.44376f, 2.13818f, 14.2318f,
4.91459f, -3.09052f, -9.69191f, -0.768234f, 1.79604f,
0.0549653f, 0.163399f, 0.0797025f, 0.0343933f, -0.0555876f,
-0.00505673f, 0.0187258f, 0.0326628f, 0.0231486f, 0.15573f,
0.0476223f, -0.254824f, 1.60155f, -0.801221f, 2.55496f,
0.737629f, -1.36249f, -0.695463f, -2.44301f, -1.73188f,
3.95279f, 1.89068f, 0.486087f, -11.3343f, 3.9416e+06f,
/* output layer */
-0.381439f, 0.12115f, -0.906927f, 2.93878f, 1.6388f,
0.882811f, 0.874344f, 1.21726f, -0.874545f, 0.321706f,
0.785055f, 0.946558f, -0.575066f, -3.46553f, 0.884905f,
0.0924047f, -9.90712f, 0.391338f, 0.160103f, -2.04954f,
4.1455f, 0.0684029f, -0.144761f, -0.285282f, 0.379244f,
-1.1584f, -0.0277241f, -9.85f, -4.82386f, 3.71333f,
3.87308f, 3.52558f};
static const int topo[3] = {25, 15, 2};
const MLP net = {
3,
topo,
weights
};

356
code/opus-1.1.4/src/opus.c Normal file
View file

@ -0,0 +1,356 @@
/* Copyright (c) 2011 Xiph.Org Foundation, Skype Limited
Written by Jean-Marc Valin and Koen Vos */
/*
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "opus.h"
#include "opus_private.h"
#ifndef DISABLE_FLOAT_API
OPUS_EXPORT void opus_pcm_soft_clip(float *_x, int N, int C, float *declip_mem)
{
int c;
int i;
float *x;
if (C<1 || N<1 || !_x || !declip_mem) return;
/* First thing: saturate everything to +/- 2 which is the highest level our
non-linearity can handle. At the point where the signal reaches +/-2,
the derivative will be zero anyway, so this doesn't introduce any
discontinuity in the derivative. */
for (i=0;i<N*C;i++)
_x[i] = MAX16(-2.f, MIN16(2.f, _x[i]));
for (c=0;c<C;c++)
{
float a;
float x0;
int curr;
x = _x+c;
a = declip_mem[c];
/* Continue applying the non-linearity from the previous frame to avoid
any discontinuity. */
for (i=0;i<N;i++)
{
if (x[i*C]*a>=0)
break;
x[i*C] = x[i*C]+a*x[i*C]*x[i*C];
}
curr=0;
x0 = x[0];
while(1)
{
int start, end;
float maxval;
int special=0;
int peak_pos;
for (i=curr;i<N;i++)
{
if (x[i*C]>1 || x[i*C]<-1)
break;
}
if (i==N)
{
a=0;
break;
}
peak_pos = i;
start=end=i;
maxval=ABS16(x[i*C]);
/* Look for first zero crossing before clipping */
while (start>0 && x[i*C]*x[(start-1)*C]>=0)
start--;
/* Look for first zero crossing after clipping */
while (end<N && x[i*C]*x[end*C]>=0)
{
/* Look for other peaks until the next zero-crossing. */
if (ABS16(x[end*C])>maxval)
{
maxval = ABS16(x[end*C]);
peak_pos = end;
}
end++;
}
/* Detect the special case where we clip before the first zero crossing */
special = (start==0 && x[i*C]*x[0]>=0);
/* Compute a such that maxval + a*maxval^2 = 1 */
a=(maxval-1)/(maxval*maxval);
/* Slightly boost "a" by 2^-22. This is just enough to ensure -ffast-math
does not cause output values larger than +/-1, but small enough not
to matter even for 24-bit output. */
a += a*2.4e-7;
if (x[i*C]>0)
a = -a;
/* Apply soft clipping */
for (i=start;i<end;i++)
x[i*C] = x[i*C]+a*x[i*C]*x[i*C];
if (special && peak_pos>=2)
{
/* Add a linear ramp from the first sample to the signal peak.
This avoids a discontinuity at the beginning of the frame. */
float delta;
float offset = x0-x[0];
delta = offset / peak_pos;
for (i=curr;i<peak_pos;i++)
{
offset -= delta;
x[i*C] += offset;
x[i*C] = MAX16(-1.f, MIN16(1.f, x[i*C]));
}
}
curr = end;
if (curr==N)
break;
}
declip_mem[c] = a;
}
}
#endif
int encode_size(int size, unsigned char *data)
{
if (size < 252)
{
data[0] = size;
return 1;
} else {
data[0] = 252+(size&0x3);
data[1] = (size-(int)data[0])>>2;
return 2;
}
}
static int parse_size(const unsigned char *data, opus_int32 len, opus_int16 *size)
{
if (len<1)
{
*size = -1;
return -1;
} else if (data[0]<252)
{
*size = data[0];
return 1;
} else if (len<2)
{
*size = -1;
return -1;
} else {
*size = 4*data[1] + data[0];
return 2;
}
}
int opus_packet_get_samples_per_frame(const unsigned char *data,
opus_int32 Fs)
{
int audiosize;
if (data[0]&0x80)
{
audiosize = ((data[0]>>3)&0x3);
audiosize = (Fs<<audiosize)/400;
} else if ((data[0]&0x60) == 0x60)
{
audiosize = (data[0]&0x08) ? Fs/50 : Fs/100;
} else {
audiosize = ((data[0]>>3)&0x3);
if (audiosize == 3)
audiosize = Fs*60/1000;
else
audiosize = (Fs<<audiosize)/100;
}
return audiosize;
}
int opus_packet_parse_impl(const unsigned char *data, opus_int32 len,
int self_delimited, unsigned char *out_toc,
const unsigned char *frames[48], opus_int16 size[48],
int *payload_offset, opus_int32 *packet_offset)
{
int i, bytes;
int count;
int cbr;
unsigned char ch, toc;
int framesize;
opus_int32 last_size;
opus_int32 pad = 0;
const unsigned char *data0 = data;
if (size==NULL || len<0)
return OPUS_BAD_ARG;
if (len==0)
return OPUS_INVALID_PACKET;
framesize = opus_packet_get_samples_per_frame(data, 48000);
cbr = 0;
toc = *data++;
len--;
last_size = len;
switch (toc&0x3)
{
/* One frame */
case 0:
count=1;
break;
/* Two CBR frames */
case 1:
count=2;
cbr = 1;
if (!self_delimited)
{
if (len&0x1)
return OPUS_INVALID_PACKET;
last_size = len/2;
/* If last_size doesn't fit in size[0], we'll catch it later */
size[0] = (opus_int16)last_size;
}
break;
/* Two VBR frames */
case 2:
count = 2;
bytes = parse_size(data, len, size);
len -= bytes;
if (size[0]<0 || size[0] > len)
return OPUS_INVALID_PACKET;
data += bytes;
last_size = len-size[0];
break;
/* Multiple CBR/VBR frames (from 0 to 120 ms) */
default: /*case 3:*/
if (len<1)
return OPUS_INVALID_PACKET;
/* Number of frames encoded in bits 0 to 5 */
ch = *data++;
count = ch&0x3F;
if (count <= 0 || framesize*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 (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);
}

View file

@ -0,0 +1,981 @@
/* Copyright (c) 2010 Xiph.Org Foundation, Skype Limited
Written by Jean-Marc Valin and Koen Vos */
/*
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#ifndef OPUS_BUILD
# error "OPUS_BUILD _MUST_ be defined to build Opus. This probably means you need other defines as well, as in a config.h. See the included build files for details."
#endif
#if defined(__GNUC__) && (__GNUC__ >= 2) && !defined(__OPTIMIZE__) && !defined(OPUS_WILL_BE_SLOW)
# pragma message "You appear to be compiling without optimization, if so opus will be very slow."
#endif
#include <stdarg.h>
#include "celt.h"
#include "opus.h"
#include "entdec.h"
#include "modes.h"
#include "API.h"
#include "stack_alloc.h"
#include "float_cast.h"
#include "opus_private.h"
#include "os_support.h"
#include "structs.h"
#include "define.h"
#include "mathops.h"
#include "cpu_support.h"
struct OpusDecoder {
int celt_dec_offset;
int silk_dec_offset;
int channels;
opus_int32 Fs; /** Sampling rate (at the API level) */
silk_DecControlStruct DecControl;
int decode_gain;
int arch;
/* Everything beyond this point gets cleared on a reset */
#define OPUS_DECODER_RESET_START stream_channels
int stream_channels;
int bandwidth;
int mode;
int prev_mode;
int frame_size;
int prev_redundancy;
int last_packet_duration;
#ifndef FIXED_POINT
opus_val16 softclip_mem[2];
#endif
opus_uint32 rangeFinal;
};
int opus_decoder_get_size(int channels)
{
int silkDecSizeBytes, celtDecSizeBytes;
int ret;
if (channels<1 || channels > 2)
return 0;
ret = silk_Get_Decoder_Size( &silkDecSizeBytes );
if(ret)
return 0;
silkDecSizeBytes = align(silkDecSizeBytes);
celtDecSizeBytes = celt_decoder_get_size(channels);
return align(sizeof(OpusDecoder))+silkDecSizeBytes+celtDecSizeBytes;
}
int opus_decoder_init(OpusDecoder *st, opus_int32 Fs, int channels)
{
void *silk_dec;
CELTDecoder *celt_dec;
int ret, silkDecSizeBytes;
if ((Fs!=48000&&Fs!=24000&&Fs!=16000&&Fs!=12000&&Fs!=8000)
|| (channels!=1&&channels!=2))
return OPUS_BAD_ARG;
OPUS_CLEAR((char*)st, opus_decoder_get_size(channels));
/* Initialize SILK encoder */
ret = silk_Get_Decoder_Size(&silkDecSizeBytes);
if (ret)
return OPUS_INTERNAL_ERROR;
silkDecSizeBytes = align(silkDecSizeBytes);
st->silk_dec_offset = align(sizeof(OpusDecoder));
st->celt_dec_offset = st->silk_dec_offset+silkDecSizeBytes;
silk_dec = (char*)st+st->silk_dec_offset;
celt_dec = (CELTDecoder*)((char*)st+st->celt_dec_offset);
st->stream_channels = st->channels = channels;
st->Fs = Fs;
st->DecControl.API_sampleRate = st->Fs;
st->DecControl.nChannelsAPI = st->channels;
/* Reset decoder */
ret = silk_InitDecoder( silk_dec );
if(ret)return OPUS_INTERNAL_ERROR;
/* Initialize CELT decoder */
ret = celt_decoder_init(celt_dec, Fs, channels);
if(ret!=OPUS_OK)return OPUS_INTERNAL_ERROR;
celt_decoder_ctl(celt_dec, CELT_SET_SIGNALLING(0));
st->prev_mode = 0;
st->frame_size = Fs/400;
st->arch = opus_select_arch();
return OPUS_OK;
}
OpusDecoder *opus_decoder_create(opus_int32 Fs, int channels, int *error)
{
int ret;
OpusDecoder *st;
if ((Fs!=48000&&Fs!=24000&&Fs!=16000&&Fs!=12000&&Fs!=8000)
|| (channels!=1&&channels!=2))
{
if (error)
*error = OPUS_BAD_ARG;
return NULL;
}
st = (OpusDecoder *)opus_alloc(opus_decoder_get_size(channels));
if (st == NULL)
{
if (error)
*error = OPUS_ALLOC_FAIL;
return NULL;
}
ret = opus_decoder_init(st, Fs, channels);
if (error)
*error = ret;
if (ret != OPUS_OK)
{
opus_free(st);
st = NULL;
}
return st;
}
static void smooth_fade(const opus_val16 *in1, const opus_val16 *in2,
opus_val16 *out, int overlap, int channels,
const opus_val16 *window, opus_int32 Fs)
{
int i, c;
int inc = 48000/Fs;
for (c=0;c<channels;c++)
{
for (i=0;i<overlap;i++)
{
opus_val16 w = MULT16_16_Q15(window[i*inc], window[i*inc]);
out[i*channels+c] = SHR32(MAC16_16(MULT16_16(w,in2[i*channels+c]),
Q15ONE-w, in1[i*channels+c]), 15);
}
}
}
static int opus_packet_get_mode(const unsigned char *data)
{
int mode;
if (data[0]&0x80)
{
mode = MODE_CELT_ONLY;
} else if ((data[0]&0x60) == 0x60)
{
mode = MODE_HYBRID;
} else {
mode = MODE_SILK_ONLY;
}
return mode;
}
static int opus_decode_frame(OpusDecoder *st, const unsigned char *data,
opus_int32 len, opus_val16 *pcm, int frame_size, int decode_fec)
{
void *silk_dec;
CELTDecoder *celt_dec;
int i, silk_ret=0, celt_ret=0;
ec_dec dec;
opus_int32 silk_frame_size;
int pcm_silk_size;
VARDECL(opus_int16, pcm_silk);
int pcm_transition_silk_size;
VARDECL(opus_val16, pcm_transition_silk);
int pcm_transition_celt_size;
VARDECL(opus_val16, pcm_transition_celt);
opus_val16 *pcm_transition=NULL;
int redundant_audio_size;
VARDECL(opus_val16, redundant_audio);
int audiosize;
int mode;
int transition=0;
int start_band;
int redundancy=0;
int redundancy_bytes = 0;
int celt_to_silk=0;
int c;
int F2_5, F5, F10, F20;
const opus_val16 *window;
opus_uint32 redundant_rng = 0;
int celt_accum;
ALLOC_STACK;
silk_dec = (char*)st+st->silk_dec_offset;
celt_dec = (CELTDecoder*)((char*)st+st->celt_dec_offset);
F20 = st->Fs/50;
F10 = F20>>1;
F5 = F10>>1;
F2_5 = F5>>1;
if (frame_size < F2_5)
{
RESTORE_STACK;
return OPUS_BUFFER_TOO_SMALL;
}
/* Limit frame_size to avoid excessive stack allocations. */
frame_size = IMIN(frame_size, st->Fs/25*3);
/* Payloads of 1 (2 including ToC) or 0 trigger the PLC/DTX */
if (len<=1)
{
data = NULL;
/* In that case, don't conceal more than what the ToC says */
frame_size = IMIN(frame_size, st->frame_size);
}
if (data != NULL)
{
audiosize = st->frame_size;
mode = st->mode;
ec_dec_init(&dec,(unsigned char*)data,len);
} else {
audiosize = frame_size;
mode = st->prev_mode;
if (mode == 0)
{
/* If we haven't got any packet yet, all we can do is return zeros */
for (i=0;i<audiosize*st->channels;i++)
pcm[i] = 0;
RESTORE_STACK;
return audiosize;
}
/* Avoids trying to run the PLC on sizes other than 2.5 (CELT), 5 (CELT),
10, or 20 (e.g. 12.5 or 30 ms). */
if (audiosize > F20)
{
do {
int ret = opus_decode_frame(st, NULL, 0, pcm, IMIN(audiosize, F20), 0);
if (ret<0)
{
RESTORE_STACK;
return ret;
}
pcm += ret*st->channels;
audiosize -= ret;
} while (audiosize > 0);
RESTORE_STACK;
return frame_size;
} else if (audiosize < F20)
{
if (audiosize > F10)
audiosize = F10;
else if (mode != MODE_SILK_ONLY && audiosize > F5 && audiosize < F10)
audiosize = F5;
}
}
/* In fixed-point, we can tell CELT to do the accumulation on top of the
SILK PCM buffer. This saves some stack space. */
#ifdef FIXED_POINT
celt_accum = (mode != MODE_CELT_ONLY) && (frame_size >= F10);
#else
celt_accum = 0;
#endif
pcm_transition_silk_size = ALLOC_NONE;
pcm_transition_celt_size = ALLOC_NONE;
if (data!=NULL && st->prev_mode > 0 && (
(mode == MODE_CELT_ONLY && st->prev_mode != MODE_CELT_ONLY && !st->prev_redundancy)
|| (mode != MODE_CELT_ONLY && st->prev_mode == MODE_CELT_ONLY) )
)
{
transition = 1;
/* Decide where to allocate the stack memory for pcm_transition */
if (mode == MODE_CELT_ONLY)
pcm_transition_celt_size = F5*st->channels;
else
pcm_transition_silk_size = F5*st->channels;
}
ALLOC(pcm_transition_celt, pcm_transition_celt_size, opus_val16);
if (transition && mode == MODE_CELT_ONLY)
{
pcm_transition = pcm_transition_celt;
opus_decode_frame(st, NULL, 0, pcm_transition, IMIN(F5, audiosize), 0);
}
if (audiosize > frame_size)
{
/*fprintf(stderr, "PCM buffer too small: %d vs %d (mode = %d)\n", audiosize, frame_size, mode);*/
RESTORE_STACK;
return OPUS_BAD_ARG;
} else {
frame_size = audiosize;
}
/* Don't allocate any memory when in CELT-only mode */
pcm_silk_size = (mode != MODE_CELT_ONLY && !celt_accum) ? IMAX(F10, frame_size)*st->channels : ALLOC_NONE;
ALLOC(pcm_silk, pcm_silk_size, opus_int16);
/* SILK processing */
if (mode != MODE_CELT_ONLY)
{
int lost_flag, decoded_samples;
opus_int16 *pcm_ptr;
#ifdef FIXED_POINT
if (celt_accum)
pcm_ptr = pcm;
else
#endif
pcm_ptr = pcm_silk;
if (st->prev_mode==MODE_CELT_ONLY)
silk_InitDecoder( silk_dec );
/* The SILK PLC cannot produce frames of less than 10 ms */
st->DecControl.payloadSize_ms = IMAX(10, 1000 * audiosize / st->Fs);
if (data != NULL)
{
st->DecControl.nChannelsInternal = st->stream_channels;
if( mode == MODE_SILK_ONLY ) {
if( st->bandwidth == OPUS_BANDWIDTH_NARROWBAND ) {
st->DecControl.internalSampleRate = 8000;
} else if( st->bandwidth == OPUS_BANDWIDTH_MEDIUMBAND ) {
st->DecControl.internalSampleRate = 12000;
} else if( st->bandwidth == OPUS_BANDWIDTH_WIDEBAND ) {
st->DecControl.internalSampleRate = 16000;
} else {
st->DecControl.internalSampleRate = 16000;
silk_assert( 0 );
}
} else {
/* Hybrid mode */
st->DecControl.internalSampleRate = 16000;
}
}
lost_flag = data == NULL ? 1 : 2 * decode_fec;
decoded_samples = 0;
do {
/* Call SILK decoder */
int first_frame = decoded_samples == 0;
silk_ret = silk_Decode( silk_dec, &st->DecControl,
lost_flag, first_frame, &dec, pcm_ptr, &silk_frame_size, st->arch );
if( silk_ret ) {
if (lost_flag) {
/* PLC failure should not be fatal */
silk_frame_size = frame_size;
for (i=0;i<frame_size*st->channels;i++)
pcm_ptr[i] = 0;
} else {
RESTORE_STACK;
return OPUS_INTERNAL_ERROR;
}
}
pcm_ptr += silk_frame_size * st->channels;
decoded_samples += silk_frame_size;
} while( decoded_samples < frame_size );
}
start_band = 0;
if (!decode_fec && mode != MODE_CELT_ONLY && data != NULL
&& ec_tell(&dec)+17+20*(st->mode == MODE_HYBRID) <= 8*len)
{
/* Check if we have a redundant 0-8 kHz band */
if (mode == MODE_HYBRID)
redundancy = ec_dec_bit_logp(&dec, 12);
else
redundancy = 1;
if (redundancy)
{
celt_to_silk = ec_dec_bit_logp(&dec, 1);
/* redundancy_bytes will be at least two, in the non-hybrid
case due to the ec_tell() check above */
redundancy_bytes = mode==MODE_HYBRID ?
(opus_int32)ec_dec_uint(&dec, 256)+2 :
len-((ec_tell(&dec)+7)>>3);
len -= redundancy_bytes;
/* This is a sanity check. It should never happen for a valid
packet, so the exact behaviour is not normative. */
if (len*8 < ec_tell(&dec))
{
len = 0;
redundancy_bytes = 0;
redundancy = 0;
}
/* Shrink decoder because of raw bits */
dec.storage -= redundancy_bytes;
}
}
if (mode != MODE_CELT_ONLY)
start_band = 17;
{
int endband=21;
switch(st->bandwidth)
{
case OPUS_BANDWIDTH_NARROWBAND:
endband = 13;
break;
case OPUS_BANDWIDTH_MEDIUMBAND:
case OPUS_BANDWIDTH_WIDEBAND:
endband = 17;
break;
case OPUS_BANDWIDTH_SUPERWIDEBAND:
endband = 19;
break;
case OPUS_BANDWIDTH_FULLBAND:
endband = 21;
break;
}
celt_decoder_ctl(celt_dec, CELT_SET_END_BAND(endband));
celt_decoder_ctl(celt_dec, CELT_SET_CHANNELS(st->stream_channels));
}
if (redundancy)
{
transition = 0;
pcm_transition_silk_size=ALLOC_NONE;
}
ALLOC(pcm_transition_silk, pcm_transition_silk_size, opus_val16);
if (transition && mode != MODE_CELT_ONLY)
{
pcm_transition = pcm_transition_silk;
opus_decode_frame(st, NULL, 0, pcm_transition, IMIN(F5, audiosize), 0);
}
/* Only allocation memory for redundancy if/when needed */
redundant_audio_size = redundancy ? F5*st->channels : ALLOC_NONE;
ALLOC(redundant_audio, redundant_audio_size, opus_val16);
/* 5 ms redundant frame for CELT->SILK*/
if (redundancy && celt_to_silk)
{
celt_decoder_ctl(celt_dec, CELT_SET_START_BAND(0));
celt_decode_with_ec(celt_dec, data+len, redundancy_bytes,
redundant_audio, F5, NULL, 0);
celt_decoder_ctl(celt_dec, OPUS_GET_FINAL_RANGE(&redundant_rng));
}
/* MUST be after PLC */
celt_decoder_ctl(celt_dec, CELT_SET_START_BAND(start_band));
if (mode != MODE_SILK_ONLY)
{
int celt_frame_size = IMIN(F20, frame_size);
/* Make sure to discard any previous CELT state */
if (mode != st->prev_mode && st->prev_mode > 0 && !st->prev_redundancy)
celt_decoder_ctl(celt_dec, OPUS_RESET_STATE);
/* Decode CELT */
celt_ret = celt_decode_with_ec(celt_dec, decode_fec ? NULL : data,
len, pcm, celt_frame_size, &dec, celt_accum);
} else {
unsigned char silence[2] = {0xFF, 0xFF};
if (!celt_accum)
{
for (i=0;i<frame_size*st->channels;i++)
pcm[i] = 0;
}
/* For hybrid -> SILK transitions, we let the CELT MDCT
do a fade-out by decoding a silence frame */
if (st->prev_mode == MODE_HYBRID && !(redundancy && celt_to_silk && st->prev_redundancy) )
{
celt_decoder_ctl(celt_dec, CELT_SET_START_BAND(0));
celt_decode_with_ec(celt_dec, silence, 2, pcm, F2_5, NULL, celt_accum);
}
}
if (mode != MODE_CELT_ONLY && !celt_accum)
{
#ifdef FIXED_POINT
for (i=0;i<frame_size*st->channels;i++)
pcm[i] = SAT16(ADD32(pcm[i], pcm_silk[i]));
#else
for (i=0;i<frame_size*st->channels;i++)
pcm[i] = pcm[i] + (opus_val16)((1.f/32768.f)*pcm_silk[i]);
#endif
}
{
const CELTMode *celt_mode;
celt_decoder_ctl(celt_dec, CELT_GET_MODE(&celt_mode));
window = celt_mode->window;
}
/* 5 ms redundant frame for SILK->CELT */
if (redundancy && !celt_to_silk)
{
celt_decoder_ctl(celt_dec, OPUS_RESET_STATE);
celt_decoder_ctl(celt_dec, CELT_SET_START_BAND(0));
celt_decode_with_ec(celt_dec, data+len, redundancy_bytes, redundant_audio, F5, NULL, 0);
celt_decoder_ctl(celt_dec, OPUS_GET_FINAL_RANGE(&redundant_rng));
smooth_fade(pcm+st->channels*(frame_size-F2_5), redundant_audio+st->channels*F2_5,
pcm+st->channels*(frame_size-F2_5), F2_5, st->channels, window, st->Fs);
}
if (redundancy && celt_to_silk)
{
for (c=0;c<st->channels;c++)
{
for (i=0;i<F2_5;i++)
pcm[st->channels*i+c] = redundant_audio[st->channels*i+c];
}
smooth_fade(redundant_audio+st->channels*F2_5, pcm+st->channels*F2_5,
pcm+st->channels*F2_5, F2_5, st->channels, window, st->Fs);
}
if (transition)
{
if (audiosize >= F5)
{
for (i=0;i<st->channels*F2_5;i++)
pcm[i] = pcm_transition[i];
smooth_fade(pcm_transition+st->channels*F2_5, pcm+st->channels*F2_5,
pcm+st->channels*F2_5, F2_5,
st->channels, window, st->Fs);
} else {
/* Not enough time to do a clean transition, but we do it anyway
This will not preserve amplitude perfectly and may introduce
a bit of temporal aliasing, but it shouldn't be too bad and
that's pretty much the best we can do. In any case, generating this
transition it pretty silly in the first place */
smooth_fade(pcm_transition, pcm,
pcm, F2_5,
st->channels, window, st->Fs);
}
}
if(st->decode_gain)
{
opus_val32 gain;
gain = celt_exp2(MULT16_16_P15(QCONST16(6.48814081e-4f, 25), st->decode_gain));
for (i=0;i<frame_size*st->channels;i++)
{
opus_val32 x;
x = MULT16_32_P16(pcm[i],gain);
pcm[i] = SATURATE(x, 32767);
}
}
if (len <= 1)
st->rangeFinal = 0;
else
st->rangeFinal = dec.rng ^ redundant_rng;
st->prev_mode = mode;
st->prev_redundancy = redundancy && !celt_to_silk;
if (celt_ret>=0)
{
if (OPUS_CHECK_ARRAY(pcm, audiosize*st->channels))
OPUS_PRINT_INT(audiosize);
}
RESTORE_STACK;
return celt_ret < 0 ? celt_ret : audiosize;
}
int opus_decode_native(OpusDecoder *st, const unsigned char *data,
opus_int32 len, opus_val16 *pcm, int frame_size, int decode_fec,
int self_delimited, opus_int32 *packet_offset, int soft_clip)
{
int i, nb_samples;
int count, offset;
unsigned char toc;
int packet_frame_size, packet_bandwidth, packet_mode, packet_stream_channels;
/* 48 x 2.5 ms = 120 ms */
opus_int16 size[48];
if (decode_fec<0 || decode_fec>1)
return OPUS_BAD_ARG;
/* For FEC/PLC, frame_size has to be to have a multiple of 2.5 ms */
if ((decode_fec || len==0 || data==NULL) && frame_size%(st->Fs/400)!=0)
return OPUS_BAD_ARG;
if (len==0 || data==NULL)
{
int pcm_count=0;
do {
int ret;
ret = opus_decode_frame(st, NULL, 0, pcm+pcm_count*st->channels, frame_size-pcm_count, 0);
if (ret<0)
return ret;
pcm_count += ret;
} while (pcm_count < frame_size);
celt_assert(pcm_count == frame_size);
if (OPUS_CHECK_ARRAY(pcm, pcm_count*st->channels))
OPUS_PRINT_INT(pcm_count);
st->last_packet_duration = pcm_count;
return pcm_count;
} else if (len<0)
return OPUS_BAD_ARG;
packet_mode = opus_packet_get_mode(data);
packet_bandwidth = opus_packet_get_bandwidth(data);
packet_frame_size = opus_packet_get_samples_per_frame(data, st->Fs);
packet_stream_channels = opus_packet_get_nb_channels(data);
count = opus_packet_parse_impl(data, len, self_delimited, &toc, NULL,
size, &offset, packet_offset);
if (count<0)
return count;
data += offset;
if (decode_fec)
{
int duration_copy;
int ret;
/* If no FEC can be present, run the PLC (recursive call) */
if (frame_size < packet_frame_size || packet_mode == MODE_CELT_ONLY || st->mode == MODE_CELT_ONLY)
return opus_decode_native(st, NULL, 0, pcm, frame_size, 0, 0, NULL, soft_clip);
/* Otherwise, run the PLC on everything except the size for which we might have FEC */
duration_copy = st->last_packet_duration;
if (frame_size-packet_frame_size!=0)
{
ret = opus_decode_native(st, NULL, 0, pcm, frame_size-packet_frame_size, 0, 0, NULL, soft_clip);
if (ret<0)
{
st->last_packet_duration = duration_copy;
return ret;
}
celt_assert(ret==frame_size-packet_frame_size);
}
/* Complete with FEC */
st->mode = packet_mode;
st->bandwidth = packet_bandwidth;
st->frame_size = packet_frame_size;
st->stream_channels = packet_stream_channels;
ret = opus_decode_frame(st, data, size[0], pcm+st->channels*(frame_size-packet_frame_size),
packet_frame_size, 1);
if (ret<0)
return ret;
else {
if (OPUS_CHECK_ARRAY(pcm, frame_size*st->channels))
OPUS_PRINT_INT(frame_size);
st->last_packet_duration = frame_size;
return frame_size;
}
}
if (count*packet_frame_size > frame_size)
return OPUS_BUFFER_TOO_SMALL;
/* Update the state as the last step to avoid updating it on an invalid packet */
st->mode = packet_mode;
st->bandwidth = packet_bandwidth;
st->frame_size = packet_frame_size;
st->stream_channels = packet_stream_channels;
nb_samples=0;
for (i=0;i<count;i++)
{
int ret;
ret = opus_decode_frame(st, data, size[i], pcm+nb_samples*st->channels, frame_size-nb_samples, 0);
if (ret<0)
return ret;
celt_assert(ret==packet_frame_size);
data += size[i];
nb_samples += ret;
}
st->last_packet_duration = nb_samples;
if (OPUS_CHECK_ARRAY(pcm, nb_samples*st->channels))
OPUS_PRINT_INT(nb_samples);
#ifndef FIXED_POINT
if (soft_clip)
opus_pcm_soft_clip(pcm, nb_samples, st->channels, st->softclip_mem);
else
st->softclip_mem[0]=st->softclip_mem[1]=0;
#endif
return nb_samples;
}
#ifdef FIXED_POINT
int opus_decode(OpusDecoder *st, const unsigned char *data,
opus_int32 len, opus_val16 *pcm, int frame_size, int decode_fec)
{
if(frame_size<=0)
return OPUS_BAD_ARG;
return opus_decode_native(st, data, len, pcm, frame_size, decode_fec, 0, NULL, 0);
}
#ifndef DISABLE_FLOAT_API
int opus_decode_float(OpusDecoder *st, const unsigned char *data,
opus_int32 len, float *pcm, int frame_size, int decode_fec)
{
VARDECL(opus_int16, out);
int ret, i;
int nb_samples;
ALLOC_STACK;
if(frame_size<=0)
{
RESTORE_STACK;
return OPUS_BAD_ARG;
}
if (data != NULL && len > 0 && !decode_fec)
{
nb_samples = opus_decoder_get_nb_samples(st, data, len);
if (nb_samples>0)
frame_size = IMIN(frame_size, nb_samples);
else
return OPUS_INVALID_PACKET;
}
ALLOC(out, frame_size*st->channels, opus_int16);
ret = opus_decode_native(st, data, len, out, frame_size, decode_fec, 0, NULL, 0);
if (ret > 0)
{
for (i=0;i<ret*st->channels;i++)
pcm[i] = (1.f/32768.f)*(out[i]);
}
RESTORE_STACK;
return ret;
}
#endif
#else
int opus_decode(OpusDecoder *st, const unsigned char *data,
opus_int32 len, opus_int16 *pcm, int frame_size, int decode_fec)
{
VARDECL(float, out);
int ret, i;
int nb_samples;
ALLOC_STACK;
if(frame_size<=0)
{
RESTORE_STACK;
return OPUS_BAD_ARG;
}
if (data != NULL && len > 0 && !decode_fec)
{
nb_samples = opus_decoder_get_nb_samples(st, data, len);
if (nb_samples>0)
frame_size = IMIN(frame_size, nb_samples);
else
return OPUS_INVALID_PACKET;
}
ALLOC(out, frame_size*st->channels, float);
ret = opus_decode_native(st, data, len, out, frame_size, decode_fec, 0, NULL, 1);
if (ret > 0)
{
for (i=0;i<ret*st->channels;i++)
pcm[i] = FLOAT2INT16(out[i]);
}
RESTORE_STACK;
return ret;
}
int opus_decode_float(OpusDecoder *st, const unsigned char *data,
opus_int32 len, opus_val16 *pcm, int frame_size, int decode_fec)
{
if(frame_size<=0)
return OPUS_BAD_ARG;
return opus_decode_native(st, data, len, pcm, frame_size, decode_fec, 0, NULL, 0);
}
#endif
int opus_decoder_ctl(OpusDecoder *st, int request, ...)
{
int ret = OPUS_OK;
va_list ap;
void *silk_dec;
CELTDecoder *celt_dec;
silk_dec = (char*)st+st->silk_dec_offset;
celt_dec = (CELTDecoder*)((char*)st+st->celt_dec_offset);
va_start(ap, request);
switch (request)
{
case OPUS_GET_BANDWIDTH_REQUEST:
{
opus_int32 *value = va_arg(ap, opus_int32*);
if (!value)
{
goto bad_arg;
}
*value = st->bandwidth;
}
break;
case OPUS_GET_FINAL_RANGE_REQUEST:
{
opus_uint32 *value = va_arg(ap, opus_uint32*);
if (!value)
{
goto bad_arg;
}
*value = st->rangeFinal;
}
break;
case OPUS_RESET_STATE:
{
OPUS_CLEAR((char*)&st->OPUS_DECODER_RESET_START,
sizeof(OpusDecoder)-
((char*)&st->OPUS_DECODER_RESET_START - (char*)st));
celt_decoder_ctl(celt_dec, OPUS_RESET_STATE);
silk_InitDecoder( silk_dec );
st->stream_channels = st->channels;
st->frame_size = st->Fs/400;
}
break;
case OPUS_GET_SAMPLE_RATE_REQUEST:
{
opus_int32 *value = va_arg(ap, opus_int32*);
if (!value)
{
goto bad_arg;
}
*value = st->Fs;
}
break;
case OPUS_GET_PITCH_REQUEST:
{
opus_int32 *value = va_arg(ap, opus_int32*);
if (!value)
{
goto bad_arg;
}
if (st->prev_mode == MODE_CELT_ONLY)
celt_decoder_ctl(celt_dec, OPUS_GET_PITCH(value));
else
*value = st->DecControl.prevPitchLag;
}
break;
case OPUS_GET_GAIN_REQUEST:
{
opus_int32 *value = va_arg(ap, opus_int32*);
if (!value)
{
goto bad_arg;
}
*value = st->decode_gain;
}
break;
case OPUS_SET_GAIN_REQUEST:
{
opus_int32 value = va_arg(ap, opus_int32);
if (value<-32768 || value>32767)
{
goto bad_arg;
}
st->decode_gain = value;
}
break;
case OPUS_GET_LAST_PACKET_DURATION_REQUEST:
{
opus_uint32 *value = va_arg(ap, opus_uint32*);
if (!value)
{
goto bad_arg;
}
*value = st->last_packet_duration;
}
break;
default:
/*fprintf(stderr, "unknown opus_decoder_ctl() request: %d", request);*/
ret = OPUS_UNIMPLEMENTED;
break;
}
va_end(ap);
return ret;
bad_arg:
va_end(ap);
return OPUS_BAD_ARG;
}
void opus_decoder_destroy(OpusDecoder *st)
{
opus_free(st);
}
int opus_packet_get_bandwidth(const unsigned char *data)
{
int bandwidth;
if (data[0]&0x80)
{
bandwidth = OPUS_BANDWIDTH_MEDIUMBAND + ((data[0]>>5)&0x3);
if (bandwidth == OPUS_BANDWIDTH_MEDIUMBAND)
bandwidth = OPUS_BANDWIDTH_NARROWBAND;
} else if ((data[0]&0x60) == 0x60)
{
bandwidth = (data[0]&0x10) ? OPUS_BANDWIDTH_FULLBAND :
OPUS_BANDWIDTH_SUPERWIDEBAND;
} else {
bandwidth = OPUS_BANDWIDTH_NARROWBAND + ((data[0]>>5)&0x3);
}
return bandwidth;
}
int opus_packet_get_nb_channels(const unsigned char *data)
{
return (data[0]&0x4) ? 2 : 1;
}
int opus_packet_get_nb_frames(const unsigned char packet[], opus_int32 len)
{
int count;
if (len<1)
return OPUS_BAD_ARG;
count = packet[0]&0x3;
if (count==0)
return 1;
else if (count!=3)
return 2;
else if (len<2)
return OPUS_INVALID_PACKET;
else
return packet[1]&0x3F;
}
int opus_packet_get_nb_samples(const unsigned char packet[], opus_int32 len,
opus_int32 Fs)
{
int samples;
int count = opus_packet_get_nb_frames(packet, len);
if (count<0)
return count;
samples = count*opus_packet_get_samples_per_frame(packet, Fs);
/* Can't have more than 120 ms */
if (samples*25 > Fs*3)
return OPUS_INVALID_PACKET;
else
return samples;
}
int opus_decoder_get_nb_samples(const OpusDecoder *dec,
const unsigned char packet[], opus_int32 len)
{
return opus_packet_get_nb_samples(packet, len, dec->Fs);
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,92 @@
/* 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;
}

View file

@ -0,0 +1,537 @@
/* 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"
struct OpusMSDecoder {
ChannelLayout layout;
/* Decoder states go here */
};
/* DECODER */
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;
}
typedef void (*opus_copy_channel_out_func)(
void *dst,
int dst_stride,
int dst_channel,
const opus_val16 *src,
int src_stride,
int frame_size
);
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);
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;
}
static 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
)
{
opus_int32 Fs;
int coupled_size;
int mono_size;
int s, c;
char *ptr;
int do_plc=0;
VARDECL(opus_val16, buf);
ALLOC_STACK;
/* Limit frame_size to avoid excessive stack allocations. */
opus_multistream_decoder_ctl(st, OPUS_GET_SAMPLE_RATE(&Fs));
frame_size = IMIN(frame_size, Fs/25*3);
ALLOC(buf, 2*frame_size, opus_val16);
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;
int packet_offset, 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);
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);
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);
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);
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);
}
}
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_val16 *src,
int src_stride,
int frame_size
)
{
float *float_dst;
opus_int32 i;
float_dst = (float*)dst;
if (src != NULL)
{
for (i=0;i<frame_size;i++)
#if defined(FIXED_POINT)
float_dst[i*dst_stride+dst_channel] = (1/32768.f)*src[i*src_stride];
#else
float_dst[i*dst_stride+dst_channel] = src[i*src_stride];
#endif
}
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_val16 *src,
int src_stride,
int frame_size
)
{
opus_int16 *short_dst;
opus_int32 i;
short_dst = (opus_int16*)dst;
if (src != NULL)
{
for (i=0;i<frame_size;i++)
#if defined(FIXED_POINT)
short_dst[i*dst_stride+dst_channel] = src[i*src_stride];
#else
short_dst[i*dst_stride+dst_channel] = FLOAT2INT16(src[i*src_stride]);
#endif
}
else
{
for (i=0;i<frame_size;i++)
short_dst[i*dst_stride+dst_channel] = 0;
}
}
#ifdef FIXED_POINT
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, 0);
}
#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);
}
#endif
#else
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, 1);
}
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);
}
#endif
int opus_multistream_decoder_ctl(OpusMSDecoder *st, int request, ...)
{
va_list ap;
int coupled_size, mono_size;
char *ptr;
int ret = OPUS_OK;
va_start(ap, request);
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:
{
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)
ret = OPUS_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:
{
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;
}
va_end(ap);
return ret;
bad_arg:
va_end(ap);
return OPUS_BAD_ARG;
}
void opus_multistream_decoder_destroy(OpusMSDecoder *st)
{
opus_free(st);
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,134 @@
/* 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 <stddef.h> /* offsetof */
struct OpusRepacketizer {
unsigned char toc;
int nb_frames;
const unsigned char *frames[48];
opus_int16 len[48];
int framesize;
};
typedef struct ChannelLayout {
int nb_channels;
int nb_streams;
int nb_coupled_streams;
unsigned char mapping[256];
} ChannelLayout;
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);
#define MODE_SILK_ONLY 1000
#define MODE_HYBRID 1001
#define MODE_CELT_ONLY 1002
#define OPUS_SET_VOICE_RATIO_REQUEST 11018
#define OPUS_GET_VOICE_RATIO_REQUEST 11019
/** Configures the encoder's expected percentage of voice
* opposed to music or other signals.
*
* @note This interface is currently more aspiration than actuality. It's
* ultimately expected to bias an automatic signal classifier, but it currently
* just shifts the static bitrate to mode mapping around a little bit.
*
* @param[in] x <tt>int</tt>: Voice percentage in the range 0-100, inclusive.
* @hideinitializer */
#define OPUS_SET_VOICE_RATIO(x) OPUS_SET_VOICE_RATIO_REQUEST, __opus_check_int(x)
/** Gets the encoder's configured voice ratio value, @see OPUS_SET_VOICE_RATIO
*
* @param[out] x <tt>int*</tt>: Voice percentage in the range 0-100, inclusive.
* @hideinitializer */
#define OPUS_GET_VOICE_RATIO(x) OPUS_GET_VOICE_RATIO_REQUEST, __opus_check_int_ptr(x)
#define OPUS_SET_FORCE_MODE_REQUEST 11002
#define OPUS_SET_FORCE_MODE(x) OPUS_SET_FORCE_MODE_REQUEST, __opus_check_int(x)
typedef void (*downmix_func)(const void *, opus_val32 *, int, int, int, int, int);
void downmix_float(const void *_x, opus_val32 *sub, int subframe, int offset, int c1, int c2, int C);
void downmix_int(const void *_x, opus_val32 *sub, int subframe, int offset, int c1, int c2, int C);
int encode_size(int size, unsigned char *data);
opus_int32 frame_size_select(opus_int32 frame_size, int variable_duration, opus_int32 Fs);
opus_int32 compute_frame_size(const void *analysis_pcm, int frame_size,
int variable_duration, int C, opus_int32 Fs, int bitrate_bps,
int delay_compensation, downmix_func downmix
#ifndef DISABLE_FLOAT_API
, float *subframe_mem
#endif
);
opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_size,
unsigned char *data, opus_int32 out_data_bytes, int lsb_depth,
const void *analysis_pcm, opus_int32 analysis_size, int c1, int c2,
int analysis_channels, downmix_func downmix, int float_api);
int opus_decode_native(OpusDecoder *st, const unsigned char *data, opus_int32 len,
opus_val16 *pcm, int frame_size, int decode_fec, int self_delimited,
opus_int32 *packet_offset, int soft_clip);
/* 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);
opus_int32 opus_repacketizer_out_range_impl(OpusRepacketizer *rp, int begin, int end,
unsigned char *data, opus_int32 maxlen, int self_delimited, int pad);
int pad_frame(unsigned char *data, opus_int32 len, opus_int32 new_len);
#endif /* OPUS_PRIVATE_H */

View file

@ -0,0 +1,348 @@
/* 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"
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);
if(ret<1)return ret;
rp->nb_frames += curr_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)
{
int i, count;
opus_int32 tot_size;
opus_int16 *len;
const unsigned char **frames;
unsigned char * ptr;
if (begin<0 || begin>=end || end>rp->nb_frames)
{
/*fprintf(stderr, "%d %d %d\n", begin, end, rp->nb_frames);*/
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;
ptr = data;
if (count==1)
{
/* Code 0 */
tot_size += len[0]+1;
if (tot_size > maxlen)
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)
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)
return OPUS_BUFFER_TOO_SMALL;
*ptr++ = (rp->toc&0xFC) | 0x2;
ptr += encode_size(len[0], ptr);
}
}
if (count > 2 || (pad && tot_size < maxlen))
{
/* 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)
return OPUS_BUFFER_TOO_SMALL;
*ptr++ = (rp->toc&0xFC) | 0x3;
*ptr++ = count | 0x80;
} else {
tot_size += count*len[0]+2;
if (tot_size > maxlen)
return OPUS_BUFFER_TOO_SMALL;
*ptr++ = (rp->toc&0xFC) | 0x3;
*ptr++ = count;
}
pad_amount = pad ? (maxlen-tot_size) : 0;
if (pad_amount != 0)
{
int nb_255s;
data[1] |= 0x40;
nb_255s = (pad_amount-1)/255;
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(). */
celt_assert(frames[i] + len[i] <= data || ptr <= frames[i]);
OPUS_MOVE(ptr, frames[i], len[i]);
ptr += len[i];
}
if (pad)
{
/* Fill padding with zeros. */
while (ptr<data+maxlen)
*ptr++=0;
}
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);
}
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);
}
int opus_packet_pad(unsigned char *data, opus_int32 len, opus_int32 new_len)
{
OpusRepacketizer rp;
opus_int32 ret;
if (len < 1)
return OPUS_BAD_ARG;
if (len==new_len)
return OPUS_OK;
else if (len > new_len)
return OPUS_BAD_ARG;
opus_repacketizer_init(&rp);
/* Moving payload to the end of the packet so we can do in-place padding */
OPUS_MOVE(data+new_len-len, data, len);
ret = opus_repacketizer_cat(&rp, data+new_len-len, len);
if (ret != OPUS_OK)
return ret;
ret = opus_repacketizer_out_range_impl(&rp, 0, rp.nb_frames, data, new_len, 0, 1);
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;
if (len < 1)
return OPUS_BAD_ARG;
opus_repacketizer_init(&rp);
ret = opus_repacketizer_cat(&rp, data, len);
if (ret < 0)
return ret;
ret = opus_repacketizer_out_range_impl(&rp, 0, rp.nb_frames, data, len, 0, 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);
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 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);
if (ret<0)
return ret;
ret = opus_repacketizer_cat_impl(&rp, data, packet_offset, self_delimited);
if (ret < 0)
return ret;
ret = opus_repacketizer_out_range_impl(&rp, 0, rp.nb_frames, dst, len, self_delimited, 0);
if (ret < 0)
return ret;
else
dst_len += ret;
dst += ret;
data += packet_offset;
len -= packet_offset;
}
return dst_len;
}

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,
};