include/opus/opus.h
include/opus/opus_custom.h
include/opus/opus_defines.h
+ include/opus/opus_projection.h
include/opus/opus_multistream.h
include/opus/opus_types.h
celt/vq.c
celt/vq.h
celt/_kiss_fft_guts.h
- celt/x86/celt_lpc_sse.c
+ celt/x86/celt_lpc_sse4_1.c
celt/x86/celt_lpc_sse.h
celt/x86/pitch_sse.c
celt/x86/pitch_sse.h
silk/float/warped_autocorrelation_FLP.c
silk/float/wrappers_FLP.c
silk/x86/main_sse.h
- silk/x86/NSQ_del_dec_sse.c
- silk/x86/NSQ_sse.c
+ silk/x86/NSQ_del_dec_sse4_1.c
+ silk/x86/NSQ_sse4_1.c
silk/x86/SigProc_FIX_sse.h
- silk/x86/VAD_sse.c
- silk/x86/VQ_WMat_EC_sse.c
+ silk/x86/VAD_sse4_1.c
+ silk/x86/VQ_WMat_EC_sse4_1.c
silk/x86/x86_silk_map.c
)
#define CELT_SIG_SCALE 32768.f
-#define celt_fatal(str) _celt_fatal(str, __FILE__, __LINE__);
-#ifdef ENABLE_ASSERTIONS
+#define CELT_FATAL(str) celt_fatal(str, __FILE__, __LINE__);
+
+#if defined(ENABLE_ASSERTIONS) || defined(ENABLE_HARDENING)
+#ifdef __GNUC__
+__attribute__((noreturn))
+#endif
+void celt_fatal(const char *str, const char *file, int line);
+
+#if defined(CELT_C) && !defined(OVERRIDE_celt_fatal)
#include <stdio.h>
#include <stdlib.h>
#ifdef __GNUC__
__attribute__((noreturn))
#endif
-static OPUS_INLINE void _celt_fatal(const char *str, const char *file, int line)
+void celt_fatal(const char *str, const char *file, int line)
{
fprintf (stderr, "Fatal (internal) error in %s, line %d: %s\n", file, line, str);
abort();
}
-#define celt_assert(cond) {if (!(cond)) {celt_fatal("assertion failed: " #cond);}}
-#define celt_assert2(cond, message) {if (!(cond)) {celt_fatal("assertion failed: " #cond "\n" message);}}
+#endif
+
+#define celt_assert(cond) {if (!(cond)) {CELT_FATAL("assertion failed: " #cond);}}
+#define celt_assert2(cond, message) {if (!(cond)) {CELT_FATAL("assertion failed: " #cond "\n" message);}}
+#define MUST_SUCCEED(call) celt_assert((call) == OPUS_OK)
#else
#define celt_assert(cond)
#define celt_assert2(cond, message)
+#define MUST_SUCCEED(call) do {if((call) != OPUS_OK) {RESTORE_STACK; return OPUS_INTERNAL_ERROR;} } while (0)
+#endif
+
+#if defined(ENABLE_ASSERTIONS)
+#define celt_sig_assert(cond) {if (!(cond)) {CELT_FATAL("signal assertion failed: " #cond);}}
+#else
+#define celt_sig_assert(cond)
#endif
#define IMUL32(a,b) ((a)*(b))
typedef opus_val16 celt_norm;
typedef opus_val32 celt_ener;
+#define celt_isnan(x) 0
+
#define Q15ONE 32767
#define SIG_SHIFT 12
/* Copyright (c) 2015 Xiph.Org Foundation
Written by Viswanath Puttagunta */
/**
- @file celt_ne10_fft.c
+ @file celt_fft_ne10.c
@brief ARM Neon optimizations for fft using NE10 library
*/
/* Copyright (c) 2015 Xiph.Org Foundation
Written by Viswanath Puttagunta */
/**
- @file celt_ne10_mdct.c
+ @file celt_mdct_ne10.c
@brief ARM Neon optimizations for mdct using NE10 library
*/
int i;
(void)arch;
celt_assert(max_pitch > 0);
- celt_assert((((unsigned char *)_x-(unsigned char *)NULL)&3)==0);
+ celt_sig_assert((((unsigned char *)_x-(unsigned char *)NULL)&3)==0);
for (i = 0; i < (max_pitch-3); i += 4) {
xcorr_kernel_neon_float((const float32_t *)_x, (const float32_t *)_y+i,
(*const CELT_PITCH_XCORR_IMPL[OPUS_ARCHMASK+1])(const opus_val16 *,
const opus_val16 *, opus_val32 *, int, int, int);
# define OVERRIDE_PITCH_XCORR (1)
-# define celt_pitch_xcorr (*CELT_PITCH_XCORR_IMPL[(arch)&OPUS_ARCHMASK])
+# define celt_pitch_xcorr(_x, _y, xcorr, len, max_pitch, arch) \
+ ((*CELT_PITCH_XCORR_IMPL[(arch)&OPUS_ARCHMASK])(_x, _y, \
+ xcorr, len, max_pitch, arch))
# elif defined(OPUS_ARM_PRESUME_EDSP) || \
defined(OPUS_ARM_PRESUME_MEDIA) || \
const opus_val16 *, opus_val32 *, int, int, int);
# define OVERRIDE_PITCH_XCORR (1)
-# define celt_pitch_xcorr (*CELT_PITCH_XCORR_IMPL[(arch)&OPUS_ARCHMASK])
+# define celt_pitch_xcorr(_x, _y, xcorr, len, max_pitch, arch) \
+ ((*CELT_PITCH_XCORR_IMPL[(arch)&OPUS_ARCHMASK])(_x, _y, \
+ xcorr, len, max_pitch, arch))
# elif defined(OPUS_ARM_PRESUME_NEON_INTR)
opus_int32 tmp;
opus_int16 x2;
tmp = (4096+((opus_int32)(x)*(x)))>>13;
- celt_assert(tmp<=32767);
+ celt_sig_assert(tmp<=32767);
x2 = tmp;
x2 = (32767-x2) + FRAC_MUL16(x2, (-7651 + FRAC_MUL16(x2, (8277 + FRAC_MUL16(-626, x2)))));
- celt_assert(x2<=32766);
+ celt_sig_assert(x2<=32766);
return 1+x2;
}
N0 = m->eBands[i+1]-m->eBands[i];
/* depth in 1/8 bits */
- celt_assert(pulses[i]>=0);
+ celt_sig_assert(pulses[i]>=0);
depth = celt_udiv(1+pulses[i], (m->eBands[i+1]-m->eBands[i]))>>LM;
#ifdef FIXED_POINT
/* Decide whether we should spread the pulses in the current frame */
int spreading_decision(const CELTMode *m, const celt_norm *X, int *average,
int last_decision, int *hf_average, int *tapset_decision, int update_hf,
- int end, int C, int M)
+ int end, int C, int M, const int *spread_weight)
{
int i, c, N0;
int sum = 0, nbBands=0;
if (i>m->nbEBands-4)
hf_sum += celt_udiv(32*(tcount[1]+tcount[0]), N);
tmp = (2*tcount[2] >= N) + (2*tcount[1] >= N) + (2*tcount[0] >= N);
- sum += tmp*256;
- nbBands++;
+ sum += tmp*spread_weight[i];
+ nbBands+=spread_weight[i];
}
} while (++c<C);
/*printf("%d %d %d\n", hf_sum, *hf_average, *tapset_decision);*/
celt_assert(nbBands>0); /* end has to be non-zero */
celt_assert(sum>=0);
- sum = celt_udiv(sum, nbBands);
+ sum = celt_udiv((opus_int32)sum<<8, nbBands);
/* Recursive averaging */
sum = (sum+*average)>>1;
*average = sum;
else
Y = NULL;
N = M*eBands[i+1]-M*eBands[i];
+ celt_assert(N > 0);
tell = ec_tell_frac(ec);
/* Compute how many bits we want to allocate to this band */
b = 0;
}
-#ifdef ENABLE_UPDATE_DRAFT
+#ifndef DISABLE_UPDATE_DRAFT
if (resynth && (M*eBands[i]-N >= M*eBands[start] || i==start+1) && (update_lowband || lowband_offset==0))
lowband_offset = i;
if (i == start+1)
fold_start = lowband_offset;
while(M*eBands[--fold_start] > effective_lowband+norm_offset);
fold_end = lowband_offset-1;
-#ifdef ENABLE_UPDATE_DRAFT
+#ifndef DISABLE_UPDATE_DRAFT
while(++fold_end < i && M*eBands[fold_end] < effective_lowband+norm_offset+N);
#else
while(M*eBands[++fold_end] < effective_lowband+norm_offset+N);
ctx = ctx_save;
OPUS_COPY(X, X_save, N);
OPUS_COPY(Y, Y_save, N);
+#ifndef DISABLE_UPDATE_DRAFT
if (i == start+1)
special_hybrid_folding(m, norm, norm2, start, M, dual_stereo);
+#endif
/* Encode and round up. */
ctx.theta_round = 1;
x_cm = quant_band_stereo(&ctx, X, Y, N, b, B,
int spreading_decision(const CELTMode *m, const celt_norm *X, int *average,
int last_decision, int *hf_average, int *tapset_decision, int update_hf,
- int end, int C, int M);
+ int end, int C, int M, const int *spread_weight);
#ifdef MEASURE_NORM_MSE
void measure_norm_mse(const CELTMode *m, float *X, float *X0, float *bandE, float *bandE0, int M, int N, int C);
float noisiness;
float activity;
float music_prob;
- float vad_prob;
+ float music_prob_min;
+ float music_prob_max;
int bandwidth;
float activity_probability;
+ float max_pitch_ratio;
/* Store as Q6 char to save space. */
unsigned char leak_boost[LEAK_BANDS];
} AnalysisInfo;
extern const signed char tf_select_table[4][8];
+#if defined(ENABLE_HARDENING) || defined(ENABLE_ASSERTIONS)
+void validate_celt_decoder(CELTDecoder *st);
+#define VALIDATE_CELT_DECODER(st) validate_celt_decoder(st)
+#else
+#define VALIDATE_CELT_DECODER(st)
+#endif
+
int resampling_factor(opus_int32 rate);
void celt_preemphasis(const opus_val16 * OPUS_RESTRICT pcmp, celt_sig * OPUS_RESTRICT inp,
#include "celt_lpc.h"
#include "vq.h"
+/* The maximum pitch lag to allow in the pitch-based PLC. It's possible to save
+ CPU time in the PLC pitch search by making this smaller than MAX_PERIOD. The
+ current value corresponds to a pitch of 66.67 Hz. */
+#define PLC_PITCH_LAG_MAX (720)
+/* The minimum pitch lag to allow in the pitch-based PLC. This corresponds to a
+ pitch of 480 Hz. */
+#define PLC_PITCH_LAG_MIN (100)
+
#if defined(SMALL_FOOTPRINT) && defined(FIXED_POINT)
#define NORM_ALIASING_HACK
#endif
/* opus_val16 backgroundLogE[], Size = 2*mode->nbEBands */
};
+#if defined(ENABLE_HARDENING) || defined(ENABLE_ASSERTIONS)
+/* Make basic checks on the CELT state to ensure we don't end
+ up writing all over memory. */
+void validate_celt_decoder(CELTDecoder *st)
+{
+#ifndef CUSTOM_MODES
+ celt_assert(st->mode == opus_custom_mode_create(48000, 960, NULL));
+ celt_assert(st->overlap == 120);
+#endif
+ celt_assert(st->channels == 1 || st->channels == 2);
+ celt_assert(st->stream_channels == 1 || st->stream_channels == 2);
+ celt_assert(st->downsample > 0);
+ celt_assert(st->start == 0 || st->start == 17);
+ celt_assert(st->start < st->end);
+ celt_assert(st->end <= 21);
+#ifdef OPUS_ARCHMASK
+ celt_assert(st->arch >= 0);
+ celt_assert(st->arch <= OPUS_ARCHMASK);
+#endif
+ celt_assert(st->last_pitch_index <= PLC_PITCH_LAG_MAX);
+ celt_assert(st->last_pitch_index >= PLC_PITCH_LAG_MIN || st->last_pitch_index == 0);
+ celt_assert(st->postfilter_period < MAX_PERIOD);
+ celt_assert(st->postfilter_period >= COMBFILTER_MINPERIOD || st->postfilter_period == 0);
+ celt_assert(st->postfilter_period_old < MAX_PERIOD);
+ celt_assert(st->postfilter_period_old >= COMBFILTER_MINPERIOD || st->postfilter_period_old == 0);
+ celt_assert(st->postfilter_tapset <= 2);
+ celt_assert(st->postfilter_tapset >= 0);
+ celt_assert(st->postfilter_tapset_old <= 2);
+ celt_assert(st->postfilter_tapset_old >= 0);
+}
+#endif
+
int celt_decoder_get_size(int channels)
{
const CELTMode *mode = opus_custom_mode_create(48000, 960, NULL);
st->start = 0;
st->end = st->mode->effEBands;
st->signalling = 1;
-#ifdef ENABLE_UPDATE_DRAFT
+#ifndef DISABLE_UPDATE_DRAFT
st->disable_inv = channels == 1;
#else
st->disable_inv = 0;
}
}
-/* The maximum pitch lag to allow in the pitch-based PLC. It's possible to save
- CPU time in the PLC pitch search by making this smaller than MAX_PERIOD. The
- current value corresponds to a pitch of 66.67 Hz. */
-#define PLC_PITCH_LAG_MAX (720)
-/* The minimum pitch lag to allow in the pitch-based PLC. This corresponds to a
- pitch of 480 Hz. */
-#define PLC_PITCH_LAG_MIN (100)
-
static int celt_plc_pitch_search(celt_sig *decode_mem[2], int C, int arch)
{
int pitch_index;
celt_synthesis(mode, X, out_syn, oldBandE, start, effEnd, C, C, 0, LM, st->downsample, 0, st->arch);
} else {
+ int exc_length;
/* Pitch-based PLC */
const opus_val16 *window;
opus_val16 *exc;
int pitch_index;
VARDECL(opus_val32, etmp);
VARDECL(opus_val16, _exc);
+ VARDECL(opus_val16, fir_tmp);
if (loss_count == 0)
{
fade = QCONST16(.8f,15);
}
+ /* We want the excitation for 2 pitch periods in order to look for a
+ decaying signal, but we can't get more than MAX_PERIOD. */
+ exc_length = IMIN(2*pitch_index, MAX_PERIOD);
+
ALLOC(etmp, overlap, opus_val32);
ALLOC(_exc, MAX_PERIOD+LPC_ORDER, opus_val16);
+ ALLOC(fir_tmp, exc_length, opus_val16);
exc = _exc+LPC_ORDER;
window = mode->window;
c=0; do {
celt_sig *buf;
int extrapolation_offset;
int extrapolation_len;
- int exc_length;
int j;
buf = decode_mem[c];
- for (i=0;i<MAX_PERIOD;i++) {
- exc[i] = ROUND16(buf[DECODE_BUFFER_SIZE-MAX_PERIOD+i], SIG_SHIFT);
- }
+ for (i=0;i<MAX_PERIOD+LPC_ORDER;i++)
+ exc[i-LPC_ORDER] = ROUND16(buf[DECODE_BUFFER_SIZE-MAX_PERIOD-LPC_ORDER+i], SIG_SHIFT);
if (loss_count == 0)
{
}
#endif
}
- /* We want the excitation for 2 pitch periods in order to look for a
- decaying signal, but we can't get more than MAX_PERIOD. */
- exc_length = IMIN(2*pitch_index, MAX_PERIOD);
/* Initialize the LPC history with the samples just before the start
of the region for which we're computing the excitation. */
{
- for (i=0;i<LPC_ORDER;i++)
- {
- exc[MAX_PERIOD-exc_length-LPC_ORDER+i] =
- ROUND16(buf[DECODE_BUFFER_SIZE-exc_length-LPC_ORDER+i], SIG_SHIFT);
- }
- /* Compute the excitation for exc_length samples before the loss. */
+ /* Compute the excitation for exc_length samples before the loss. We need the copy
+ because celt_fir() cannot filter in-place. */
celt_fir(exc+MAX_PERIOD-exc_length, lpc+c*LPC_ORDER,
- exc+MAX_PERIOD-exc_length, exc_length, LPC_ORDER, st->arch);
+ fir_tmp, exc_length, LPC_ORDER, st->arch);
+ OPUS_COPY(exc+MAX_PERIOD-exc_length, fir_tmp, exc_length);
}
/* Check if the waveform is decaying, and if so how fast.
const opus_int16 *eBands;
ALLOC_STACK;
+ VALIDATE_CELT_DECODER(st);
mode = st->mode;
nbEBands = mode->nbEBands;
overlap = mode->overlap;
ALLOC(pulses, nbEBands, int);
ALLOC(fine_priority, nbEBands, int);
- codedBands = compute_allocation(mode, start, end, offsets, cap,
+ codedBands = clt_compute_allocation(mode, start, end, offsets, cap,
alloc_trim, &intensity, &dual_stereo, bits, &balance, pulses,
fine_quant, fine_priority, C, LM, dec, 0, 0, 0);
/* Compute harmonic mean discarding the unreliable boundaries
The data is smooth, so we only take 1/4th of the samples */
unmask=0;
+ /* We should never see NaNs here. If we find any, then something really bad happened and we better abort
+ before it does any damage later on. If these asserts are disabled (no hardening), then the table
+ lookup a few lines below (id = ...) is likely to crash dur to an out-of-bounds read. DO NOT FIX
+ that crash on NaN since it could result in a worse issue later on. */
+ celt_assert(!celt_isnan(tmp[0]));
+ celt_assert(!celt_isnan(norm));
for (i=12;i<len2-5;i+=4)
{
int id;
static int tf_analysis(const CELTMode *m, int len, int isTransient,
int *tf_res, int lambda, celt_norm *X, int N0, int LM,
- opus_val16 tf_estimate, int tf_chan)
+ opus_val16 tf_estimate, int tf_chan, int *importance)
{
int i;
VARDECL(int, metric);
biasing the decision */
if (narrow && (metric[i]==0 || metric[i]==-2*LM))
metric[i]-=1;
- /*printf("%d ", metric[i]);*/
+ /*printf("%d ", metric[i]/2 + (!isTransient)*LM);*/
}
/*printf("\n");*/
/* Search for the optimal tf resolution, including tf_select */
tf_select = 0;
for (sel=0;sel<2;sel++)
{
- cost0 = 0;
- cost1 = isTransient ? 0 : lambda;
+ cost0 = importance[0]*abs(metric[0]-2*tf_select_table[LM][4*isTransient+2*sel+0]);
+ cost1 = importance[0]*abs(metric[0]-2*tf_select_table[LM][4*isTransient+2*sel+1]) + (isTransient ? 0 : lambda);
for (i=1;i<len;i++)
{
int curr0, curr1;
curr0 = IMIN(cost0, cost1 + lambda);
curr1 = IMIN(cost0 + lambda, cost1);
- cost0 = curr0 + abs(metric[i]-2*tf_select_table[LM][4*isTransient+2*sel+0]);
- cost1 = curr1 + abs(metric[i]-2*tf_select_table[LM][4*isTransient+2*sel+1]);
+ cost0 = curr0 + importance[i]*abs(metric[i]-2*tf_select_table[LM][4*isTransient+2*sel+0]);
+ cost1 = curr1 + importance[i]*abs(metric[i]-2*tf_select_table[LM][4*isTransient+2*sel+1]);
}
cost0 = IMIN(cost0, cost1);
selcost[sel]=cost0;
* If tests confirm it's useful for non-transients, we could allow it. */
if (selcost[1]<selcost[0] && isTransient)
tf_select=1;
- cost0 = 0;
- cost1 = isTransient ? 0 : lambda;
+ cost0 = importance[0]*abs(metric[0]-2*tf_select_table[LM][4*isTransient+2*tf_select+0]);
+ cost1 = importance[0]*abs(metric[0]-2*tf_select_table[LM][4*isTransient+2*tf_select+1]) + (isTransient ? 0 : lambda);
/* Viterbi forward pass */
for (i=1;i<len;i++)
{
curr1 = from1;
path1[i]= 1;
}
- cost0 = curr0 + abs(metric[i]-2*tf_select_table[LM][4*isTransient+2*tf_select+0]);
- cost1 = curr1 + abs(metric[i]-2*tf_select_table[LM][4*isTransient+2*tf_select+1]);
+ cost0 = curr0 + importance[i]*abs(metric[i]-2*tf_select_table[LM][4*isTransient+2*tf_select+0]);
+ cost1 = curr1 + importance[i]*abs(metric[i]-2*tf_select_table[LM][4*isTransient+2*tf_select+1]);
}
tf_res[len-1] = cost0 < cost1 ? 0 : 1;
/* Viterbi backward pass to check the decisions */
static opus_val16 dynalloc_analysis(const opus_val16 *bandLogE, const opus_val16 *bandLogE2,
int nbEBands, int start, int end, int C, int *offsets, int lsb_depth, const opus_int16 *logN,
int isTransient, int vbr, int constrained_vbr, const opus_int16 *eBands, int LM,
- int effectiveBytes, opus_int32 *tot_boost_, int lfe, opus_val16 *surround_dynalloc, AnalysisInfo *analysis)
+ int effectiveBytes, opus_int32 *tot_boost_, int lfe, opus_val16 *surround_dynalloc,
+ AnalysisInfo *analysis, int *importance, int *spread_weight)
{
int i, c;
opus_int32 tot_boost=0;
for (i=0;i<end;i++)
maxDepth = MAX16(maxDepth, bandLogE[c*nbEBands+i]-noise_floor[i]);
} while (++c<C);
+ {
+ /* Compute a really simple masking model to avoid taking into account completely masked
+ bands when computing the spreading decision. */
+ VARDECL(opus_val16, mask);
+ VARDECL(opus_val16, sig);
+ ALLOC(mask, nbEBands, opus_val16);
+ ALLOC(sig, nbEBands, opus_val16);
+ for (i=0;i<end;i++)
+ mask[i] = bandLogE[i]-noise_floor[i];
+ if (C==2)
+ {
+ for (i=0;i<end;i++)
+ mask[i] = MAX16(mask[i], bandLogE[nbEBands+i]-noise_floor[i]);
+ }
+ OPUS_COPY(sig, mask, end);
+ for (i=1;i<end;i++)
+ mask[i] = MAX16(mask[i], mask[i-1] - QCONST16(2.f, DB_SHIFT));
+ for (i=end-2;i>=0;i--)
+ mask[i] = MAX16(mask[i], mask[i+1] - QCONST16(3.f, DB_SHIFT));
+ for (i=0;i<end;i++)
+ {
+ /* Compute SMR: Mask is never more than 72 dB below the peak and never below the noise floor.*/
+ opus_val16 smr = sig[i]-MAX16(MAX16(0, maxDepth-QCONST16(12.f, DB_SHIFT)), mask[i]);
+ /* Clamp SMR to make sure we're not shifting by something negative or too large. */
+#ifdef FIXED_POINT
+ /* FIXME: Use PSHR16() instead */
+ int shift = -PSHR32(MAX16(-QCONST16(5.f, DB_SHIFT), MIN16(0, smr)), DB_SHIFT);
+#else
+ int shift = IMIN(5, IMAX(0, -(int)floor(.5f + smr)));
+#endif
+ spread_weight[i] = 32 >> shift;
+ }
+ /*for (i=0;i<end;i++)
+ printf("%d ", spread_weight[i]);
+ printf("\n");*/
+ }
/* Make sure that dynamic allocation can't make us bust the budget */
if (effectiveBytes > 50 && LM>=1 && !lfe)
{
}
for (i=start;i<end;i++)
follower[i] = MAX16(follower[i], surround_dynalloc[i]);
+ for (i=start;i<end;i++)
+ {
+#ifdef FIXED_POINT
+ importance[i] = PSHR32(13*celt_exp2(MIN16(follower[i], QCONST16(4.f, DB_SHIFT))), 16);
+#else
+ importance[i] = (int)floor(.5f+13*celt_exp2(MIN16(follower[i], QCONST16(4.f, DB_SHIFT))));
+#endif
+ }
/* For non-transient CBR/CVBR frames, halve the dynalloc contribution */
if ((!vbr || constrained_vbr)&&!isTransient)
{
tot_boost += boost_bits;
}
}
+ } else {
+ for (i=start;i<end;i++)
+ importance[i] = 13;
}
*tot_boost_ = tot_boost;
RESTORE_STACK;
static int run_prefilter(CELTEncoder *st, celt_sig *in, celt_sig *prefilter_mem, int CC, int N,
- int prefilter_tapset, int *pitch, opus_val16 *gain, int *qgain, int enabled, int nbAvailableBytes)
+ int prefilter_tapset, int *pitch, opus_val16 *gain, int *qgain, int enabled, int nbAvailableBytes, AnalysisInfo *analysis)
{
int c;
VARDECL(celt_sig, _pre);
gain1 = 0;
pitch_index = COMBFILTER_MINPERIOD;
}
-
+#ifndef DISABLE_FLOAT_API
+ if (analysis->valid)
+ gain1 = (opus_val16)(gain1 * analysis->max_pitch_ratio);
+#else
+ (void)analysis;
+#endif
/* Gain threshold for enabling the prefilter/postfilter */
pf_threshold = QCONST16(.2f,15);
VARDECL(int, pulses);
VARDECL(int, cap);
VARDECL(int, offsets);
+ VARDECL(int, importance);
+ VARDECL(int, spread_weight);
VARDECL(int, fine_priority);
VARDECL(int, tf_res);
VARDECL(unsigned char, collapse_masks);
opus_int32 equiv_rate;
int hybrid;
int weak_transient = 0;
+ int enable_tf_analysis;
VARDECL(opus_val16, surround_dynalloc);
ALLOC_STACK;
tell0_frac=tell=1;
nbFilledBytes=0;
} else {
- tell0_frac=tell=ec_tell_frac(enc);
+ tell0_frac=ec_tell_frac(enc);
tell=ec_tell(enc);
nbFilledBytes=(tell+4)>>3;
}
&& st->complexity >= 5;
prefilter_tapset = st->tapset_decision;
- pf_on = run_prefilter(st, in, prefilter_mem, CC, N, prefilter_tapset, &pitch_index, &gain1, &qg, enabled, nbAvailableBytes);
+ pf_on = run_prefilter(st, in, prefilter_mem, CC, N, prefilter_tapset, &pitch_index, &gain1, &qg, enabled, nbAvailableBytes, &st->analysis);
if ((gain1 > QCONST16(.4f,15) || st->prefilter_gain > QCONST16(.4f,15)) && (!st->analysis.valid || st->analysis.tonality > .3)
&& (pitch_index > 1.26*st->prefilter_period || pitch_index < .79*st->prefilter_period))
pitch_change = 1;
/* Reduces the likelihood of energy instability on fricatives at low bitrate
in hybrid mode. It seems like we still want to have real transients on vowels
though (small SILK quantization offset value). */
- int allow_weak_transients = hybrid && effectiveBytes<15 && st->silk_info.offset >= 100;
+ int allow_weak_transients = hybrid && effectiveBytes<15 && st->silk_info.signalType != 2;
isTransient = transient_analysis(in, N+overlap, CC,
&tf_estimate, &tf_chan, allow_weak_transients, &weak_transient);
}
}
compute_mdcts(mode, shortBlocks, in, freq, C, CC, LM, st->upsample, st->arch);
+ /* This should catch any NaN in the CELT input. Since we're not supposed to see any (they're filtered
+ at the Opus layer), just abort. */
+ celt_assert(!celt_isnan(freq[0]) && (C==1 || !celt_isnan(freq[N])));
if (CC==2&&C==1)
tf_chan = 0;
compute_band_energies(mode, freq, bandE, effEnd, C, LM, st->arch);
/* Band normalisation */
normalise_bands(mode, freq, X, bandE, effEnd, C, M);
+ enable_tf_analysis = effectiveBytes>=15*C && !hybrid && st->complexity>=2 && !st->lfe;
+
+ ALLOC(offsets, nbEBands, int);
+ ALLOC(importance, nbEBands, int);
+ ALLOC(spread_weight, nbEBands, int);
+
+ maxDepth = dynalloc_analysis(bandLogE, bandLogE2, nbEBands, start, end, C, offsets,
+ st->lsb_depth, mode->logN, isTransient, st->vbr, st->constrained_vbr,
+ eBands, LM, effectiveBytes, &tot_boost, st->lfe, surround_dynalloc, &st->analysis, importance, spread_weight);
+
ALLOC(tf_res, nbEBands, int);
/* Disable variable tf resolution for hybrid and at very low bitrate */
- if (effectiveBytes>=15*C && !hybrid && st->complexity>=2 && !st->lfe)
+ if (enable_tf_analysis)
{
int lambda;
- lambda = IMAX(5, 1280/effectiveBytes + 2);
- tf_select = tf_analysis(mode, effEnd, isTransient, tf_res, lambda, X, N, LM, tf_estimate, tf_chan);
+ lambda = IMAX(80, 20480/effectiveBytes + 2);
+ tf_select = tf_analysis(mode, effEnd, isTransient, tf_res, lambda, X, N, LM, tf_estimate, tf_chan, importance);
for (i=effEnd;i<end;i++)
tf_res[i] = tf_res[effEnd-1];
} else if (hybrid && weak_transient)
for (i=0;i<end;i++)
tf_res[i] = 1;
tf_select=0;
- } else if (hybrid && effectiveBytes<15)
+ } else if (hybrid && effectiveBytes<15 && st->silk_info.signalType != 2)
{
/* For low bitrate hybrid, we force temporal resolution to 5 ms rather than 2.5 ms. */
for (i=0;i<end;i++)
{
st->spread_decision = spreading_decision(mode, X,
&st->tonal_average, st->spread_decision, &st->hf_average,
- &st->tapset_decision, pf_on&&!shortBlocks, effEnd, C, M);
+ &st->tapset_decision, pf_on&&!shortBlocks, effEnd, C, M, spread_weight);
}
/*printf("%d %d\n", st->tapset_decision, st->spread_decision);*/
/*printf("%f %d %f %d\n\n", st->analysis.tonality, st->spread_decision, st->analysis.tonality_slope, st->tapset_decision);*/
ec_enc_icdf(enc, st->spread_decision, spread_icdf, 5);
}
- ALLOC(offsets, nbEBands, int);
-
- maxDepth = dynalloc_analysis(bandLogE, bandLogE2, nbEBands, start, end, C, offsets,
- st->lsb_depth, mode->logN, isTransient, st->vbr, st->constrained_vbr,
- eBands, LM, effectiveBytes, &tot_boost, st->lfe, surround_dynalloc, &st->analysis);
/* For LFE, everything interesting is in the first band */
if (st->lfe)
offsets[0] = IMIN(8, effectiveBytes/3);
#endif
if (st->lfe)
signalBandwidth = 1;
- codedBands = compute_allocation(mode, start, end, offsets, cap,
+ codedBands = clt_compute_allocation(mode, start, end, offsets, cap,
alloc_trim, &st->intensity, &dual_stereo, bits, &balance, pulses,
fine_quant, fine_priority, C, LM, enc, 1, st->lastCodedBands, signalBandwidth);
if (st->lastCodedBands)
int i,j;
VARDECL(opus_val16, rnum);
SAVE_STACK;
-
+ celt_assert(x != y);
ALLOC(rnum, ord, opus_val16);
for(i=0;i<ord;i++)
rnum[i] = num[ord-i-1];
{
opus_val32 sum[4];
sum[0] = SHL32(EXTEND32(x[i ]), SIG_SHIFT);
- sum[1] = SHL32(EXTEND32(x[i+1]), SIG_SHIFT),
+ sum[1] = SHL32(EXTEND32(x[i+1]), SIG_SHIFT);
sum[2] = SHL32(EXTEND32(x[i+2]), SIG_SHIFT);
sum[3] = SHL32(EXTEND32(x[i+3]), SIG_SHIFT);
xcorr_kernel(rnum, x+i-ord, sum, ord, arch);
k0=_k;
q=row[_n];
if(q>_i){
- celt_assert(p>q);
+ celt_sig_assert(p>q);
_k=_n;
do p=CELT_PVQ_U_ROW[--_k][_n];
while(p>_i);
/* Tested exhaustively for all n and for 1<=d<=256 */
static OPUS_INLINE opus_uint32 celt_udiv(opus_uint32 n, opus_uint32 d) {
- celt_assert(d>0);
+ celt_sig_assert(d>0);
#ifdef USE_SMALL_DIV_TABLE
if (d>256)
return n/d;
}
static OPUS_INLINE opus_int32 celt_sudiv(opus_int32 n, opus_int32 d) {
- celt_assert(d>0);
+ celt_sig_assert(d>0);
#ifdef USE_SMALL_DIV_TABLE
if (n<0)
return -(opus_int32)celt_udiv(-n, d);
The bits must have been encoded with ec_enc_uint().
No call to ec_dec_update() is necessary after this call.
_ft: The number of integers that can be decoded (one more than the max).
- This must be at least one, and no more than 2**32-1.
+ This must be at least 2, and no more than 2**32-1.
Return: The decoded bits.*/
opus_uint32 ec_dec_uint(ec_dec *_this,opus_uint32 _ft);
/*Encodes a raw unsigned integer in the stream.
_fl: The integer to encode.
_ft: The number of integers that can be encoded (one more than the max).
- This must be at least one, and no more than 2**32-1.*/
+ This must be at least 2, and no more than 2**32-1.*/
void ec_enc_uint(ec_enc *_this,opus_uint32 _fl,opus_uint32 _ft);
/*Encodes a sequence of raw bits in the stream.
#include <math.h>
#define float2int(x) lrint(x)
-#elif (defined(_MSC_VER) && _MSC_VER >= 1400) && defined (_M_X64)
+#elif (defined(_MSC_VER) && _MSC_VER >= 1400) && (defined(_M_X64) || (defined(_M_IX86_FP) && _M_IX86_FP >= 1))
#include <xmmintrin.h>
__inline long int float2int(float value)
#include "mathops.h"
/*Compute floor(sqrt(_val)) with exact arithmetic.
- This has been tested on all possible 32-bit inputs.*/
+ _val must be greater than 0.
+ This has been tested on all possible 32-bit inputs greater than 0.*/
unsigned isqrt32(opus_uint32 _val){
unsigned b;
unsigned g;
int i;
opus_val16 n;
opus_val16 r;
- celt_assert2(x>0, "celt_rcp() only defined for positive values");
+ celt_sig_assert(x>0);
i = celt_ilog2(x);
/* n is Q15 with range [0,1). */
n = VSHR32(x,i-15)-32768;
#undef cA
#undef cB
#undef cC
-#undef cD
+#undef cE
#endif
/** Integer log in base2. Undefined for zero and negative numbers */
static OPUS_INLINE opus_int16 celt_ilog2(opus_int32 x)
{
- celt_assert2(x>0, "celt_ilog2() only defined for strictly positive numbers");
+ celt_sig_assert(x>0);
return EC_ILOG(x)-1;
}
#endif
}
}
-static void celt_fir5(const opus_val16 *x,
+static void celt_fir5(opus_val16 *x,
const opus_val16 *num,
- opus_val16 *y,
- int N,
- opus_val16 *mem)
+ int N)
{
int i;
opus_val16 num0, num1, num2, num3, num4;
num2=num[2];
num3=num[3];
num4=num[4];
- mem0=mem[0];
- mem1=mem[1];
- mem2=mem[2];
- mem3=mem[3];
- mem4=mem[4];
+ mem0=0;
+ mem1=0;
+ mem2=0;
+ mem3=0;
+ mem4=0;
for (i=0;i<N;i++)
{
opus_val32 sum = SHL32(EXTEND32(x[i]), SIG_SHIFT);
mem2 = mem1;
mem1 = mem0;
mem0 = x[i];
- y[i] = ROUND16(sum, SIG_SHIFT);
+ x[i] = ROUND16(sum, SIG_SHIFT);
}
- mem[0]=mem0;
- mem[1]=mem1;
- mem[2]=mem2;
- mem[3]=mem3;
- mem[4]=mem4;
}
int i;
opus_val32 ac[5];
opus_val16 tmp=Q15ONE;
- opus_val16 lpc[4], mem[5]={0,0,0,0,0};
+ opus_val16 lpc[4];
opus_val16 lpc2[5];
opus_val16 c1 = QCONST16(.8f,15);
#ifdef FIXED_POINT
lpc2[2] = lpc[2] + MULT16_16_Q15(c1,lpc[1]);
lpc2[3] = lpc[3] + MULT16_16_Q15(c1,lpc[2]);
lpc2[4] = MULT16_16_Q15(c1,lpc[3]);
- celt_fir5(x_lp, lpc2, x_lp, len>>1, mem);
+ celt_fir5(x_lp, lpc2, len>>1);
}
/* Pure C implementation. */
opus_val32 maxcorr=1;
#endif
celt_assert(max_pitch>0);
- celt_assert((((unsigned char *)_x-(unsigned char *)NULL)&3)==0);
+ celt_sig_assert((((unsigned char *)_x-(unsigned char *)NULL)&3)==0);
for (i=0;i<max_pitch-3;i+=4)
{
opus_val32 sum[4]={0,0,0,0};
/* It would be better to express this invariant as a
test on C at function entry, but that isn't enough
to make the static analyzer happy. */
- celt_assert(c<2);
+ celt_sig_assert(c<2);
tell = ec_tell(dec);
if(budget-tell>=15)
{
return codedBands;
}
-int compute_allocation(const CELTMode *m, int start, int end, const int *offsets, const int *cap, int alloc_trim, int *intensity, int *dual_stereo,
+int clt_compute_allocation(const CELTMode *m, int start, int end, const int *offsets, const int *cap, int alloc_trim, int *intensity, int *dual_stereo,
opus_int32 total, opus_int32 *balance, int *pulses, int *ebits, int *fine_priority, int C, int LM, ec_ctx *ec, int encode, int prev, int signalBandwidth)
{
int lo, hi, len, j;
@param pulses Number of pulses per band (returned)
@return Total number of bits allocated
*/
-int compute_allocation(const CELTMode *m, int start, int end, const int *offsets, const int *cap, int alloc_trim, int *intensity, int *dual_stero,
+int clt_compute_allocation(const CELTMode *m, int start, int end, const int *offsets, const int *cap, int alloc_trim, int *intensity, int *dual_stero,
opus_int32 total, opus_int32 *balance, int *pulses, int *ebits, int *fine_priority, int C, int LM, ec_ctx *ec, int encode, int prev, int signalBandwidth);
#endif
#include <stdio.h>
#include <math.h>
#include <time.h>
+#define CELT_C
#include "entcode.h"
#include "entenc.h"
#include "entdec.h"
#include <stdio.h>
#include <stdlib.h>
-#include "laplace.h"
#define CELT_C
+#include "laplace.h"
#include "stack_alloc.h"
#include "entenc.c"
#define CUSTOM_MODES
#endif
-#define CELT_C
-
#include <stdio.h>
#include <stdlib.h>
#include "vq.h"
pulsesLeft -= iy[j];
} while (++j<N);
}
- celt_assert2(pulsesLeft>=0, "Allocated too many pulses in the quick pass");
+ celt_sig_assert(pulsesLeft>=0);
/* This should never happen, but just in case it does (e.g. on silence)
we fill the first bin with pulses. */
#ifdef FIXED_POINT_DEBUG
- celt_assert2(pulsesLeft<=N+3, "Not enough pulses in the quick pass");
+ celt_sig_assert(pulsesLeft<=N+3);
#endif
if (pulsesLeft > N+3)
{
}
X[N] = X[N+1] = X[N+2] = -100;
y[N] = y[N+1] = y[N+2] = 100;
- celt_assert2(pulsesLeft>=0, "Allocated too many pulses in the quick pass");
+ celt_sig_assert(pulsesLeft>=0);
/* This should never happen, but just in case it does (e.g. on silence)
we fill the first bin with pulses. */
(_mm_cvtepi8_epi32(*(__m128i *)(x)))
#endif
-# if !defined(__OPTIMIZE__)
+/* similar reasoning about the instruction sequence as in the 32-bit macro above,
+ */
+# if defined(__clang__) || !defined(__OPTIMIZE__)
# define OP_CVTEPI16_EPI32_M64(x) \
(_mm_cvtepi16_epi32(_mm_loadl_epi64((__m128i *)(x))))
# else
const unsigned char *frames[48],
opus_int16 size[48],
int *payload_offset
-) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(5);
/** Gets the bandwidth of an Opus packet.
* @param [in] data <tt>char*</tt>: Opus packet
#define OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST 4046
#define OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST 4047
+/** Defines for the presence of extended APIs. */
+#define OPUS_HAVE_OPUS_PROJECTION_H
+
/* Macros to trigger compilation errors when the wrong types are provided to a CTL */
#define __opus_check_int(x) (((void)((x) == (opus_int32)0)), (opus_int32)(x))
#define __opus_check_int_ptr(ptr) ((ptr) + ((ptr) - (opus_int32*)(ptr)))
--- /dev/null
+/* Copyright (c) 2017 Google Inc.
+ Written by Andrew Allen */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/**
+ * @file opus_projection.h
+ * @brief Opus projection reference API
+ */
+
+#ifndef OPUS_PROJECTION_H
+#define OPUS_PROJECTION_H
+
+#include "opus_multistream.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @cond OPUS_INTERNAL_DOC */
+
+/** These are the actual encoder and decoder CTL ID numbers.
+ * They should not be used directly by applications.c
+ * In general, SETs should be even and GETs should be odd.*/
+/**@{*/
+#define OPUS_PROJECTION_GET_DEMIXING_MATRIX_GAIN_REQUEST 6001
+#define OPUS_PROJECTION_GET_DEMIXING_MATRIX_SIZE_REQUEST 6003
+#define OPUS_PROJECTION_GET_DEMIXING_MATRIX_REQUEST 6005
+/**@}*/
+
+
+/** @endcond */
+
+/** @defgroup opus_projection_ctls Projection specific encoder and decoder CTLs
+ *
+ * These are convenience macros that are specific to the
+ * opus_projection_encoder_ctl() and opus_projection_decoder_ctl()
+ * interface.
+ * The CTLs from @ref opus_genericctls, @ref opus_encoderctls,
+ * @ref opus_decoderctls, and @ref opus_multistream_ctls may be applied to a
+ * projection encoder or decoder as well.
+ */
+/**@{*/
+
+/** Gets the gain (in dB. S7.8-format) of the demixing matrix from the encoder.
+ * @param[out] x <tt>opus_int32 *</tt>: Returns the gain (in dB. S7.8-format)
+ * of the demixing matrix.
+ * @hideinitializer
+ */
+#define OPUS_PROJECTION_GET_DEMIXING_MATRIX_GAIN(x) OPUS_PROJECTION_GET_DEMIXING_MATRIX_GAIN_REQUEST, __opus_check_int_ptr(x)
+
+
+/** Gets the size in bytes of the demixing matrix from the encoder.
+ * @param[out] x <tt>opus_int32 *</tt>: Returns the size in bytes of the
+ * demixing matrix.
+ * @hideinitializer
+ */
+#define OPUS_PROJECTION_GET_DEMIXING_MATRIX_SIZE(x) OPUS_PROJECTION_GET_DEMIXING_MATRIX_SIZE_REQUEST, __opus_check_int_ptr(x)
+
+
+/** Copies the demixing matrix to the supplied pointer location.
+ * @param[out] x <tt>unsigned char *</tt>: Returns the demixing matrix to the
+ * supplied pointer location.
+ * @param y <tt>opus_int32</tt>: The size in bytes of the reserved memory at the
+ * pointer location.
+ * @hideinitializer
+ */
+#define OPUS_PROJECTION_GET_DEMIXING_MATRIX(x,y) OPUS_PROJECTION_GET_DEMIXING_MATRIX_REQUEST, x, __opus_check_int(y)
+
+
+/**@}*/
+
+/** Opus projection encoder state.
+ * This contains the complete state of a projection Opus encoder.
+ * It is position independent and can be freely copied.
+ * @see opus_projection_ambisonics_encoder_create
+ */
+typedef struct OpusProjectionEncoder OpusProjectionEncoder;
+
+
+/** Opus projection decoder state.
+ * This contains the complete state of a projection Opus decoder.
+ * It is position independent and can be freely copied.
+ * @see opus_projection_decoder_create
+ * @see opus_projection_decoder_init
+ */
+typedef struct OpusProjectionDecoder OpusProjectionDecoder;
+
+
+/**\name Projection encoder functions */
+/**@{*/
+
+/** Gets the size of an OpusProjectionEncoder structure.
+ * @param channels <tt>int</tt>: The total number of input channels to encode.
+ * This must be no more than 255.
+ * @param mapping_family <tt>int</tt>: The mapping family to use for selecting
+ * the appropriate projection.
+ * @returns The size in bytes on success, or a negative error code
+ * (see @ref opus_errorcodes) on error.
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_projection_ambisonics_encoder_get_size(
+ int channels,
+ int mapping_family
+);
+
+
+/** Allocates and initializes a projection encoder state.
+ * Call opus_projection_encoder_destroy() to release
+ * this object when finished.
+ * @param Fs <tt>opus_int32</tt>: Sampling rate of the input signal (in Hz).
+ * This must be one of 8000, 12000, 16000,
+ * 24000, or 48000.
+ * @param channels <tt>int</tt>: Number of channels in the input signal.
+ * This must be at most 255.
+ * It may be greater than the number of
+ * coded channels (<code>streams +
+ * coupled_streams</code>).
+ * @param mapping_family <tt>int</tt>: The mapping family to use for selecting
+ * the appropriate projection.
+ * @param[out] streams <tt>int *</tt>: The total number of streams that will
+ * be encoded from the input.
+ * @param[out] coupled_streams <tt>int *</tt>: Number of coupled (2 channel)
+ * streams that will be encoded from the input.
+ * @param application <tt>int</tt>: The target encoder application.
+ * This must be one of the following:
+ * <dl>
+ * <dt>#OPUS_APPLICATION_VOIP</dt>
+ * <dd>Process signal for improved speech intelligibility.</dd>
+ * <dt>#OPUS_APPLICATION_AUDIO</dt>
+ * <dd>Favor faithfulness to the original input.</dd>
+ * <dt>#OPUS_APPLICATION_RESTRICTED_LOWDELAY</dt>
+ * <dd>Configure the minimum possible coding delay by disabling certain modes
+ * of operation.</dd>
+ * </dl>
+ * @param[out] error <tt>int *</tt>: Returns #OPUS_OK on success, or an error
+ * code (see @ref opus_errorcodes) on
+ * failure.
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusProjectionEncoder *opus_projection_ambisonics_encoder_create(
+ opus_int32 Fs,
+ int channels,
+ int mapping_family,
+ int *streams,
+ int *coupled_streams,
+ int application,
+ int *error
+) OPUS_ARG_NONNULL(4) OPUS_ARG_NONNULL(5);
+
+
+/** Initialize a previously allocated projection encoder state.
+ * The memory pointed to by \a st must be at least the size returned by
+ * opus_projection_ambisonics_encoder_get_size().
+ * This is intended for applications which use their own allocator instead of
+ * malloc.
+ * To reset a previously initialized state, use the #OPUS_RESET_STATE CTL.
+ * @see opus_projection_ambisonics_encoder_create
+ * @see opus_projection_ambisonics_encoder_get_size
+ * @param st <tt>OpusProjectionEncoder*</tt>: Projection encoder state to initialize.
+ * @param Fs <tt>opus_int32</tt>: Sampling rate of the input signal (in Hz).
+ * This must be one of 8000, 12000, 16000,
+ * 24000, or 48000.
+ * @param channels <tt>int</tt>: Number of channels in the input signal.
+ * This must be at most 255.
+ * It may be greater than the number of
+ * coded channels (<code>streams +
+ * coupled_streams</code>).
+ * @param streams <tt>int</tt>: The total number of streams to encode from the
+ * input.
+ * This must be no more than the number of channels.
+ * @param coupled_streams <tt>int</tt>: Number of coupled (2 channel) streams
+ * to encode.
+ * This must be no larger than the total
+ * number of streams.
+ * Additionally, The total number of
+ * encoded channels (<code>streams +
+ * coupled_streams</code>) must be no
+ * more than the number of input channels.
+ * @param application <tt>int</tt>: The target encoder application.
+ * This must be one of the following:
+ * <dl>
+ * <dt>#OPUS_APPLICATION_VOIP</dt>
+ * <dd>Process signal for improved speech intelligibility.</dd>
+ * <dt>#OPUS_APPLICATION_AUDIO</dt>
+ * <dd>Favor faithfulness to the original input.</dd>
+ * <dt>#OPUS_APPLICATION_RESTRICTED_LOWDELAY</dt>
+ * <dd>Configure the minimum possible coding delay by disabling certain modes
+ * of operation.</dd>
+ * </dl>
+ * @returns #OPUS_OK on success, or an error code (see @ref opus_errorcodes)
+ * on failure.
+ */
+OPUS_EXPORT int opus_projection_ambisonics_encoder_init(
+ OpusProjectionEncoder *st,
+ opus_int32 Fs,
+ int channels,
+ int mapping_family,
+ int *streams,
+ int *coupled_streams,
+ int application
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(5) OPUS_ARG_NONNULL(6);
+
+
+/** Encodes a projection Opus frame.
+ * @param st <tt>OpusProjectionEncoder*</tt>: Projection encoder state.
+ * @param[in] pcm <tt>const opus_int16*</tt>: The input signal as interleaved
+ * samples.
+ * This must contain
+ * <code>frame_size*channels</code>
+ * samples.
+ * @param frame_size <tt>int</tt>: Number of samples per channel in the input
+ * signal.
+ * This must be an Opus frame size for the
+ * encoder's sampling rate.
+ * For example, at 48 kHz the permitted values
+ * are 120, 240, 480, 960, 1920, and 2880.
+ * Passing in a duration of less than 10 ms
+ * (480 samples at 48 kHz) will prevent the
+ * encoder from using the LPC or hybrid modes.
+ * @param[out] data <tt>unsigned char*</tt>: Output payload.
+ * This must contain storage for at
+ * least \a max_data_bytes.
+ * @param [in] max_data_bytes <tt>opus_int32</tt>: Size of the allocated
+ * memory for the output
+ * payload. This may be
+ * used to impose an upper limit on
+ * the instant bitrate, but should
+ * not be used as the only bitrate
+ * control. Use #OPUS_SET_BITRATE to
+ * control the bitrate.
+ * @returns The length of the encoded packet (in bytes) on success or a
+ * negative error code (see @ref opus_errorcodes) on failure.
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_projection_encode(
+ OpusProjectionEncoder *st,
+ const opus_int16 *pcm,
+ int frame_size,
+ unsigned char *data,
+ opus_int32 max_data_bytes
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4);
+
+
+/** Encodes a projection Opus frame from floating point input.
+ * @param st <tt>OpusProjectionEncoder*</tt>: Projection encoder state.
+ * @param[in] pcm <tt>const float*</tt>: The input signal as interleaved
+ * samples with a normal range of
+ * +/-1.0.
+ * Samples with a range beyond +/-1.0
+ * are supported but will be clipped by
+ * decoders using the integer API and
+ * should only be used if it is known
+ * that the far end supports extended
+ * dynamic range.
+ * This must contain
+ * <code>frame_size*channels</code>
+ * samples.
+ * @param frame_size <tt>int</tt>: Number of samples per channel in the input
+ * signal.
+ * This must be an Opus frame size for the
+ * encoder's sampling rate.
+ * For example, at 48 kHz the permitted values
+ * are 120, 240, 480, 960, 1920, and 2880.
+ * Passing in a duration of less than 10 ms
+ * (480 samples at 48 kHz) will prevent the
+ * encoder from using the LPC or hybrid modes.
+ * @param[out] data <tt>unsigned char*</tt>: Output payload.
+ * This must contain storage for at
+ * least \a max_data_bytes.
+ * @param [in] max_data_bytes <tt>opus_int32</tt>: Size of the allocated
+ * memory for the output
+ * payload. This may be
+ * used to impose an upper limit on
+ * the instant bitrate, but should
+ * not be used as the only bitrate
+ * control. Use #OPUS_SET_BITRATE to
+ * control the bitrate.
+ * @returns The length of the encoded packet (in bytes) on success or a
+ * negative error code (see @ref opus_errorcodes) on failure.
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_projection_encode_float(
+ OpusProjectionEncoder *st,
+ const float *pcm,
+ int frame_size,
+ unsigned char *data,
+ opus_int32 max_data_bytes
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4);
+
+
+/** Frees an <code>OpusProjectionEncoder</code> allocated by
+ * opus_projection_ambisonics_encoder_create().
+ * @param st <tt>OpusProjectionEncoder*</tt>: Projection encoder state to be freed.
+ */
+OPUS_EXPORT void opus_projection_encoder_destroy(OpusProjectionEncoder *st);
+
+
+/** Perform a CTL function on a projection Opus encoder.
+ *
+ * Generally the request and subsequent arguments are generated by a
+ * convenience macro.
+ * @param st <tt>OpusProjectionEncoder*</tt>: Projection encoder state.
+ * @param request This and all remaining parameters should be replaced by one
+ * of the convenience macros in @ref opus_genericctls,
+ * @ref opus_encoderctls, @ref opus_multistream_ctls, or
+ * @ref opus_projection_ctls
+ * @see opus_genericctls
+ * @see opus_encoderctls
+ * @see opus_multistream_ctls
+ * @see opus_projection_ctls
+ */
+OPUS_EXPORT int opus_projection_encoder_ctl(OpusProjectionEncoder *st, int request, ...) OPUS_ARG_NONNULL(1);
+
+
+/**@}*/
+
+/**\name Projection decoder functions */
+/**@{*/
+
+/** Gets the size of an <code>OpusProjectionDecoder</code> structure.
+ * @param channels <tt>int</tt>: The total number of output channels.
+ * This must be no more than 255.
+ * @param streams <tt>int</tt>: The total number of streams coded in the
+ * input.
+ * This must be no more than 255.
+ * @param coupled_streams <tt>int</tt>: Number streams to decode as coupled
+ * (2 channel) streams.
+ * This must be no larger than the total
+ * number of streams.
+ * Additionally, The total number of
+ * coded channels (<code>streams +
+ * coupled_streams</code>) must be no
+ * more than 255.
+ * @returns The size in bytes on success, or a negative error code
+ * (see @ref opus_errorcodes) on error.
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_projection_decoder_get_size(
+ int channels,
+ int streams,
+ int coupled_streams
+);
+
+
+/** Allocates and initializes a projection decoder state.
+ * Call opus_projection_decoder_destroy() to release
+ * this object when finished.
+ * @param Fs <tt>opus_int32</tt>: Sampling rate to decode at (in Hz).
+ * This must be one of 8000, 12000, 16000,
+ * 24000, or 48000.
+ * @param channels <tt>int</tt>: Number of channels to output.
+ * This must be at most 255.
+ * It may be different from the number of coded
+ * channels (<code>streams +
+ * coupled_streams</code>).
+ * @param streams <tt>int</tt>: The total number of streams coded in the
+ * input.
+ * This must be no more than 255.
+ * @param coupled_streams <tt>int</tt>: Number of streams to decode as coupled
+ * (2 channel) streams.
+ * This must be no larger than the total
+ * number of streams.
+ * Additionally, The total number of
+ * coded channels (<code>streams +
+ * coupled_streams</code>) must be no
+ * more than 255.
+ * @param[in] demixing_matrix <tt>const unsigned char[demixing_matrix_size]</tt>: Demixing matrix
+ * that mapping from coded channels to output channels,
+ * as described in @ref opus_projection and
+ * @ref opus_projection_ctls.
+ * @param demixing_matrix_size <tt>opus_int32</tt>: The size in bytes of the
+ * demixing matrix, as
+ * described in @ref
+ * opus_projection_ctls.
+ * @param[out] error <tt>int *</tt>: Returns #OPUS_OK on success, or an error
+ * code (see @ref opus_errorcodes) on
+ * failure.
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusProjectionDecoder *opus_projection_decoder_create(
+ opus_int32 Fs,
+ int channels,
+ int streams,
+ int coupled_streams,
+ unsigned char *demixing_matrix,
+ opus_int32 demixing_matrix_size,
+ int *error
+) OPUS_ARG_NONNULL(5);
+
+
+/** Intialize a previously allocated projection decoder state object.
+ * The memory pointed to by \a st must be at least the size returned by
+ * opus_projection_decoder_get_size().
+ * This is intended for applications which use their own allocator instead of
+ * malloc.
+ * To reset a previously initialized state, use the #OPUS_RESET_STATE CTL.
+ * @see opus_projection_decoder_create
+ * @see opus_projection_deocder_get_size
+ * @param st <tt>OpusProjectionDecoder*</tt>: Projection encoder state to initialize.
+ * @param Fs <tt>opus_int32</tt>: Sampling rate to decode at (in Hz).
+ * This must be one of 8000, 12000, 16000,
+ * 24000, or 48000.
+ * @param channels <tt>int</tt>: Number of channels to output.
+ * This must be at most 255.
+ * It may be different from the number of coded
+ * channels (<code>streams +
+ * coupled_streams</code>).
+ * @param streams <tt>int</tt>: The total number of streams coded in the
+ * input.
+ * This must be no more than 255.
+ * @param coupled_streams <tt>int</tt>: Number of streams to decode as coupled
+ * (2 channel) streams.
+ * This must be no larger than the total
+ * number of streams.
+ * Additionally, The total number of
+ * coded channels (<code>streams +
+ * coupled_streams</code>) must be no
+ * more than 255.
+ * @param[in] demixing_matrix <tt>const unsigned char[demixing_matrix_size]</tt>: Demixing matrix
+ * that mapping from coded channels to output channels,
+ * as described in @ref opus_projection and
+ * @ref opus_projection_ctls.
+ * @param demixing_matrix_size <tt>opus_int32</tt>: The size in bytes of the
+ * demixing matrix, as
+ * described in @ref
+ * opus_projection_ctls.
+ * @returns #OPUS_OK on success, or an error code (see @ref opus_errorcodes)
+ * on failure.
+ */
+OPUS_EXPORT int opus_projection_decoder_init(
+ OpusProjectionDecoder *st,
+ opus_int32 Fs,
+ int channels,
+ int streams,
+ int coupled_streams,
+ unsigned char *demixing_matrix,
+ opus_int32 demixing_matrix_size
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(6);
+
+
+/** Decode a projection Opus packet.
+ * @param st <tt>OpusProjectionDecoder*</tt>: Projection decoder state.
+ * @param[in] data <tt>const unsigned char*</tt>: Input payload.
+ * Use a <code>NULL</code>
+ * pointer to indicate packet
+ * loss.
+ * @param len <tt>opus_int32</tt>: Number of bytes in payload.
+ * @param[out] pcm <tt>opus_int16*</tt>: Output signal, with interleaved
+ * samples.
+ * This must contain room for
+ * <code>frame_size*channels</code>
+ * samples.
+ * @param frame_size <tt>int</tt>: The number of samples per channel of
+ * available space in \a pcm.
+ * If this is less than the maximum packet duration
+ * (120 ms; 5760 for 48kHz), this function will not be capable
+ * of decoding some packets. In the case of PLC (data==NULL)
+ * or FEC (decode_fec=1), then frame_size needs to be exactly
+ * the duration of audio that is missing, otherwise the
+ * decoder will not be in the optimal state to decode the
+ * next incoming packet. For the PLC and FEC cases, frame_size
+ * <b>must</b> be a multiple of 2.5 ms.
+ * @param decode_fec <tt>int</tt>: Flag (0 or 1) to request that any in-band
+ * forward error correction data be decoded.
+ * If no such data is available, the frame is
+ * decoded as if it were lost.
+ * @returns Number of samples decoded on success or a negative error code
+ * (see @ref opus_errorcodes) on failure.
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_projection_decode(
+ OpusProjectionDecoder *st,
+ const unsigned char *data,
+ opus_int32 len,
+ opus_int16 *pcm,
+ int frame_size,
+ int decode_fec
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
+
+
+/** Decode a projection Opus packet with floating point output.
+ * @param st <tt>OpusProjectionDecoder*</tt>: Projection decoder state.
+ * @param[in] data <tt>const unsigned char*</tt>: Input payload.
+ * Use a <code>NULL</code>
+ * pointer to indicate packet
+ * loss.
+ * @param len <tt>opus_int32</tt>: Number of bytes in payload.
+ * @param[out] pcm <tt>opus_int16*</tt>: Output signal, with interleaved
+ * samples.
+ * This must contain room for
+ * <code>frame_size*channels</code>
+ * samples.
+ * @param frame_size <tt>int</tt>: The number of samples per channel of
+ * available space in \a pcm.
+ * If this is less than the maximum packet duration
+ * (120 ms; 5760 for 48kHz), this function will not be capable
+ * of decoding some packets. In the case of PLC (data==NULL)
+ * or FEC (decode_fec=1), then frame_size needs to be exactly
+ * the duration of audio that is missing, otherwise the
+ * decoder will not be in the optimal state to decode the
+ * next incoming packet. For the PLC and FEC cases, frame_size
+ * <b>must</b> be a multiple of 2.5 ms.
+ * @param decode_fec <tt>int</tt>: Flag (0 or 1) to request that any in-band
+ * forward error correction data be decoded.
+ * If no such data is available, the frame is
+ * decoded as if it were lost.
+ * @returns Number of samples decoded on success or a negative error code
+ * (see @ref opus_errorcodes) on failure.
+ */
+OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_projection_decode_float(
+ OpusProjectionDecoder *st,
+ const unsigned char *data,
+ opus_int32 len,
+ float *pcm,
+ int frame_size,
+ int decode_fec
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
+
+
+/** Perform a CTL function on a projection Opus decoder.
+ *
+ * Generally the request and subsequent arguments are generated by a
+ * convenience macro.
+ * @param st <tt>OpusProjectionDecoder*</tt>: Projection decoder state.
+ * @param request This and all remaining parameters should be replaced by one
+ * of the convenience macros in @ref opus_genericctls,
+ * @ref opus_decoderctls, @ref opus_multistream_ctls, or
+ * @ref opus_projection_ctls.
+ * @see opus_genericctls
+ * @see opus_decoderctls
+ * @see opus_multistream_ctls
+ * @see opus_projection_ctls
+ */
+OPUS_EXPORT int opus_projection_decoder_ctl(OpusProjectionDecoder *st, int request, ...) OPUS_ARG_NONNULL(1);
+
+
+/** Frees an <code>OpusProjectionDecoder</code> allocated by
+ * opus_projection_decoder_create().
+ * @param st <tt>OpusProjectionDecoder</tt>: Projection decoder state to be freed.
+ */
+OPUS_EXPORT void opus_projection_decoder_destroy(OpusProjectionDecoder *st);
+
+
+/**@}*/
+
+/**@}*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* OPUS_PROJECTION_H */
#ifndef OPUS_TYPES_H
#define OPUS_TYPES_H
+#define opus_int int /* used for counters etc; at least 16 bits */
+#define opus_int64 long long
+#define opus_int8 signed char
+
+#define opus_uint unsigned int /* used for counters etc; at least 16 bits */
+#define opus_uint64 unsigned long long
+#define opus_uint8 unsigned char
+
/* Use the real stdint.h if it's there (taken from Paul Hsieh's pstdint.h) */
#if (defined(__STDC__) && __STDC__ && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || (defined(__GNUC__) && (defined(_STDINT_H) || defined(_STDINT_H_)) || defined (HAVE_STDINT_H))
#include <stdint.h>
-
+# undef opus_int64
+# undef opus_int8
+# undef opus_uint64
+# undef opus_uint8
+ typedef int8_t opus_int8;
+ typedef uint8_t opus_uint8;
typedef int16_t opus_int16;
typedef uint16_t opus_uint16;
typedef int32_t opus_int32;
typedef uint32_t opus_uint32;
+ typedef int64_t opus_int64;
+ typedef uint64_t opus_uint64;
#elif defined(_WIN32)
# if defined(__CYGWIN__)
#endif
-#define opus_int int /* used for counters etc; at least 16 bits */
-#define opus_int64 long long
-#define opus_int8 signed char
-
-#define opus_uint unsigned int /* used for counters etc; at least 16 bits */
-#define opus_uint64 unsigned long long
-#define opus_uint8 unsigned char
-
#endif /* OPUS_TYPES_H */
opus_int nSamplesIn, /* I Number of samples in input vector */
ec_enc *psRangeEnc, /* I/O Compressor data structure */
opus_int32 *nBytesOut, /* I/O Number of bytes in payload (input: Max bytes) */
- const opus_int prefillFlag /* I Flag to indicate prefilling buffers no coding */
+ const opus_int prefillFlag, /* I Flag to indicate prefilling buffers no coding */
+ int activity /* I Decision of Opus voice activity detector */
);
/****************************************/
/* Generate CNG signal, by synthesis filtering */
silk_memcpy( CNG_sig_Q14, psCNG->CNG_synth_state, MAX_LPC_ORDER * sizeof( opus_int32 ) );
+ celt_assert( psDec->LPC_order == 10 || psDec->LPC_order == 16 );
for( i = 0; i < length; i++ ) {
- silk_assert( psDec->LPC_order == 10 || psDec->LPC_order == 16 );
/* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */
LPC_pred_Q10 = silk_RSHIFT( psDec->LPC_order, 1 );
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 1 ], A_Q12[ 0 ] );
const opus_int16 *in_ptr;
#endif
- silk_assert( d >= 6 );
- silk_assert( (d & 1) == 0 );
- silk_assert( d <= len );
+ celt_assert( d >= 6 );
+ celt_assert( (d & 1) == 0 );
+ celt_assert( d <= len );
#if defined(FIXED_POINT) && USE_CELT_FIR
- silk_assert( d <= SILK_MAX_ORDER_LPC );
+ celt_assert( d <= SILK_MAX_ORDER_LPC );
for ( j = 0; j < d; j++ ) {
num[ j ] = -B[ j ];
}
opus_int32 a32_QA1[ SILK_MAX_ORDER_LPC ];
silk_assert( LSF_COS_TAB_SZ_FIX == 128 );
- silk_assert( d==10 || d==16 );
+ celt_assert( d==10 || d==16 );
/* convert LSFs to 2*cos(LSF), using piecewise linear curve from table */
ordering = d == 16 ? ordering16 : ordering10;
const opus_int16 *w_Q9_ptr;
const opus_uint8 *cb_Q8_ptr;
- silk_assert( ( LPC_order & 1 ) == 0 );
+ celt_assert( ( LPC_order & 1 ) == 0 );
/* Loop over codebook */
cb_Q8_ptr = pCB_Q8;
opus_int k;
opus_int32 tmp1_int, tmp2_int;
- silk_assert( D > 0 );
- silk_assert( ( D & 1 ) == 0 );
+ celt_assert( D > 0 );
+ celt_assert( ( D & 1 ) == 0 );
/* First value */
tmp1_int = silk_max_int( pNLSF_Q15[ 0 ], 1 );
const opus_int16 *pCB_Wght_Q9;
SAVE_STACK;
- silk_assert( signalType >= 0 && signalType <= 2 );
+ celt_assert( signalType >= 0 && signalType <= 2 );
silk_assert( NLSF_mu_Q20 <= 32767 && NLSF_mu_Q20 >= 0 );
/* NLSF stabilization */
if( ( k & ( 3 - silk_LSHIFT( LSF_interpolation_flag, 1 ) ) ) == 0 ) {
/* Rewhiten with new A coefs */
start_idx = psEncC->ltp_mem_length - lag - psEncC->predictLPCOrder - LTP_ORDER / 2;
- silk_assert( start_idx > 0 );
+ celt_assert( start_idx > 0 );
silk_LPC_analysis_filter( &sLTP[ start_idx ], &NSQ->xq[ start_idx + k * psEncC->subfr_length ],
A_Q12, psEncC->ltp_mem_length - start_idx, psEncC->predictLPCOrder, psEncC->arch );
}
/* Noise shape feedback */
- silk_assert( ( shapingLPCOrder & 1 ) == 0 ); /* check that order is even */
+ celt_assert( ( shapingLPCOrder & 1 ) == 0 ); /* check that order is even */
n_AR_Q12 = silk_NSQ_noise_shape_feedback_loop(&NSQ->sDiff_shp_Q14, NSQ->sAR2_Q14, AR_shp_Q13, shapingLPCOrder, arch);
n_AR_Q12 = silk_SMLAWB( n_AR_Q12, NSQ->sLF_AR_shp_Q14, Tilt_Q14 );
n_LF_Q12 = silk_SMULWB( NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - 1 ], LF_shp_Q14 );
n_LF_Q12 = silk_SMLAWT( n_LF_Q12, NSQ->sLF_AR_shp_Q14, LF_shp_Q14 );
- silk_assert( lag > 0 || signalType != TYPE_VOICED );
+ celt_assert( lag > 0 || signalType != TYPE_VOICED );
/* Combine prediction and noise shaping signals */
tmp1 = silk_SUB32( silk_LSHIFT32( LPC_pred_Q10, 2 ), n_AR_Q12 ); /* Q12 */
/* Rewhiten with new A coefs */
start_idx = psEncC->ltp_mem_length - lag - psEncC->predictLPCOrder - LTP_ORDER / 2;
- silk_assert( start_idx > 0 );
+ celt_assert( start_idx > 0 );
silk_LPC_analysis_filter( &sLTP[ start_idx ], &NSQ->xq[ start_idx + k * psEncC->subfr_length ],
A_Q12, psEncC->ltp_mem_length - start_idx, psEncC->predictLPCOrder, psEncC->arch );
NSQ_sample_struct *psSS;
SAVE_STACK;
- silk_assert( nStatesDelayedDecision > 0 );
+ celt_assert( nStatesDelayedDecision > 0 );
ALLOC( psSampleState, nStatesDelayedDecision, NSQ_sample_pair );
shp_lag_ptr = &NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - lag + HARM_SHAPE_FIR_TAPS / 2 ];
LPC_pred_Q14 = silk_LSHIFT( LPC_pred_Q14, 4 ); /* Q10 -> Q14 */
/* Noise shape feedback */
- silk_assert( ( shapingLPCOrder & 1 ) == 0 ); /* check that order is even */
+ celt_assert( ( shapingLPCOrder & 1 ) == 0 ); /* check that order is even */
/* Output of lowpass section */
tmp2 = silk_SMLAWB( psDD->Diff_Q14, psDD->sAR2_Q14[ 0 ], warping_Q16 );
/* Output of allpass section */
/* Rewhiten LTP state */
idx = psDec->ltp_mem_length - lag - psDec->LPC_order - LTP_ORDER / 2;
- silk_assert( idx > 0 );
+ celt_assert( idx > 0 );
silk_LPC_analysis_filter( &sLTP[ idx ], &psDec->outBuf[ idx ], A_Q12, psDec->ltp_mem_length - idx, psDec->LPC_order, arch );
/* Scale LTP state */
inv_gain_Q30 = silk_INVERSE32_varQ( psPLC->prevGain_Q16[ 1 ], 46 );
/* Copy LPC state */
silk_memcpy( sLPC_Q14_ptr, psDec->sLPC_Q14_buf, MAX_LPC_ORDER * sizeof( opus_int32 ) );
- silk_assert( psDec->LPC_order >= 10 ); /* check that unrolling works */
+ celt_assert( psDec->LPC_order >= 10 ); /* check that unrolling works */
for( i = 0; i < psDec->frame_length; i++ ) {
/* partly unrolled */
/* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */
/* Safety checks */
silk_assert( VAD_N_BANDS == 4 );
- silk_assert( MAX_FRAME_LENGTH >= psEncC->frame_length );
- silk_assert( psEncC->frame_length <= 512 );
- silk_assert( psEncC->frame_length == 8 * silk_RSHIFT( psEncC->frame_length, 3 ) );
+ celt_assert( MAX_FRAME_LENGTH >= psEncC->frame_length );
+ celt_assert( psEncC->frame_length <= 512 );
+ celt_assert( psEncC->frame_length == 8 * silk_RSHIFT( psEncC->frame_length, 3 ) );
/***********************/
/* Filter and Decimate */
speech_nrg += ( b + 1 ) * silk_RSHIFT( Xnrg[ b ] - psSilk_VAD->NL[ b ], 4 );
}
+ if( psEncC->frame_length == 20 * psEncC->fs_kHz ) {
+ speech_nrg = silk_RSHIFT32( speech_nrg, 1 );
+ }
/* Power scaling */
if( speech_nrg <= 0 ) {
SA_Q15 = silk_RSHIFT( SA_Q15, 1 );
- } else if( speech_nrg < 32768 ) {
- if( psEncC->frame_length == 10 * psEncC->fs_kHz ) {
- speech_nrg = silk_LSHIFT_SAT32( speech_nrg, 16 );
- } else {
- speech_nrg = silk_LSHIFT_SAT32( speech_nrg, 15 );
- }
+ } else if( speech_nrg < 16384 ) {
+ speech_nrg = silk_LSHIFT32( speech_nrg, 16 );
/* square-root */
speech_nrg = silk_SQRT_APPROX( speech_nrg );
/* Initially faster smoothing */
if( psSilk_VAD->counter < 1000 ) { /* 1000 = 20 sec */
min_coef = silk_DIV32_16( silk_int16_MAX, silk_RSHIFT( psSilk_VAD->counter, 4 ) + 1 );
+ /* Increment frame counter */
+ psSilk_VAD->counter++;
} else {
min_coef = 0;
}
/* Store as part of state */
psSilk_VAD->NL[ k ] = nl;
}
-
- /* Increment frame counter */
- psSilk_VAD->counter++;
}
{
case 24:
t0_s32x4 = vpadalq_s16( t0_s32x4, t2_s16x8 );
- /* Intend to fall through */
+ /* FALLTHROUGH */
case 16:
t0_s32x4 = vpadalq_s16( t0_s32x4, t1_s16x8 );
vst1q_s32( Atmp_QA + 16, vshll_n_s16( vget_low_s16 ( t2_s16x8 ), QA - 12 ) );
vst1q_s32( Atmp_QA + 20, vshll_n_s16( vget_high_s16( t2_s16x8 ), QA - 12 ) );
- /* Intend to fall through */
+ /* FALLTHROUGH */
case 8:
{
case 6:
DC_resp += (opus_int32)A_Q12[ 5 ];
DC_resp += (opus_int32)A_Q12[ 4 ];
- /* Intend to fall through */
+ /* FALLTHROUGH */
case 4:
DC_resp += (opus_int32)A_Q12[ 3 ];
DC_resp += (opus_int32)A_Q12[ 2 ];
- /* Intend to fall through */
+ /* FALLTHROUGH */
case 2:
DC_resp += (opus_int32)A_Q12[ 1 ];
DC_resp += (opus_int32)A_Q12[ 0 ];
- /* Intend to fall through */
+ /* FALLTHROUGH */
default:
break;
silk_EncControlStruct *encControl /* I Control structure */
)
{
- silk_assert( encControl != NULL );
+ celt_assert( encControl != NULL );
if( ( ( encControl->API_sampleRate != 8000 ) &&
( encControl->API_sampleRate != 12000 ) &&
( encControl->minInternalSampleRate > encControl->desiredInternalSampleRate ) ||
( encControl->maxInternalSampleRate < encControl->desiredInternalSampleRate ) ||
( encControl->minInternalSampleRate > encControl->maxInternalSampleRate ) ) {
- silk_assert( 0 );
+ celt_assert( 0 );
return SILK_ENC_FS_NOT_SUPPORTED;
}
if( encControl->payloadSize_ms != 10 &&
encControl->payloadSize_ms != 20 &&
encControl->payloadSize_ms != 40 &&
encControl->payloadSize_ms != 60 ) {
- silk_assert( 0 );
+ celt_assert( 0 );
return SILK_ENC_PACKET_SIZE_NOT_SUPPORTED;
}
if( encControl->packetLossPercentage < 0 || encControl->packetLossPercentage > 100 ) {
- silk_assert( 0 );
+ celt_assert( 0 );
return SILK_ENC_INVALID_LOSS_RATE;
}
if( encControl->useDTX < 0 || encControl->useDTX > 1 ) {
- silk_assert( 0 );
+ celt_assert( 0 );
return SILK_ENC_INVALID_DTX_SETTING;
}
if( encControl->useCBR < 0 || encControl->useCBR > 1 ) {
- silk_assert( 0 );
+ celt_assert( 0 );
return SILK_ENC_INVALID_CBR_SETTING;
}
if( encControl->useInBandFEC < 0 || encControl->useInBandFEC > 1 ) {
- silk_assert( 0 );
+ celt_assert( 0 );
return SILK_ENC_INVALID_INBAND_FEC_SETTING;
}
if( encControl->nChannelsAPI < 1 || encControl->nChannelsAPI > ENCODER_NUM_CHANNELS ) {
- silk_assert( 0 );
+ celt_assert( 0 );
return SILK_ENC_INVALID_NUMBER_OF_CHANNELS_ERROR;
}
if( encControl->nChannelsInternal < 1 || encControl->nChannelsInternal > ENCODER_NUM_CHANNELS ) {
- silk_assert( 0 );
+ celt_assert( 0 );
return SILK_ENC_INVALID_NUMBER_OF_CHANNELS_ERROR;
}
if( encControl->nChannelsInternal > encControl->nChannelsAPI ) {
- silk_assert( 0 );
+ celt_assert( 0 );
return SILK_ENC_INVALID_NUMBER_OF_CHANNELS_ERROR;
}
if( encControl->complexity < 0 || encControl->complexity > 10 ) {
- silk_assert( 0 );
+ celt_assert( 0 );
return SILK_ENC_INVALID_COMPLEXITY_SETTING;
}
#include "main.h"
#include "tuning_parameters.h"
+/* These tables hold SNR values divided by 21 (so they fit in 8 bits)
+ for different target bitrates spaced at 400 bps interval. The first
+ 10 values are omitted (0-4 kb/s) because they're all zeros.
+ These tables were obtained by running different SNRs through the
+ encoder and measuring the active bitrate. */
+static const unsigned char silk_TargetRate_NB_21[117 - 10] = {
+ 0, 15, 39, 52, 61, 68,
+ 74, 79, 84, 88, 92, 95, 99,102,105,108,111,114,117,119,122,124,
+ 126,129,131,133,135,137,139,142,143,145,147,149,151,153,155,157,
+ 158,160,162,163,165,167,168,170,171,173,174,176,177,179,180,182,
+ 183,185,186,187,189,190,192,193,194,196,197,199,200,201,203,204,
+ 205,207,208,209,211,212,213,215,216,217,219,220,221,223,224,225,
+ 227,228,230,231,232,234,235,236,238,239,241,242,243,245,246,248,
+ 249,250,252,253,255
+};
+
+static const unsigned char silk_TargetRate_MB_21[165 - 10] = {
+ 0, 0, 28, 43, 52, 59,
+ 65, 70, 74, 78, 81, 85, 87, 90, 93, 95, 98,100,102,105,107,109,
+ 111,113,115,116,118,120,122,123,125,127,128,130,131,133,134,136,
+ 137,138,140,141,143,144,145,147,148,149,151,152,153,154,156,157,
+ 158,159,160,162,163,164,165,166,167,168,169,171,172,173,174,175,
+ 176,177,178,179,180,181,182,183,184,185,186,187,188,188,189,190,
+ 191,192,193,194,195,196,197,198,199,200,201,202,203,203,204,205,
+ 206,207,208,209,210,211,212,213,214,214,215,216,217,218,219,220,
+ 221,222,223,224,224,225,226,227,228,229,230,231,232,233,234,235,
+ 236,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,
+ 251,252,253,254,255
+};
+
+static const unsigned char silk_TargetRate_WB_21[201 - 10] = {
+ 0, 0, 0, 8, 29, 41,
+ 49, 56, 62, 66, 70, 74, 77, 80, 83, 86, 88, 91, 93, 95, 97, 99,
+ 101,103,105,107,108,110,112,113,115,116,118,119,121,122,123,125,
+ 126,127,129,130,131,132,134,135,136,137,138,140,141,142,143,144,
+ 145,146,147,148,149,150,151,152,153,154,156,157,158,159,159,160,
+ 161,162,163,164,165,166,167,168,169,170,171,171,172,173,174,175,
+ 176,177,177,178,179,180,181,181,182,183,184,185,185,186,187,188,
+ 189,189,190,191,192,192,193,194,195,195,196,197,198,198,199,200,
+ 200,201,202,203,203,204,205,206,206,207,208,209,209,210,211,211,
+ 212,213,214,214,215,216,216,217,218,219,219,220,221,221,222,223,
+ 224,224,225,226,226,227,228,229,229,230,231,232,232,233,234,234,
+ 235,236,237,237,238,239,240,240,241,242,243,243,244,245,246,246,
+ 247,248,249,249,250,251,252,253,255
+};
+
/* Control SNR of redidual quantizer */
opus_int silk_control_SNR(
silk_encoder_state *psEncC, /* I/O Pointer to Silk encoder state */
opus_int32 TargetRate_bps /* I Target max bitrate (bps) */
)
{
- opus_int k, ret = SILK_NO_ERROR;
- opus_int32 frac_Q6;
- const opus_int32 *rateTable;
-
- /* Set bitrate/coding quality */
- TargetRate_bps = silk_LIMIT( TargetRate_bps, MIN_TARGET_RATE_BPS, MAX_TARGET_RATE_BPS );
- if( TargetRate_bps != psEncC->TargetRate_bps ) {
- psEncC->TargetRate_bps = TargetRate_bps;
-
- /* If new TargetRate_bps, translate to SNR_dB value */
- if( psEncC->fs_kHz == 8 ) {
- rateTable = silk_TargetRate_table_NB;
- } else if( psEncC->fs_kHz == 12 ) {
- rateTable = silk_TargetRate_table_MB;
- } else {
- rateTable = silk_TargetRate_table_WB;
- }
+ int id;
+ int bound;
+ const unsigned char *snr_table;
- /* Reduce bitrate for 10 ms modes in these calculations */
- if( psEncC->nb_subfr == 2 ) {
- TargetRate_bps -= REDUCE_BITRATE_10_MS_BPS;
- }
-
- /* Find bitrate interval in table and interpolate */
- for( k = 1; k < TARGET_RATE_TAB_SZ; k++ ) {
- if( TargetRate_bps <= rateTable[ k ] ) {
- frac_Q6 = silk_DIV32( silk_LSHIFT( TargetRate_bps - rateTable[ k - 1 ], 6 ), rateTable[ k ] - rateTable[ k - 1 ] );
- psEncC->SNR_dB_Q7 = silk_LSHIFT( silk_SNR_table_Q1[ k - 1 ], 6 ) + silk_MUL( frac_Q6, silk_SNR_table_Q1[ k ] - silk_SNR_table_Q1[ k - 1 ] );
- break;
- }
- }
+ psEncC->TargetRate_bps = TargetRate_bps;
+ if( psEncC->nb_subfr == 2 ) {
+ TargetRate_bps -= 2000 + psEncC->fs_kHz/16;
}
-
- return ret;
+ if( psEncC->fs_kHz == 8 ) {
+ bound = sizeof(silk_TargetRate_NB_21);
+ snr_table = silk_TargetRate_NB_21;
+ } else if( psEncC->fs_kHz == 12 ) {
+ bound = sizeof(silk_TargetRate_MB_21);
+ snr_table = silk_TargetRate_MB_21;
+ } else {
+ bound = sizeof(silk_TargetRate_WB_21);
+ snr_table = silk_TargetRate_WB_21;
+ }
+ id = (TargetRate_bps+200)/400;
+ id = silk_min(id - 10, bound-1);
+ if( id <= 0 ) {
+ psEncC->SNR_dB_Q7 = 0;
+ } else {
+ psEncC->SNR_dB_Q7 = snr_table[id]*21;
+ }
+ return SILK_NO_ERROR;
}
)
{
opus_int fs_kHz;
+ opus_int orig_kHz;
opus_int32 fs_Hz;
- fs_kHz = psEncC->fs_kHz;
+ orig_kHz = psEncC->fs_kHz;
+ /* Handle a bandwidth-switching reset where we need to be aware what the last sampling rate was. */
+ if( orig_kHz == 0 ) {
+ orig_kHz = psEncC->sLP.saved_fs_kHz;
+ }
+ fs_kHz = orig_kHz;
fs_Hz = silk_SMULBB( fs_kHz, 1000 );
if( fs_Hz == 0 ) {
/* Encoder has just been initialized */
}
if( psEncC->allow_bandwidth_switch || encControl->opusCanSwitch ) {
/* Check if we should switch down */
- if( silk_SMULBB( psEncC->fs_kHz, 1000 ) > psEncC->desiredInternal_fs_Hz )
+ if( silk_SMULBB( orig_kHz, 1000 ) > psEncC->desiredInternal_fs_Hz )
{
/* Switch down */
if( psEncC->sLP.mode == 0 ) {
psEncC->sLP.mode = 0;
/* Switch to a lower sample frequency */
- fs_kHz = psEncC->fs_kHz == 16 ? 12 : 8;
+ fs_kHz = orig_kHz == 16 ? 12 : 8;
} else {
if( psEncC->sLP.transition_frame_no <= 0 ) {
encControl->switchReady = 1;
}
else
/* Check if we should switch up */
- if( silk_SMULBB( psEncC->fs_kHz, 1000 ) < psEncC->desiredInternal_fs_Hz )
+ if( silk_SMULBB( orig_kHz, 1000 ) < psEncC->desiredInternal_fs_Hz )
{
/* Switch up */
if( encControl->opusCanSwitch ) {
/* Switch to a higher sample frequency */
- fs_kHz = psEncC->fs_kHz == 8 ? 12 : 16;
+ fs_kHz = orig_kHz == 8 ? 12 : 16;
/* New transition */
psEncC->sLP.transition_frame_no = 0;
}
/* Set internal sampling frequency */
- silk_assert( fs_kHz == 8 || fs_kHz == 12 || fs_kHz == 16 );
- silk_assert( psEnc->sCmn.nb_subfr == 2 || psEnc->sCmn.nb_subfr == 4 );
+ celt_assert( fs_kHz == 8 || fs_kHz == 12 || fs_kHz == 16 );
+ celt_assert( psEnc->sCmn.nb_subfr == 2 || psEnc->sCmn.nb_subfr == 4 );
if( psEnc->sCmn.fs_kHz != fs_kHz ) {
/* reset part of the state */
silk_memset( &psEnc->sShape, 0, sizeof( psEnc->sShape ) );
}
/* Check that settings are valid */
- silk_assert( ( psEnc->sCmn.subfr_length * psEnc->sCmn.nb_subfr ) == psEnc->sCmn.frame_length );
+ celt_assert( ( psEnc->sCmn.subfr_length * psEnc->sCmn.nb_subfr ) == psEnc->sCmn.frame_length );
return ret;
}
opus_int ret = 0;
/* Set encoding complexity */
- silk_assert( Complexity >= 0 && Complexity <= 10 );
+ celt_assert( Complexity >= 0 && Complexity <= 10 );
if( Complexity < 1 ) {
psEncC->pitchEstimationComplexity = SILK_PE_MIN_COMPLEX;
psEncC->pitchEstimationThreshold_Q16 = SILK_FIX_CONST( 0.8, 16 );
psEncC->shapeWinLength = SUB_FRAME_LENGTH_MS * psEncC->fs_kHz + 2 * psEncC->la_shape;
psEncC->Complexity = Complexity;
- silk_assert( psEncC->pitchEstimationLPCOrder <= MAX_FIND_PITCH_LPC_ORDER );
- silk_assert( psEncC->shapingLPCOrder <= MAX_SHAPE_LPC_ORDER );
- silk_assert( psEncC->nStatesDelayedDecision <= MAX_DEL_DEC_STATES );
- silk_assert( psEncC->warping_Q16 <= 32767 );
- silk_assert( psEncC->la_shape <= LA_SHAPE_MAX );
- silk_assert( psEncC->shapeWinLength <= SHAPE_LPC_WIN_MAX );
+ celt_assert( psEncC->pitchEstimationLPCOrder <= MAX_FIND_PITCH_LPC_ORDER );
+ celt_assert( psEncC->shapingLPCOrder <= MAX_SHAPE_LPC_ORDER );
+ celt_assert( psEncC->nStatesDelayedDecision <= MAX_DEL_DEC_STATES );
+ celt_assert( psEncC->warping_Q16 <= 32767 );
+ celt_assert( psEncC->la_shape <= LA_SHAPE_MAX );
+ celt_assert( psEncC->shapeWinLength <= SHAPE_LPC_WIN_MAX );
return ret;
}
int delay_stack_alloc;
SAVE_STACK;
- silk_assert( decControl->nChannelsInternal == 1 || decControl->nChannelsInternal == 2 );
+ celt_assert( decControl->nChannelsInternal == 1 || decControl->nChannelsInternal == 2 );
/**********************************/
/* Test if first frame in payload */
channel_state[ n ].nFramesPerPacket = 3;
channel_state[ n ].nb_subfr = 4;
} else {
- silk_assert( 0 );
+ celt_assert( 0 );
RESTORE_STACK;
return SILK_DEC_INVALID_FRAME_SIZE;
}
fs_kHz_dec = ( decControl->internalSampleRate >> 10 ) + 1;
if( fs_kHz_dec != 8 && fs_kHz_dec != 12 && fs_kHz_dec != 16 ) {
- silk_assert( 0 );
+ celt_assert( 0 );
RESTORE_STACK;
return SILK_DEC_INVALID_SAMPLING_FREQUENCY;
}
if( k == 0 || ( k == 2 && NLSF_interpolation_flag ) ) {
/* Rewhiten with new A coefs */
start_idx = psDec->ltp_mem_length - lag - psDec->LPC_order - LTP_ORDER / 2;
- silk_assert( start_idx > 0 );
+ celt_assert( start_idx > 0 );
if( k == 2 ) {
silk_memcpy( &psDec->outBuf[ psDec->ltp_mem_length ], xq, 2 * psDec->subfr_length * sizeof( opus_int16 ) );
for( i = 0; i < psDec->subfr_length; i++ ) {
/* Short-term prediction */
- silk_assert( psDec->LPC_order == 10 || psDec->LPC_order == 16 );
+ celt_assert( psDec->LPC_order == 10 || psDec->LPC_order == 16 );
/* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */
LPC_pred_Q10 = silk_RSHIFT( psDec->LPC_order, 1 );
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14[ MAX_LPC_ORDER + i - 1 ], A_Q12_tmp[ 0 ] );
psDecCtrl->LTP_scale_Q14 = 0;
/* Safety checks */
- silk_assert( L > 0 && L <= MAX_FRAME_LENGTH );
+ celt_assert( L > 0 && L <= MAX_FRAME_LENGTH );
if( lostFlag == FLAG_DECODE_NORMAL ||
( lostFlag == FLAG_DECODE_LBRR && psDec->LBRR_flags[ psDec->nFramesDecoded ] == 1 ) )
psDec->lossCnt = 0;
psDec->prevSignalType = psDec->indices.signalType;
- silk_assert( psDec->prevSignalType >= 0 && psDec->prevSignalType <= 2 );
+ celt_assert( psDec->prevSignalType >= 0 && psDec->prevSignalType <= 2 );
/* A frame has been decoded without errors */
psDec->first_frame_after_reset = 0;
/*************************/
/* Update output buffer. */
/*************************/
- silk_assert( psDec->ltp_mem_length >= psDec->frame_length );
+ celt_assert( psDec->ltp_mem_length >= psDec->frame_length );
mv_len = psDec->ltp_mem_length - psDec->frame_length;
silk_memmove( psDec->outBuf, &psDec->outBuf[ psDec->frame_length ], mv_len * sizeof(opus_int16) );
silk_memcpy( &psDec->outBuf[ mv_len ], pOut, psDec->frame_length * sizeof( opus_int16 ) );
/**********************/
psDec->indices.NLSFIndices[ 0 ] = (opus_int8)ec_dec_icdf( psRangeDec, &psDec->psNLSF_CB->CB1_iCDF[ ( psDec->indices.signalType >> 1 ) * psDec->psNLSF_CB->nVectors ], 8 );
silk_NLSF_unpack( ec_ix, pred_Q8, psDec->psNLSF_CB, psDec->indices.NLSFIndices[ 0 ] );
- silk_assert( psDec->psNLSF_CB->order == psDec->LPC_order );
+ celt_assert( psDec->psNLSF_CB->order == psDec->LPC_order );
for( i = 0; i < psDec->psNLSF_CB->order; i++ ) {
Ix = ec_dec_icdf( psRangeDec, &psDec->psNLSF_CB->ec_iCDF[ ec_ix[ i ] ], 8 );
if( Ix == 0 ) {
Lag_CB_ptr = &silk_CB_lags_stage2[ 0 ][ 0 ];
cbk_size = PE_NB_CBKS_STAGE2_EXT;
} else {
- silk_assert( nb_subfr == PE_MAX_NB_SUBFR >> 1 );
+ celt_assert( nb_subfr == PE_MAX_NB_SUBFR >> 1 );
Lag_CB_ptr = &silk_CB_lags_stage2_10_ms[ 0 ][ 0 ];
cbk_size = PE_NB_CBKS_STAGE2_10MS;
}
Lag_CB_ptr = &silk_CB_lags_stage3[ 0 ][ 0 ];
cbk_size = PE_NB_CBKS_STAGE3_MAX;
} else {
- silk_assert( nb_subfr == PE_MAX_NB_SUBFR >> 1 );
+ celt_assert( nb_subfr == PE_MAX_NB_SUBFR >> 1 );
Lag_CB_ptr = &silk_CB_lags_stage3_10_ms[ 0 ][ 0 ];
cbk_size = PE_NB_CBKS_STAGE3_10MS;
}
silk_assert( 1 << LOG2_SHELL_CODEC_FRAME_LENGTH == SHELL_CODEC_FRAME_LENGTH );
iter = silk_RSHIFT( frame_length, LOG2_SHELL_CODEC_FRAME_LENGTH );
if( iter * SHELL_CODEC_FRAME_LENGTH < frame_length ) {
- silk_assert( frame_length == 12 * 10 ); /* Make sure only happens for 10 ms @ 12 kHz */
+ celt_assert( frame_length == 12 * 10 ); /* Make sure only happens for 10 ms @ 12 kHz */
iter++;
}
{
opus_int frame_length, ret = 0;
- silk_assert( fs_kHz == 8 || fs_kHz == 12 || fs_kHz == 16 );
- silk_assert( psDec->nb_subfr == MAX_NB_SUBFR || psDec->nb_subfr == MAX_NB_SUBFR/2 );
+ celt_assert( fs_kHz == 8 || fs_kHz == 12 || fs_kHz == 16 );
+ celt_assert( psDec->nb_subfr == MAX_NB_SUBFR || psDec->nb_subfr == MAX_NB_SUBFR/2 );
/* New (sub)frame length */
psDec->subfr_length = silk_SMULBB( SUB_FRAME_LENGTH_MS, fs_kHz );
psDec->pitch_lag_low_bits_iCDF = silk_uniform4_iCDF;
} else {
/* unsupported sampling rate */
- silk_assert( 0 );
+ celt_assert( 0 );
}
psDec->first_frame_after_reset = 1;
psDec->lagPrev = 100;
}
/* Check that settings are valid */
- silk_assert( psDec->frame_length > 0 && psDec->frame_length <= MAX_FRAME_LENGTH );
+ celt_assert( psDec->frame_length > 0 && psDec->frame_length <= MAX_FRAME_LENGTH );
return ret;
}
/* Limits on bitrate */
#define MIN_TARGET_RATE_BPS 5000
#define MAX_TARGET_RATE_BPS 80000
-#define TARGET_RATE_TAB_SZ 8
/* LBRR thresholds */
#define LBRR_NB_MIN_RATE_BPS 12000
#define MAX_CONSECUTIVE_DTX 20 /* eq 400 ms */
#define DTX_ACTIVITY_THRESHOLD 0.1f
+/* VAD decision */
+#define VAD_NO_DECISION -1
+#define VAD_NO_ACTIVITY 0
+#define VAD_ACTIVITY 1
+
/* Maximum sampling frequency */
#define MAX_FS_KHZ 16
#define MAX_API_FS_KHZ 48
silk_memset( psEnc, 0, sizeof( silk_encoder ) );
for( n = 0; n < ENCODER_NUM_CHANNELS; n++ ) {
if( ret += silk_init_encoder( &psEnc->state_Fxx[ n ], arch ) ) {
- silk_assert( 0 );
+ celt_assert( 0 );
}
}
/* Read control structure */
if( ret += silk_QueryEncoder( encState, encStatus ) ) {
- silk_assert( 0 );
+ celt_assert( 0 );
}
return ret;
opus_int nSamplesIn, /* I Number of samples in input vector */
ec_enc *psRangeEnc, /* I/O Compressor data structure */
opus_int32 *nBytesOut, /* I/O Number of bytes in payload (input: Max bytes) */
- const opus_int prefillFlag /* I Flag to indicate prefilling buffers no coding */
+ const opus_int prefillFlag, /* I Flag to indicate prefilling buffers no coding */
+ opus_int activity /* I Decision of Opus voice activity detector */
)
{
opus_int n, i, nBits, flags, tmp_payloadSize_ms = 0, tmp_complexity = 0, ret = 0;
/* Check values in encoder control structure */
if( ( ret = check_control_input( encControl ) ) != 0 ) {
- silk_assert( 0 );
+ celt_assert( 0 );
RESTORE_STACK;
return ret;
}
tot_blocks = ( nBlocksOf10ms > 1 ) ? nBlocksOf10ms >> 1 : 1;
curr_block = 0;
if( prefillFlag ) {
+ silk_LP_state save_LP;
/* Only accept input length of 10 ms */
if( nBlocksOf10ms != 1 ) {
- silk_assert( 0 );
+ celt_assert( 0 );
RESTORE_STACK;
return SILK_ENC_INPUT_INVALID_NO_OF_SAMPLES;
}
+ if ( prefillFlag == 2 ) {
+ save_LP = psEnc->state_Fxx[ 0 ].sCmn.sLP;
+ /* Save the sampling rate so the bandwidth switching code can keep handling transitions. */
+ save_LP.saved_fs_kHz = psEnc->state_Fxx[ 0 ].sCmn.fs_kHz;
+ }
/* Reset Encoder */
for( n = 0; n < encControl->nChannelsInternal; n++ ) {
ret = silk_init_encoder( &psEnc->state_Fxx[ n ], psEnc->state_Fxx[ n ].sCmn.arch );
- silk_assert( !ret );
+ /* Restore the variable LP state. */
+ if ( prefillFlag == 2 ) {
+ psEnc->state_Fxx[ n ].sCmn.sLP = save_LP;
+ }
+ celt_assert( !ret );
}
tmp_payloadSize_ms = encControl->payloadSize_ms;
encControl->payloadSize_ms = 10;
} else {
/* Only accept input lengths that are a multiple of 10 ms */
if( nBlocksOf10ms * encControl->API_sampleRate != 100 * nSamplesIn || nSamplesIn < 0 ) {
- silk_assert( 0 );
+ celt_assert( 0 );
RESTORE_STACK;
return SILK_ENC_INPUT_INVALID_NO_OF_SAMPLES;
}
/* Make sure no more than one packet can be produced */
if( 1000 * (opus_int32)nSamplesIn > encControl->payloadSize_ms * encControl->API_sampleRate ) {
- silk_assert( 0 );
+ celt_assert( 0 );
RESTORE_STACK;
return SILK_ENC_INPUT_INVALID_NO_OF_SAMPLES;
}
}
psEnc->state_Fxx[ n ].sCmn.inDTX = psEnc->state_Fxx[ n ].sCmn.useDTX;
}
- silk_assert( encControl->nChannelsInternal == 1 || psEnc->state_Fxx[ 0 ].sCmn.fs_kHz == psEnc->state_Fxx[ 1 ].sCmn.fs_kHz );
+ celt_assert( encControl->nChannelsInternal == 1 || psEnc->state_Fxx[ 0 ].sCmn.fs_kHz == psEnc->state_Fxx[ 1 ].sCmn.fs_kHz );
/* Input buffering/resampling and encoding */
nSamplesToBufferMax =
}
psEnc->state_Fxx[ 0 ].sCmn.inputBufIx += nSamplesToBuffer;
} else {
- silk_assert( encControl->nChannelsAPI == 1 && encControl->nChannelsInternal == 1 );
+ celt_assert( encControl->nChannelsAPI == 1 && encControl->nChannelsInternal == 1 );
silk_memcpy(buf, samplesIn, nSamplesFromInput*sizeof(opus_int16));
ret += silk_resampler( &psEnc->state_Fxx[ 0 ].sCmn.resampler_state,
&psEnc->state_Fxx[ 0 ].sCmn.inputBuf[ psEnc->state_Fxx[ 0 ].sCmn.inputBufIx + 2 ], buf, nSamplesFromInput );
/* Silk encoder */
if( psEnc->state_Fxx[ 0 ].sCmn.inputBufIx >= psEnc->state_Fxx[ 0 ].sCmn.frame_length ) {
/* Enough data in input buffer, so encode */
- silk_assert( psEnc->state_Fxx[ 0 ].sCmn.inputBufIx == psEnc->state_Fxx[ 0 ].sCmn.frame_length );
- silk_assert( encControl->nChannelsInternal == 1 || psEnc->state_Fxx[ 1 ].sCmn.inputBufIx == psEnc->state_Fxx[ 1 ].sCmn.frame_length );
+ celt_assert( psEnc->state_Fxx[ 0 ].sCmn.inputBufIx == psEnc->state_Fxx[ 0 ].sCmn.frame_length );
+ celt_assert( encControl->nChannelsInternal == 1 || psEnc->state_Fxx[ 1 ].sCmn.inputBufIx == psEnc->state_Fxx[ 1 ].sCmn.frame_length );
/* Deal with LBRR data */
if( psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded == 0 && !prefillFlag ) {
psEnc->state_Fxx[ 1 ].sCmn.sNSQ.prev_gain_Q16 = 65536;
psEnc->state_Fxx[ 1 ].sCmn.first_frame_after_reset = 1;
}
- silk_encode_do_VAD_Fxx( &psEnc->state_Fxx[ 1 ] );
+ silk_encode_do_VAD_Fxx( &psEnc->state_Fxx[ 1 ], activity );
} else {
psEnc->state_Fxx[ 1 ].sCmn.VAD_flags[ psEnc->state_Fxx[ 0 ].sCmn.nFramesEncoded ] = 0;
}
silk_memcpy( psEnc->state_Fxx[ 0 ].sCmn.inputBuf, psEnc->sStereo.sMid, 2 * sizeof( opus_int16 ) );
silk_memcpy( psEnc->sStereo.sMid, &psEnc->state_Fxx[ 0 ].sCmn.inputBuf[ psEnc->state_Fxx[ 0 ].sCmn.frame_length ], 2 * sizeof( opus_int16 ) );
}
- silk_encode_do_VAD_Fxx( &psEnc->state_Fxx[ 0 ] );
+ silk_encode_do_VAD_Fxx( &psEnc->state_Fxx[ 0 ], activity );
/* Encode */
for( n = 0; n < encControl->nChannelsInternal; n++ ) {
/* Encode signal type and quantizer offset */
/*******************************************/
typeOffset = 2 * psIndices->signalType + psIndices->quantOffsetType;
- silk_assert( typeOffset >= 0 && typeOffset < 6 );
- silk_assert( encode_LBRR == 0 || typeOffset >= 2 );
+ celt_assert( typeOffset >= 0 && typeOffset < 6 );
+ celt_assert( encode_LBRR == 0 || typeOffset >= 2 );
if( encode_LBRR || typeOffset >= 2 ) {
ec_enc_icdf( psRangeEnc, typeOffset - 2, silk_type_offset_VAD_iCDF, 8 );
} else {
/****************/
ec_enc_icdf( psRangeEnc, psIndices->NLSFIndices[ 0 ], &psEncC->psNLSF_CB->CB1_iCDF[ ( psIndices->signalType >> 1 ) * psEncC->psNLSF_CB->nVectors ], 8 );
silk_NLSF_unpack( ec_ix, pred_Q8, psEncC->psNLSF_CB, psIndices->NLSFIndices[ 0 ] );
- silk_assert( psEncC->psNLSF_CB->order == psEncC->predictLPCOrder );
+ celt_assert( psEncC->psNLSF_CB->order == psEncC->predictLPCOrder );
for( i = 0; i < psEncC->psNLSF_CB->order; i++ ) {
if( psIndices->NLSFIndices[ i+1 ] >= NLSF_QUANT_MAX_AMPLITUDE ) {
ec_enc_icdf( psRangeEnc, 2 * NLSF_QUANT_MAX_AMPLITUDE, &psEncC->psNLSF_CB->ec_iCDF[ ec_ix[ i ] ], 8 );
silk_assert( 1 << LOG2_SHELL_CODEC_FRAME_LENGTH == SHELL_CODEC_FRAME_LENGTH );
iter = silk_RSHIFT( frame_length, LOG2_SHELL_CODEC_FRAME_LENGTH );
if( iter * SHELL_CODEC_FRAME_LENGTH < frame_length ) {
- silk_assert( frame_length == 12 * 10 ); /* Make sure only happens for 10 ms @ 12 kHz */
+ celt_assert( frame_length == 12 * 10 ); /* Make sure only happens for 10 ms @ 12 kHz */
iter++;
silk_memset( &pulses[ frame_length ], 0, SHELL_CODEC_FRAME_LENGTH * sizeof(opus_int8));
}
opus_int k, f_Q16, c_Q16;
opus_int32 S0_Q16, S1_Q16;
- silk_assert( win_type == 1 || win_type == 2 );
+ celt_assert( win_type == 1 || win_type == 2 );
/* Length must be in a range from 16 to 120 and a multiple of 4 */
- silk_assert( length >= 16 && length <= 120 );
- silk_assert( ( length & 3 ) == 0 );
+ celt_assert( length >= 16 && length <= 120 );
+ celt_assert( ( length & 3 ) == 0 );
/* Frequency */
k = ( length >> 2 ) - 4;
- silk_assert( k >= 0 && k <= 26 );
+ celt_assert( k >= 0 && k <= 26 );
f_Q16 = (opus_int)freq_table_Q16[ k ];
/* Factor used for cosine approximation */
opus_int32 xcorr[ SILK_MAX_ORDER_LPC ];
opus_int64 C0_64;
- silk_assert( subfr_length * nb_subfr <= MAX_FRAME_SIZE );
+ celt_assert( subfr_length * nb_subfr <= MAX_FRAME_SIZE );
/* Compute autocorrelations, added over subframes */
C0_64 = silk_inner_prod16_aligned_64( x, x, subfr_length*nb_subfr, arch );
);
void silk_encode_do_VAD_FIX(
- silk_encoder_state_FIX *psEnc /* I/O Pointer to Silk FIX encoder state */
+ silk_encoder_state_FIX *psEnc, /* I/O Pointer to Silk FIX encoder state */
+ opus_int activity /* I Decision of Opus voice activity detector */
)
{
+ const opus_int activity_threshold = SILK_FIX_CONST( SPEECH_ACTIVITY_DTX_THRES, 8 );
+
/****************************/
/* Voice Activity Detection */
/****************************/
silk_VAD_GetSA_Q8( &psEnc->sCmn, psEnc->sCmn.inputBuf + 1, psEnc->sCmn.arch );
+ /* If Opus VAD is inactive and Silk VAD is active: lower Silk VAD to just under the threshold */
+ if( activity == VAD_NO_ACTIVITY && psEnc->sCmn.speech_activity_Q8 >= activity_threshold ) {
+ psEnc->sCmn.speech_activity_Q8 = activity_threshold - 1;
+ }
/**************************************************/
/* Convert speech activity into VAD and DTX flags */
/**************************************************/
- if( psEnc->sCmn.speech_activity_Q8 < SILK_FIX_CONST( SPEECH_ACTIVITY_DTX_THRES, 8 ) ) {
+ if( psEnc->sCmn.speech_activity_Q8 < activity_threshold ) {
psEnc->sCmn.indices.signalType = TYPE_NO_VOICE_ACTIVITY;
psEnc->sCmn.noSpeechCounter++;
- if( psEnc->sCmn.noSpeechCounter < NB_SPEECH_FRAMES_BEFORE_DTX ) {
+ if( psEnc->sCmn.noSpeechCounter <= NB_SPEECH_FRAMES_BEFORE_DTX ) {
psEnc->sCmn.inDTX = 0;
} else if( psEnc->sCmn.noSpeechCounter > MAX_CONSECUTIVE_DTX + NB_SPEECH_FRAMES_BEFORE_DTX ) {
psEnc->sCmn.noSpeechCounter = NB_SPEECH_FRAMES_BEFORE_DTX;
if( found_lower && ( gainsID == gainsID_lower || nBits > maxBits ) ) {
/* Restore output state from earlier iteration that did meet the bitrate budget */
silk_memcpy( psRangeEnc, &sRangeEnc_copy2, sizeof( ec_enc ) );
- silk_assert( sRangeEnc_copy2.offs <= 1275 );
+ celt_assert( sRangeEnc_copy2.offs <= 1275 );
silk_memcpy( psRangeEnc->buf, ec_buf_copy, sRangeEnc_copy2.offs );
silk_memcpy( &psEnc->sCmn.sNSQ, &sNSQ_copy2, sizeof( silk_nsq_state ) );
psEnc->sShape.LastGainIndex = LastGainIndex_copy2;
gainsID_lower = gainsID;
/* Copy part of the output state */
silk_memcpy( &sRangeEnc_copy2, psRangeEnc, sizeof( ec_enc ) );
- silk_assert( psRangeEnc->offs <= 1275 );
+ celt_assert( psRangeEnc->offs <= 1275 );
silk_memcpy( ec_buf_copy, psRangeEnc->buf, psRangeEnc->offs );
silk_memcpy( &sNSQ_copy2, &psEnc->sCmn.sNSQ, sizeof( silk_nsq_state ) );
LastGainIndex_copy2 = psEnc->sShape.LastGainIndex;
silk_A2NLSF( NLSF_Q15, a_Q16, psEncC->predictLPCOrder );
}
- silk_assert( psEncC->indices.NLSFInterpCoef_Q2 == 4 || ( psEncC->useInterpolatedNLSFs && !psEncC->first_frame_after_reset && psEncC->nb_subfr == MAX_NB_SUBFR ) );
+ celt_assert( psEncC->indices.NLSFInterpCoef_Q2 == 4 || ( psEncC->useInterpolatedNLSFs && !psEncC->first_frame_after_reset && psEncC->nb_subfr == MAX_NB_SUBFR ) );
RESTORE_STACK;
}
buf_len = psEnc->sCmn.la_pitch + psEnc->sCmn.frame_length + psEnc->sCmn.ltp_mem_length;
/* Safety check */
- silk_assert( buf_len >= psEnc->sCmn.pitch_LPC_win_length );
+ celt_assert( buf_len >= psEnc->sCmn.pitch_LPC_win_length );
/*************************************/
/* Estimate LPC AR coefficients */
/**********/
/* VOICED */
/**********/
- silk_assert( psEnc->sCmn.ltp_mem_length - psEnc->sCmn.predictLPCOrder >= psEncCtrl->pitchL[ 0 ] + LTP_ORDER / 2 );
+ celt_assert( psEnc->sCmn.ltp_mem_length - psEnc->sCmn.predictLPCOrder >= psEncCtrl->pitchL[ 0 ] + LTP_ORDER / 2 );
ALLOC( xXLTP_Q17, psEnc->sCmn.nb_subfr * LTP_ORDER, opus_int32 );
ALLOC( XXLTP_Q17, psEnc->sCmn.nb_subfr * LTP_ORDER * LTP_ORDER, opus_int32 );
/* Encoder main function */
void silk_encode_do_VAD_FIX(
- silk_encoder_state_FIX *psEnc /* I/O Pointer to Silk FIX encoder state */
+ silk_encoder_state_FIX *psEnc, /* I/O Pointer to Silk FIX encoder state */
+ opus_int activity /* I Decision of Opus voice activity detector */
);
/* Encoder main function */
SAVE_STACK;
/* Check for valid sampling frequency */
- silk_assert( Fs_kHz == 8 || Fs_kHz == 12 || Fs_kHz == 16 );
+ celt_assert( Fs_kHz == 8 || Fs_kHz == 12 || Fs_kHz == 16 );
/* Check for valid complexity setting */
- silk_assert( complexity >= SILK_PE_MIN_COMPLEX );
- silk_assert( complexity <= SILK_PE_MAX_COMPLEX );
+ celt_assert( complexity >= SILK_PE_MIN_COMPLEX );
+ celt_assert( complexity <= SILK_PE_MAX_COMPLEX );
silk_assert( search_thres1_Q16 >= 0 && search_thres1_Q16 <= (1<<16) );
silk_assert( search_thres2_Q13 >= 0 && search_thres2_Q13 <= (1<<13) );
silk_resampler_down2_3( filt_state, frame_8kHz_buf, frame, frame_length );
frame_8kHz = frame_8kHz_buf;
} else {
- silk_assert( Fs_kHz == 8 );
+ celt_assert( Fs_kHz == 8 );
frame_8kHz = frame;
}
target_ptr = &frame_4kHz[ silk_LSHIFT( SF_LENGTH_4KHZ, 2 ) ];
for( k = 0; k < nb_subfr >> 1; k++ ) {
/* Check that we are within range of the array */
- silk_assert( target_ptr >= frame_4kHz );
- silk_assert( target_ptr + SF_LENGTH_8KHZ <= frame_4kHz + frame_length_4kHz );
+ celt_assert( target_ptr >= frame_4kHz );
+ celt_assert( target_ptr + SF_LENGTH_8KHZ <= frame_4kHz + frame_length_4kHz );
basis_ptr = target_ptr - MIN_LAG_4KHZ;
/* Check that we are within range of the array */
- silk_assert( basis_ptr >= frame_4kHz );
- silk_assert( basis_ptr + SF_LENGTH_8KHZ <= frame_4kHz + frame_length_4kHz );
+ celt_assert( basis_ptr >= frame_4kHz );
+ celt_assert( basis_ptr + SF_LENGTH_8KHZ <= frame_4kHz + frame_length_4kHz );
celt_pitch_xcorr( target_ptr, target_ptr - MAX_LAG_4KHZ, xcorr32, SF_LENGTH_8KHZ, MAX_LAG_4KHZ - MIN_LAG_4KHZ + 1, arch );
/* Sort */
length_d_srch = silk_ADD_LSHIFT32( 4, complexity, 1 );
- silk_assert( 3 * length_d_srch <= PE_D_SRCH_LENGTH );
+ celt_assert( 3 * length_d_srch <= PE_D_SRCH_LENGTH );
silk_insertion_sort_decreasing_int16( C, d_srch, CSTRIDE_4KHZ,
length_d_srch );
break;
}
}
- silk_assert( length_d_srch > 0 );
+ celt_assert( length_d_srch > 0 );
ALLOC( d_comp, D_COMP_STRIDE, opus_int16 );
for( i = D_COMP_MIN; i < D_COMP_MAX; i++ ) {
for( k = 0; k < nb_subfr; k++ ) {
/* Check that we are within range of the array */
- silk_assert( target_ptr >= frame_8kHz );
- silk_assert( target_ptr + SF_LENGTH_8KHZ <= frame_8kHz + frame_length_8kHz );
+ celt_assert( target_ptr >= frame_8kHz );
+ celt_assert( target_ptr + SF_LENGTH_8KHZ <= frame_8kHz + frame_length_8kHz );
energy_target = silk_ADD32( silk_inner_prod_aligned( target_ptr, target_ptr, SF_LENGTH_8KHZ, arch ), 1 );
for( j = 0; j < length_d_comp; j++ ) {
*lagIndex = (opus_int16)( lag - MIN_LAG_8KHZ );
*contourIndex = (opus_int8)CBimax;
}
- silk_assert( *lagIndex >= 0 );
+ celt_assert( *lagIndex >= 0 );
/* return as voiced */
RESTORE_STACK;
return 0;
const opus_int8 *Lag_range_ptr, *Lag_CB_ptr;
SAVE_STACK;
- silk_assert( complexity >= SILK_PE_MIN_COMPLEX );
- silk_assert( complexity <= SILK_PE_MAX_COMPLEX );
+ celt_assert( complexity >= SILK_PE_MIN_COMPLEX );
+ celt_assert( complexity <= SILK_PE_MAX_COMPLEX );
if( nb_subfr == PE_MAX_NB_SUBFR ) {
Lag_range_ptr = &silk_Lag_range_stage3[ complexity ][ 0 ][ 0 ];
nb_cbk_search = silk_nb_cbk_searchs_stage3[ complexity ];
cbk_size = PE_NB_CBKS_STAGE3_MAX;
} else {
- silk_assert( nb_subfr == PE_MAX_NB_SUBFR >> 1);
+ celt_assert( nb_subfr == PE_MAX_NB_SUBFR >> 1);
Lag_range_ptr = &silk_Lag_range_stage3_10_ms[ 0 ][ 0 ];
Lag_CB_ptr = &silk_CB_lags_stage3_10_ms[ 0 ][ 0 ];
nb_cbk_search = PE_NB_CBKS_STAGE3_10MS;
/* Calculate the correlations for each subframe */
lag_low = matrix_ptr( Lag_range_ptr, k, 0, 2 );
lag_high = matrix_ptr( Lag_range_ptr, k, 1, 2 );
- silk_assert(lag_high-lag_low+1 <= SCRATCH_SIZE);
+ celt_assert(lag_high-lag_low+1 <= SCRATCH_SIZE);
celt_pitch_xcorr( target_ptr, target_ptr - start_lag - lag_high, xcorr32, sf_length, lag_high - lag_low + 1, arch );
for( j = lag_low; j <= lag_high; j++ ) {
silk_assert( lag_counter < SCRATCH_SIZE );
const opus_int8 *Lag_range_ptr, *Lag_CB_ptr;
SAVE_STACK;
- silk_assert( complexity >= SILK_PE_MIN_COMPLEX );
- silk_assert( complexity <= SILK_PE_MAX_COMPLEX );
+ celt_assert( complexity >= SILK_PE_MIN_COMPLEX );
+ celt_assert( complexity <= SILK_PE_MAX_COMPLEX );
if( nb_subfr == PE_MAX_NB_SUBFR ) {
Lag_range_ptr = &silk_Lag_range_stage3[ complexity ][ 0 ][ 0 ];
nb_cbk_search = silk_nb_cbk_searchs_stage3[ complexity ];
cbk_size = PE_NB_CBKS_STAGE3_MAX;
} else {
- silk_assert( nb_subfr == PE_MAX_NB_SUBFR >> 1);
+ celt_assert( nb_subfr == PE_MAX_NB_SUBFR >> 1);
Lag_range_ptr = &silk_Lag_range_stage3_10_ms[ 0 ][ 0 ];
Lag_CB_ptr = &silk_CB_lags_stage3_10_ms[ 0 ][ 0 ];
nb_cbk_search = PE_NB_CBKS_STAGE3_10MS;
const opus_int32 *pRow;
/* Safety checks */
- silk_assert( D >= 0 );
- silk_assert( D <= 16 );
- silk_assert( cQ > 0 );
- silk_assert( cQ < 16 );
+ celt_assert( D >= 0 );
+ celt_assert( D <= 16 );
+ celt_assert( cQ > 0 );
+ celt_assert( cQ < 16 );
lshifts = 16 - cQ;
Qxtra = lshifts;
/* Filter input to create the LPC residual for each frame half, and measure subframe energies */
ALLOC( LPC_res, ( MAX_NB_SUBFR >> 1 ) * offset, opus_int16 );
- silk_assert( ( nb_subfr >> 1 ) * ( MAX_NB_SUBFR >> 1 ) == nb_subfr );
+ celt_assert( ( nb_subfr >> 1 ) * ( MAX_NB_SUBFR >> 1 ) == nb_subfr );
for( i = 0; i < nb_subfr >> 1; i++ ) {
/* Calculate half frame LPC residual signal including preceding samples */
silk_LPC_analysis_filter( LPC_res, x_ptr, a_Q12[ i ], ( MAX_NB_SUBFR >> 1 ) * offset, LPC_order, arch );
opus_int32 C[ SILK_MAX_ORDER_LPC + 1 ][ 2 ];
opus_int32 Ctmp1_Q30, Ctmp2_Q30, rc_tmp_Q31;
- silk_assert( order >= 0 && order <= SILK_MAX_ORDER_LPC );
+ celt_assert( order >= 0 && order <= SILK_MAX_ORDER_LPC );
/* Check for invalid input */
if( c[ 0 ] <= 0 ) {
opus_int32 C[ SILK_MAX_ORDER_LPC + 1 ][ 2 ];
opus_int32 Ctmp1, Ctmp2, rc_tmp_Q15;
- silk_assert( order >= 0 && order <= SILK_MAX_ORDER_LPC );
+ celt_assert( order >= 0 && order <= SILK_MAX_ORDER_LPC );
/* Get number of leading zeros */
lz = silk_CLZ32( c[ 0 ] );
opus_int64 corr_QC[ MAX_SHAPE_LPC_ORDER + 1 ] = { 0 };
/* Order must be even */
- silk_assert( ( order & 1 ) == 0 );
+ celt_assert( ( order & 1 ) == 0 );
silk_assert( 2 * QS - QC >= 0 );
/* Loop over samples */
__m128i FIRST_3210, LAST_3210, ATMP_3210, TMP1_3210, TMP2_3210, T1_3210, T2_3210, PTR_3210, SUBFR_3210, X1_3210, X2_3210;
__m128i CONST1 = _mm_set1_epi32(1);
- silk_assert( subfr_length * nb_subfr <= MAX_FRAME_SIZE );
+ celt_assert( subfr_length * nb_subfr <= MAX_FRAME_SIZE );
/* Compute autocorrelations, added over subframes */
silk_sum_sqr_shift( &C0, &rshifts, x, nb_subfr * subfr_length );
const opus_int Order /* I LPC order */
)
{
- silk_assert( Order <= length );
+ celt_assert( Order <= length );
switch( Order ) {
case 6:
break;
default:
- silk_assert( 0 );
+ celt_assert( 0 );
break;
}
opus_int k;
silk_float freq, c, S0, S1;
- silk_assert( win_type == 1 || win_type == 2 );
+ celt_assert( win_type == 1 || win_type == 2 );
/* Length must be multiple of 4 */
- silk_assert( ( length & 3 ) == 0 );
+ celt_assert( ( length & 3 ) == 0 );
freq = PI / ( length + 1 );
double CAf[ SILK_MAX_ORDER_LPC + 1 ], CAb[ SILK_MAX_ORDER_LPC + 1 ];
double Af[ SILK_MAX_ORDER_LPC ];
- silk_assert( subfr_length * nb_subfr <= MAX_FRAME_SIZE );
+ celt_assert( subfr_length * nb_subfr <= MAX_FRAME_SIZE );
/* Compute autocorrelations, added over subframes */
C0 = silk_energy_FLP( x, nb_subfr * subfr_length );
);
void silk_encode_do_VAD_FLP(
- silk_encoder_state_FLP *psEnc /* I/O Encoder state FLP */
+ silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */
+ opus_int activity /* I Decision of Opus voice activity detector */
)
{
+ const opus_int activity_threshold = SILK_FIX_CONST( SPEECH_ACTIVITY_DTX_THRES, 8 );
+
/****************************/
/* Voice Activity Detection */
/****************************/
silk_VAD_GetSA_Q8( &psEnc->sCmn, psEnc->sCmn.inputBuf + 1, psEnc->sCmn.arch );
+ /* If Opus VAD is inactive and Silk VAD is active: lower Silk VAD to just under the threshold */
+ if( activity == VAD_NO_ACTIVITY && psEnc->sCmn.speech_activity_Q8 >= activity_threshold ) {
+ psEnc->sCmn.speech_activity_Q8 = activity_threshold - 1;
+ }
/**************************************************/
/* Convert speech activity into VAD and DTX flags */
/**************************************************/
- if( psEnc->sCmn.speech_activity_Q8 < SILK_FIX_CONST( SPEECH_ACTIVITY_DTX_THRES, 8 ) ) {
+ if( psEnc->sCmn.speech_activity_Q8 < activity_threshold ) {
psEnc->sCmn.indices.signalType = TYPE_NO_VOICE_ACTIVITY;
psEnc->sCmn.noSpeechCounter++;
- if( psEnc->sCmn.noSpeechCounter < NB_SPEECH_FRAMES_BEFORE_DTX ) {
+ if( psEnc->sCmn.noSpeechCounter <= NB_SPEECH_FRAMES_BEFORE_DTX ) {
psEnc->sCmn.inDTX = 0;
} else if( psEnc->sCmn.noSpeechCounter > MAX_CONSECUTIVE_DTX + NB_SPEECH_FRAMES_BEFORE_DTX ) {
psEnc->sCmn.noSpeechCounter = NB_SPEECH_FRAMES_BEFORE_DTX;
if( found_lower && ( gainsID == gainsID_lower || nBits > maxBits ) ) {
/* Restore output state from earlier iteration that did meet the bitrate budget */
silk_memcpy( psRangeEnc, &sRangeEnc_copy2, sizeof( ec_enc ) );
- silk_assert( sRangeEnc_copy2.offs <= 1275 );
+ celt_assert( sRangeEnc_copy2.offs <= 1275 );
silk_memcpy( psRangeEnc->buf, ec_buf_copy, sRangeEnc_copy2.offs );
silk_memcpy( &psEnc->sCmn.sNSQ, &sNSQ_copy2, sizeof( silk_nsq_state ) );
psEnc->sShape.LastGainIndex = LastGainIndex_copy2;
gainsID_lower = gainsID;
/* Copy part of the output state */
silk_memcpy( &sRangeEnc_copy2, psRangeEnc, sizeof( ec_enc ) );
- silk_assert( psRangeEnc->offs <= 1275 );
+ celt_assert( psRangeEnc->offs <= 1275 );
silk_memcpy( ec_buf_copy, psRangeEnc->buf, psRangeEnc->offs );
silk_memcpy( &sNSQ_copy2, &psEnc->sCmn.sNSQ, sizeof( silk_nsq_state ) );
LastGainIndex_copy2 = psEnc->sShape.LastGainIndex;
silk_A2NLSF_FLP( NLSF_Q15, a, psEncC->predictLPCOrder );
}
- silk_assert( psEncC->indices.NLSFInterpCoef_Q2 == 4 ||
+ celt_assert( psEncC->indices.NLSFInterpCoef_Q2 == 4 ||
( psEncC->useInterpolatedNLSFs && !psEncC->first_frame_after_reset && psEncC->nb_subfr == MAX_NB_SUBFR ) );
}
buf_len = psEnc->sCmn.la_pitch + psEnc->sCmn.frame_length + psEnc->sCmn.ltp_mem_length;
/* Safety check */
- silk_assert( buf_len >= psEnc->sCmn.pitch_LPC_win_length );
+ celt_assert( buf_len >= psEnc->sCmn.pitch_LPC_win_length );
x_buf = x - psEnc->sCmn.ltp_mem_length;
/**********/
/* VOICED */
/**********/
- silk_assert( psEnc->sCmn.ltp_mem_length - psEnc->sCmn.predictLPCOrder >= psEncCtrl->pitchL[ 0 ] + LTP_ORDER / 2 );
+ celt_assert( psEnc->sCmn.ltp_mem_length - psEnc->sCmn.predictLPCOrder >= psEncCtrl->pitchL[ 0 ] + LTP_ORDER / 2 );
/* LTP analysis */
silk_find_LTP_FLP( XXLTP, xXLTP, res_pitch, psEncCtrl->pitchL, psEnc->sCmn.subfr_length, psEnc->sCmn.nb_subfr );
/* Encoder main function */
void silk_encode_do_VAD_FLP(
- silk_encoder_state_FLP *psEnc /* I/O Encoder state FLP */
+ silk_encoder_state_FLP *psEnc, /* I/O Encoder state FLP */
+ opus_int activity /* I Decision of Opus voice activity detector */
);
/* Encoder main function */
const opus_int8 *Lag_CB_ptr;
/* Check for valid sampling frequency */
- silk_assert( Fs_kHz == 8 || Fs_kHz == 12 || Fs_kHz == 16 );
+ celt_assert( Fs_kHz == 8 || Fs_kHz == 12 || Fs_kHz == 16 );
/* Check for valid complexity setting */
- silk_assert( complexity >= SILK_PE_MIN_COMPLEX );
- silk_assert( complexity <= SILK_PE_MAX_COMPLEX );
+ celt_assert( complexity >= SILK_PE_MIN_COMPLEX );
+ celt_assert( complexity <= SILK_PE_MAX_COMPLEX );
silk_assert( search_thres1 >= 0.0f && search_thres1 <= 1.0f );
silk_assert( search_thres2 >= 0.0f && search_thres2 <= 1.0f );
silk_resampler_down2_3( filt_state, frame_8_FIX, frame_12_FIX, frame_length );
silk_short2float_array( frame_8kHz, frame_8_FIX, frame_length_8kHz );
} else {
- silk_assert( Fs_kHz == 8 );
+ celt_assert( Fs_kHz == 8 );
silk_float2short_array( frame_8_FIX, frame, frame_length_8kHz );
}
target_ptr = &frame_4kHz[ silk_LSHIFT( sf_length_4kHz, 2 ) ];
for( k = 0; k < nb_subfr >> 1; k++ ) {
/* Check that we are within range of the array */
- silk_assert( target_ptr >= frame_4kHz );
- silk_assert( target_ptr + sf_length_8kHz <= frame_4kHz + frame_length_4kHz );
+ celt_assert( target_ptr >= frame_4kHz );
+ celt_assert( target_ptr + sf_length_8kHz <= frame_4kHz + frame_length_4kHz );
basis_ptr = target_ptr - min_lag_4kHz;
/* Check that we are within range of the array */
- silk_assert( basis_ptr >= frame_4kHz );
- silk_assert( basis_ptr + sf_length_8kHz <= frame_4kHz + frame_length_4kHz );
+ celt_assert( basis_ptr >= frame_4kHz );
+ celt_assert( basis_ptr + sf_length_8kHz <= frame_4kHz + frame_length_4kHz );
celt_pitch_xcorr( target_ptr, target_ptr-max_lag_4kHz, xcorr, sf_length_8kHz, max_lag_4kHz - min_lag_4kHz + 1, arch );
/* Sort */
length_d_srch = 4 + 2 * complexity;
- silk_assert( 3 * length_d_srch <= PE_D_SRCH_LENGTH );
+ celt_assert( 3 * length_d_srch <= PE_D_SRCH_LENGTH );
silk_insertion_sort_decreasing_FLP( &C[ 0 ][ min_lag_4kHz ], d_srch, max_lag_4kHz - min_lag_4kHz + 1, length_d_srch );
/* Escape if correlation is very low already here */
break;
}
}
- silk_assert( length_d_srch > 0 );
+ celt_assert( length_d_srch > 0 );
for( i = min_lag_8kHz - 5; i < max_lag_8kHz + 5; i++ ) {
d_comp[ i ] = 0;
*lagIndex = (opus_int16)( lag - min_lag_8kHz );
*contourIndex = (opus_int8)CBimax;
}
- silk_assert( *lagIndex >= 0 );
+ celt_assert( *lagIndex >= 0 );
/* return as voiced */
return 0;
}
opus_val32 xcorr[ SCRATCH_SIZE ];
const opus_int8 *Lag_range_ptr, *Lag_CB_ptr;
- silk_assert( complexity >= SILK_PE_MIN_COMPLEX );
- silk_assert( complexity <= SILK_PE_MAX_COMPLEX );
+ celt_assert( complexity >= SILK_PE_MIN_COMPLEX );
+ celt_assert( complexity <= SILK_PE_MAX_COMPLEX );
if( nb_subfr == PE_MAX_NB_SUBFR ) {
Lag_range_ptr = &silk_Lag_range_stage3[ complexity ][ 0 ][ 0 ];
nb_cbk_search = silk_nb_cbk_searchs_stage3[ complexity ];
cbk_size = PE_NB_CBKS_STAGE3_MAX;
} else {
- silk_assert( nb_subfr == PE_MAX_NB_SUBFR >> 1);
+ celt_assert( nb_subfr == PE_MAX_NB_SUBFR >> 1);
Lag_range_ptr = &silk_Lag_range_stage3_10_ms[ 0 ][ 0 ];
Lag_CB_ptr = &silk_CB_lags_stage3_10_ms[ 0 ][ 0 ];
nb_cbk_search = PE_NB_CBKS_STAGE3_10MS;
silk_float scratch_mem[ SCRATCH_SIZE ];
const opus_int8 *Lag_range_ptr, *Lag_CB_ptr;
- silk_assert( complexity >= SILK_PE_MIN_COMPLEX );
- silk_assert( complexity <= SILK_PE_MAX_COMPLEX );
+ celt_assert( complexity >= SILK_PE_MIN_COMPLEX );
+ celt_assert( complexity <= SILK_PE_MAX_COMPLEX );
if( nb_subfr == PE_MAX_NB_SUBFR ) {
Lag_range_ptr = &silk_Lag_range_stage3[ complexity ][ 0 ][ 0 ];
nb_cbk_search = silk_nb_cbk_searchs_stage3[ complexity ];
cbk_size = PE_NB_CBKS_STAGE3_MAX;
} else {
- silk_assert( nb_subfr == PE_MAX_NB_SUBFR >> 1);
+ celt_assert( nb_subfr == PE_MAX_NB_SUBFR >> 1);
Lag_range_ptr = &silk_Lag_range_stage3_10_ms[ 0 ][ 0 ];
Lag_CB_ptr = &silk_CB_lags_stage3_10_ms[ 0 ][ 0 ];
nb_cbk_search = PE_NB_CBKS_STAGE3_10MS;
silk_float tmp, nrg = 0.0f, regularization;
/* Safety checks */
- silk_assert( D >= 0 );
+ celt_assert( D >= 0 );
regularization = REGULARIZATION_FACTOR * ( wXX[ 0 ] + wXX[ D * D - 1 ] );
for( k = 0; k < MAX_ITERATIONS_RESIDUAL_NRG; k++ ) {
double C[ SILK_MAX_ORDER_LPC + 1 ][ 2 ];
double Ctmp1, Ctmp2, rc_tmp;
- silk_assert( order >= 0 && order <= SILK_MAX_ORDER_LPC );
+ celt_assert( order >= 0 && order <= SILK_MAX_ORDER_LPC );
/* Copy correlations */
k = 0;
opus_int i, j;
/* Safety checks */
- silk_assert( K > 0 );
- silk_assert( L > 0 );
- silk_assert( L >= K );
+ celt_assert( K > 0 );
+ celt_assert( L > 0 );
+ celt_assert( L >= K );
/* Write start indices in index vector */
for( i = 0; i < K; i++ ) {
double C[ MAX_SHAPE_LPC_ORDER + 1 ] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };
/* Order must be even */
- silk_assert( ( order & 1 ) == 0 );
+ celt_assert( ( order & 1 ) == 0 );
/* Loop over samples */
for( n = 0; n < length; n++ ) {
{
opus_int i;
- silk_assert( ifact_Q2 >= 0 );
- silk_assert( ifact_Q2 <= 4 );
+ celt_assert( ifact_Q2 >= 0 );
+ celt_assert( ifact_Q2 <= 4 );
for( i = 0; i < d; i++ ) {
xi[ i ] = (opus_int16)silk_ADD_RSHIFT( x0[ i ], silk_SMULBB( x1[ i ] - x0[ i ], ifact_Q2 ), 2 );
silk_assert( psEncC->speech_activity_Q8 >= 0 );
silk_assert( psEncC->speech_activity_Q8 <= SILK_FIX_CONST( 1.0, 8 ) );
- silk_assert( psEncC->useInterpolatedNLSFs == 1 || psEncC->indices.NLSFInterpCoef_Q2 == ( 1 << 2 ) );
+ celt_assert( psEncC->useInterpolatedNLSFs == 1 || psEncC->indices.NLSFInterpCoef_Q2 == ( 1 << 2 ) );
/***********************/
/* Calculate mu values */
NLSF_mu_Q20 = silk_ADD_RSHIFT( NLSF_mu_Q20, NLSF_mu_Q20, 1 );
}
- silk_assert( NLSF_mu_Q20 > 0 );
+ celt_assert( NLSF_mu_Q20 > 0 );
silk_assert( NLSF_mu_Q20 <= SILK_FIX_CONST( 0.005, 20 ) );
/* Calculate NLSF weights */
} else {
/* Copy LPC coefficients for first half from second half */
- silk_assert( psEncC->predictLPCOrder <= MAX_LPC_ORDER );
+ celt_assert( psEncC->predictLPCOrder <= MAX_LPC_ORDER );
silk_memcpy( PredCoef_Q12[ 0 ], PredCoef_Q12[ 1 ], psEncC->predictLPCOrder * sizeof( opus_int16 ) );
}
}
if( forEnc ) {
if( ( Fs_Hz_in != 8000 && Fs_Hz_in != 12000 && Fs_Hz_in != 16000 && Fs_Hz_in != 24000 && Fs_Hz_in != 48000 ) ||
( Fs_Hz_out != 8000 && Fs_Hz_out != 12000 && Fs_Hz_out != 16000 ) ) {
- silk_assert( 0 );
+ celt_assert( 0 );
return -1;
}
S->inputDelay = delay_matrix_enc[ rateID( Fs_Hz_in ) ][ rateID( Fs_Hz_out ) ];
} else {
if( ( Fs_Hz_in != 8000 && Fs_Hz_in != 12000 && Fs_Hz_in != 16000 ) ||
( Fs_Hz_out != 8000 && Fs_Hz_out != 12000 && Fs_Hz_out != 16000 && Fs_Hz_out != 24000 && Fs_Hz_out != 48000 ) ) {
- silk_assert( 0 );
+ celt_assert( 0 );
return -1;
}
S->inputDelay = delay_matrix_dec[ rateID( Fs_Hz_in ) ][ rateID( Fs_Hz_out ) ];
S->Coefs = silk_Resampler_1_6_COEFS;
} else {
/* None available */
- silk_assert( 0 );
+ celt_assert( 0 );
return -1;
}
} else {
opus_int nSamples;
/* Need at least 1 ms of input data */
- silk_assert( inLen >= S->Fs_in_kHz );
+ celt_assert( inLen >= S->Fs_in_kHz );
/* Delay can't exceed the 1 ms of buffering */
- silk_assert( S->inputDelay <= S->Fs_in_kHz );
+ celt_assert( S->inputDelay <= S->Fs_in_kHz );
nSamples = S->Fs_in_kHz - S->inputDelay;
opus_int32 k, len2 = silk_RSHIFT32( inLen, 1 );
opus_int32 in32, out32, Y, X;
- silk_assert( silk_resampler_down2_0 > 0 );
- silk_assert( silk_resampler_down2_1 < 0 );
+ celt_assert( silk_resampler_down2_0 > 0 );
+ celt_assert( silk_resampler_down2_1 < 0 );
/* Internal variables and state are in Q10 format */
for( k = 0; k < len2; k++ ) {
}
break;
default:
- silk_assert( 0 );
+ celt_assert( 0 );
}
return out;
}
opus_int i, j;
/* Safety checks */
- silk_assert( K > 0 );
- silk_assert( L > 0 );
- silk_assert( L >= K );
+ celt_assert( K > 0 );
+ celt_assert( L > 0 );
+ celt_assert( L >= K );
/* Write start indices in index vector */
for( i = 0; i < K; i++ ) {
opus_int value;
/* Safety checks */
- silk_assert( K > 0 );
- silk_assert( L > 0 );
- silk_assert( L >= K );
+ celt_assert( K > 0 );
+ celt_assert( L > 0 );
+ celt_assert( L >= K );
/* Write start indices in index vector */
for( i = 0; i < K; i++ ) {
opus_int i, j;
/* Safety checks */
- silk_assert( L > 0 );
+ celt_assert( L > 0 );
/* Sort vector elements by value, increasing order */
for( i = 1; i < L; i++ ) {
if( total_rate_bps < 1 ) {
total_rate_bps = 1;
}
- min_mid_rate_bps = silk_SMLABB( 2000, fs_kHz, 900 );
+ min_mid_rate_bps = silk_SMLABB( 2000, fs_kHz, 600 );
silk_assert( min_mid_rate_bps < 32767 );
/* Default bitrate distribution: 8 parts for Mid and (5+3*frac) parts for Side. so: mid_rate = ( 8 / ( 13 + 3 * frac ) ) * total_ rate */
frac_3_Q16 = silk_MUL( 3, frac_Q16 );
/* Entropy coding */
n = 5 * ix[ 0 ][ 2 ] + ix[ 1 ][ 2 ];
- silk_assert( n < 25 );
+ celt_assert( n < 25 );
ec_enc_icdf( psRangeEnc, n, silk_stereo_pred_joint_iCDF, 8 );
for( n = 0; n < 2; n++ ) {
- silk_assert( ix[ n ][ 0 ] < 3 );
- silk_assert( ix[ n ][ 1 ] < STEREO_QUANT_SUB_STEPS );
+ celt_assert( ix[ n ][ 0 ] < 3 );
+ celt_assert( ix[ n ][ 1 ] < STEREO_QUANT_SUB_STEPS );
ec_enc_icdf( psRangeEnc, ix[ n ][ 0 ], silk_uniform3_iCDF, 8 );
ec_enc_icdf( psRangeEnc, ix[ n ][ 1 ], silk_uniform5_iCDF, 8 );
}
opus_int32 In_LP_State[ 2 ]; /* Low pass filter state */
opus_int32 transition_frame_no; /* Counter which is mapped to a cut-off frequency */
opus_int mode; /* Operating mode, <0: switch down, >0: switch up; 0: do nothing */
+ opus_int32 saved_fs_kHz; /* If non-zero, holds the last sampling rate before a bandwidth switching reset. */
} silk_LP_state;
/* Structure containing NLSF codebook */
extern const silk_NLSF_CB_struct silk_NLSF_CB_WB; /* 1040 */
extern const silk_NLSF_CB_struct silk_NLSF_CB_NB_MB; /* 728 */
-/* Piece-wise linear mapping from bitrate in kbps to coding quality in dB SNR */
-extern const opus_int32 silk_TargetRate_table_NB[ TARGET_RATE_TAB_SZ ]; /* 32 */
-extern const opus_int32 silk_TargetRate_table_MB[ TARGET_RATE_TAB_SZ ]; /* 32 */
-extern const opus_int32 silk_TargetRate_table_WB[ TARGET_RATE_TAB_SZ ]; /* 32 */
-extern const opus_int16 silk_SNR_table_Q1[ TARGET_RATE_TAB_SZ ]; /* 32 */
-
/* Quantization offsets */
extern const opus_int16 silk_Quantization_Offsets_Q10[ 2 ][ 2 ]; /* 8 */
{
#endif
-/* Piece-wise linear mapping from bitrate in kbps to coding quality in dB SNR */
-const opus_int32 silk_TargetRate_table_NB[ TARGET_RATE_TAB_SZ ] = {
- 0, 8000, 9400, 11500, 13500, 17500, 25000, MAX_TARGET_RATE_BPS
-};
-const opus_int32 silk_TargetRate_table_MB[ TARGET_RATE_TAB_SZ ] = {
- 0, 9000, 12000, 14500, 18500, 24500, 35500, MAX_TARGET_RATE_BPS
-};
-const opus_int32 silk_TargetRate_table_WB[ TARGET_RATE_TAB_SZ ] = {
- 0, 10500, 14000, 17000, 21500, 28500, 42000, MAX_TARGET_RATE_BPS
-};
-const opus_int16 silk_SNR_table_Q1[ TARGET_RATE_TAB_SZ ] = {
- 18, 29, 38, 40, 46, 52, 62, 84
-};
-
/* Tables for stereo predictor coding */
const opus_int16 silk_stereo_pred_quant_Q13[ STEREO_QUANT_TAB_SIZE ] = {
-13732, -10050, -8266, -7526, -6500, -5000, -2950, -820,
/* Rewhiten with new A coefs */
start_idx = psEncC->ltp_mem_length - lag - psEncC->predictLPCOrder - LTP_ORDER / 2;
- silk_assert( start_idx > 0 );
+ celt_assert( start_idx > 0 );
silk_LPC_analysis_filter( &sLTP[ start_idx ], &NSQ->xq[ start_idx + k * psEncC->subfr_length ],
A_Q12, psEncC->ltp_mem_length - start_idx, psEncC->predictLPCOrder, psEncC->arch );
__m128i b_Q12_0123, b_sr_Q12_0123;
SAVE_STACK;
- silk_assert( nStatesDelayedDecision > 0 );
+ celt_assert( nStatesDelayedDecision > 0 );
ALLOC( psSampleState, nStatesDelayedDecision, NSQ_sample_pair );
shp_lag_ptr = &NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - lag + HARM_SHAPE_FIR_TAPS / 2 ];
if( ( k & ( 3 - silk_LSHIFT( LSF_interpolation_flag, 1 ) ) ) == 0 ) {
/* Rewhiten with new A coefs */
start_idx = psEncC->ltp_mem_length - lag - psEncC->predictLPCOrder - LTP_ORDER / 2;
- silk_assert( start_idx > 0 );
+ celt_assert( start_idx > 0 );
silk_LPC_analysis_filter( &sLTP[ start_idx ], &NSQ->xq[ start_idx + k * psEncC->subfr_length ],
A_Q12, psEncC->ltp_mem_length - start_idx, psEncC->predictLPCOrder, psEncC->arch );
/* Safety checks */
silk_assert( VAD_N_BANDS == 4 );
- silk_assert( MAX_FRAME_LENGTH >= psEncC->frame_length );
- silk_assert( psEncC->frame_length <= 512 );
- silk_assert( psEncC->frame_length == 8 * silk_RSHIFT( psEncC->frame_length, 3 ) );
+ celt_assert( MAX_FRAME_LENGTH >= psEncC->frame_length );
+ celt_assert( psEncC->frame_length <= 512 );
+ celt_assert( psEncC->frame_length == 8 * silk_RSHIFT( psEncC->frame_length, 3 ) );
/***********************/
/* Filter and Decimate */
#ifndef DISABLE_FLOAT_API
+#define TRANSITION_PENALTY 10
+
static const float dct_table[128] = {
0.250000f, 0.250000f, 0.250000f, 0.250000f, 0.250000f, 0.250000f, 0.250000f, 0.250000f,
0.250000f, 0.250000f, 0.250000f, 0.250000f, 0.250000f, 0.250000f, 0.250000f, 0.250000f,
/* Clear non-reusable fields. */
char *start = (char*)&tonal->TONALITY_ANALYSIS_RESET_START;
OPUS_CLEAR(start, sizeof(TonalityAnalysisState) - (start - (char*)tonal));
- tonal->music_confidence = .9f;
- tonal->speech_confidence = .1f;
}
void tonality_get_info(TonalityAnalysisState *tonal, AnalysisInfo *info_out, int len)
{
int pos;
int curr_lookahead;
- float psum;
float tonality_max;
float tonality_avg;
int tonality_count;
int i;
+ int pos0;
+ float prob_avg;
+ float prob_count;
+ float prob_min, prob_max;
+ float vad_prob;
+ int mpos, vpos;
+ int bandwidth_span;
pos = tonal->read_pos;
curr_lookahead = tonal->write_pos-tonal->read_pos;
pos--;
if (pos<0)
pos = DETECT_SIZE-1;
+ pos0 = pos;
OPUS_COPY(info_out, &tonal->info[pos], 1);
tonality_max = tonality_avg = info_out->tonality;
tonality_count = 1;
+ /* Look at the neighbouring frames and pick largest bandwidth found (to be safe). */
+ bandwidth_span = 6;
/* If possible, look ahead for a tone to compensate for the delay in the tone detector. */
for (i=0;i<3;i++)
{
tonality_max = MAX32(tonality_max, tonal->info[pos].tonality);
tonality_avg += tonal->info[pos].tonality;
tonality_count++;
+ info_out->bandwidth = IMAX(info_out->bandwidth, tonal->info[pos].bandwidth);
+ bandwidth_span--;
+ }
+ pos = pos0;
+ /* Look back in time to see if any has a wider bandwidth than the current frame. */
+ for (i=0;i<bandwidth_span;i++)
+ {
+ pos--;
+ if (pos < 0)
+ pos = DETECT_SIZE-1;
+ if (pos == tonal->write_pos)
+ break;
+ info_out->bandwidth = IMAX(info_out->bandwidth, tonal->info[pos].bandwidth);
}
info_out->tonality = MAX32(tonality_avg/tonality_count, tonality_max-.2f);
+
+ mpos = vpos = pos0;
+ /* If we have enough look-ahead, compensate for the ~5-frame delay in the music prob and
+ ~1 frame delay in the VAD prob. */
+ if (curr_lookahead > 15)
+ {
+ mpos += 5;
+ if (mpos>=DETECT_SIZE)
+ mpos -= DETECT_SIZE;
+ vpos += 1;
+ if (vpos>=DETECT_SIZE)
+ vpos -= DETECT_SIZE;
+ }
+
+ /* The following calculations attempt to minimize a "badness function"
+ for the transition. When switching from speech to music, the badness
+ of switching at frame k is
+ b_k = S*v_k + \sum_{i=0}^{k-1} v_i*(p_i - T)
+ where
+ v_i is the activity probability (VAD) at frame i,
+ p_i is the music probability at frame i
+ T is the probability threshold for switching
+ S is the penalty for switching during active audio rather than silence
+ the current frame has index i=0
+
+ Rather than apply badness to directly decide when to switch, what we compute
+ instead is the threshold for which the optimal switching point is now. When
+ considering whether to switch now (frame 0) or at frame k, we have:
+ S*v_0 = S*v_k + \sum_{i=0}^{k-1} v_i*(p_i - T)
+ which gives us:
+ T = ( \sum_{i=0}^{k-1} v_i*p_i + S*(v_k-v_0) ) / ( \sum_{i=0}^{k-1} v_i )
+ We take the min threshold across all positive values of k (up to the maximum
+ amount of lookahead we have) to give us the threshold for which the current
+ frame is the optimal switch point.
+
+ The last step is that we need to consider whether we want to switch at all.
+ For that we use the average of the music probability over the entire window.
+ If the threshold is higher than that average we're not going to
+ switch, so we compute a min with the average as well. The result of all these
+ min operations is music_prob_min, which gives the threshold for switching to music
+ if we're currently encoding for speech.
+
+ We do the exact opposite to compute music_prob_max which is used for switching
+ from music to speech.
+ */
+ prob_min = 1.f;
+ prob_max = 0.f;
+ vad_prob = tonal->info[vpos].activity_probability;
+ prob_count = MAX16(.1f, vad_prob);
+ prob_avg = MAX16(.1f, vad_prob)*tonal->info[mpos].music_prob;
+ while (1)
+ {
+ float pos_vad;
+ mpos++;
+ if (mpos==DETECT_SIZE)
+ mpos = 0;
+ if (mpos == tonal->write_pos)
+ break;
+ vpos++;
+ if (vpos==DETECT_SIZE)
+ vpos = 0;
+ if (vpos == tonal->write_pos)
+ break;
+ pos_vad = tonal->info[vpos].activity_probability;
+ prob_min = MIN16((prob_avg - TRANSITION_PENALTY*(vad_prob - pos_vad))/prob_count, prob_min);
+ prob_max = MAX16((prob_avg + TRANSITION_PENALTY*(vad_prob - pos_vad))/prob_count, prob_max);
+ prob_count += MAX16(.1f, pos_vad);
+ prob_avg += MAX16(.1f, pos_vad)*tonal->info[mpos].music_prob;
+ }
+ info_out->music_prob = prob_avg/prob_count;
+ prob_min = MIN16(prob_avg/prob_count, prob_min);
+ prob_max = MAX16(prob_avg/prob_count, prob_max);
+ prob_min = MAX16(prob_min, 0.f);
+ prob_max = MIN16(prob_max, 1.f);
+
+ /* If we don't have enough look-ahead, do our best to make a decent decision. */
+ if (curr_lookahead < 10)
+ {
+ float pmin, pmax;
+ pmin = prob_min;
+ pmax = prob_max;
+ pos = pos0;
+ /* Look for min/max in the past. */
+ for (i=0;i<IMIN(tonal->count-1, 15);i++)
+ {
+ pos--;
+ if (pos < 0)
+ pos = DETECT_SIZE-1;
+ pmin = MIN16(pmin, tonal->info[pos].music_prob);
+ pmax = MAX16(pmax, tonal->info[pos].music_prob);
+ }
+ /* Bias against switching on active audio. */
+ pmin = MAX16(0.f, pmin - .1f*vad_prob);
+ pmax = MIN16(1.f, pmax + .1f*vad_prob);
+ prob_min += (1.f-.1f*curr_lookahead)*(pmin - prob_min);
+ prob_max += (1.f-.1f*curr_lookahead)*(pmax - prob_max);
+ }
+ info_out->music_prob_min = prob_min;
+ info_out->music_prob_max = prob_max;
+
+ /* printf("%f %f %f %f %f\n", prob_min, prob_max, prob_avg/prob_count, vad_prob, info_out->music_prob); */
tonal->read_subframe += len/(tonal->Fs/400);
while (tonal->read_subframe>=8)
{
}
if (tonal->read_pos>=DETECT_SIZE)
tonal->read_pos-=DETECT_SIZE;
-
- /* The -1 is to compensate for the delay in the features themselves. */
- curr_lookahead = IMAX(curr_lookahead-1, 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 %f %f\n", psum, info_out->music_prob, info_out->vad_prob, info_out->activity_probability, info_out->tonality);*/
-
- info_out->music_prob = psum;
}
static const float std_feature_bias[9] = {
float alpha, alphaE, alphaE2;
float frame_loudness;
float bandwidth_mask;
+ int is_masked[NB_TBANDS+1];
int bandwidth=0;
float maxE = 0;
float noise_floor;
float band_log2[NB_TBANDS+1];
float leakage_from[NB_TBANDS+1];
float leakage_to[NB_TBANDS+1];
+ float layer_out[MAX_NEURONS];
+ float below_max_pitch;
+ float above_max_pitch;
SAVE_STACK;
alpha = 1.f/IMIN(10, 1+tonal->count);
alphaE = 1.f/IMIN(25, 1+tonal->count);
- alphaE2 = 1.f/IMIN(500, 1+tonal->count);
+ /* Noise floor related decay for bandwidth detection: -2.2 dB/second */
+ alphaE2 = 1.f/IMIN(100, 1+tonal->count);
+ if (tonal->count <= 1) alphaE2 = 1;
if (tonal->Fs == 48000)
{
offset = 3*offset/2;
}
- if (tonal->count<4) {
- if (tonal->application == OPUS_APPLICATION_VOIP)
- tonal->music_prob = .1f;
- else
- tonal->music_prob = .625f;
- }
kfft = celt_mode->mdct.kfft[0];
if (tonal->count==0)
tonal->mem_fill = 240;
maxE = 0;
noise_floor = 5.7e-4f/(1<<(IMAX(0,lsb_depth-8)));
noise_floor *= noise_floor;
+ below_max_pitch=0;
+ above_max_pitch=0;
for (b=0;b<NB_TBANDS;b++)
{
float E=0;
+ float Em;
int band_start, band_end;
/* Keep a margin of 300 Hz for aliasing */
band_start = tbands[b];
}
E = SCALE_ENER(E);
maxE = MAX32(maxE, E);
+ if (band_start < 64)
+ {
+ below_max_pitch += E;
+ } else {
+ above_max_pitch += E;
+ }
tonal->meanE[b] = MAX32((1-alphaE2)*tonal->meanE[b], E);
- 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);
+ Em = MAX32(E, tonal->meanE[b]);
/* 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
+ 1) less than 90 dB below the peak band (maximal masking possible considering
both the ATH and the loudness-dependent slope of the spreading function)
- 3) above the PCM quantization noise floor
+ 2) above the PCM quantization noise floor
We use b+1 because the first CELT band isn't included in tbands[]
*/
- if (E>.1*bandwidth_mask && E*1e9f > maxE && E > noise_floor*(band_end-band_start))
+ if (E*1e9f > maxE && (Em > 3*noise_floor*(band_end-band_start) || E > noise_floor*(band_end-band_start)))
bandwidth = b+1;
+ /* Check if the band is masked (see below). */
+ is_masked[b] = E < (tonal->prev_bandwidth >= b+1 ? .01f : .05f)*bandwidth_mask;
+ /* Use a simple follower with 13 dB/Bark slope for spreading function. */
+ bandwidth_mask = MAX32(.05f*bandwidth_mask, E);
}
/* Special case for the last two bands, for which we don't have spectrum but only
- the energy above 12 kHz. */
+ the energy above 12 kHz. The difficulty here is that the high-pass we use
+ leaks some LF energy, so we need to increase the threshold without accidentally cutting
+ off the band. */
if (tonal->Fs == 48000) {
- float ratio;
- float E = hp_ener*(1.f/(240*240));
- ratio = tonal->prev_bandwidth==20 ? 0.03f : 0.07f;
+ float noise_ratio;
+ float Em;
+ float E = hp_ener*(1.f/(60*60));
+ noise_ratio = tonal->prev_bandwidth==20 ? 10.f : 30.f;
+
#ifdef FIXED_POINT
/* silk_resampler_down2_hp() shifted right by an extra 8 bits. */
E *= 256.f*(1.f/Q15ONE)*(1.f/Q15ONE);
#endif
- maxE = MAX32(maxE, E);
+ above_max_pitch += 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);
- if (E>ratio*bandwidth_mask && E*1e9f > maxE && E > noise_floor*160)
- bandwidth = 20;
- /* This detector is unreliable, so if the bandwidth is close to SWB, assume it's FB. */
- if (bandwidth >= 17)
+ Em = MAX32(E, tonal->meanE[b]);
+ if (Em > 3*noise_ratio*noise_floor*160 || E > noise_ratio*noise_floor*160)
bandwidth = 20;
+ /* Check if the band is masked (see below). */
+ is_masked[b] = E < (tonal->prev_bandwidth == 20 ? .01f : .05f)*bandwidth_mask;
}
+ if (above_max_pitch > below_max_pitch)
+ info->max_pitch_ratio = below_max_pitch/above_max_pitch;
+ else
+ info->max_pitch_ratio = 1;
+ /* In some cases, resampling aliasing can create a small amount of energy in the first band
+ being cut. So if the last band is masked, we don't include it. */
+ if (bandwidth == 20 && is_masked[NB_TBANDS])
+ bandwidth-=2;
+ else if (bandwidth > 0 && bandwidth <= NB_TBANDS && is_masked[bandwidth-1])
+ bandwidth--;
if (tonal->count<=2)
bandwidth = 20;
frame_loudness = 20*(float)log10(frame_loudness);
features[23] = info->tonality_slope + 0.069216f;
features[24] = tonal->lowECount - 0.067930f;
- 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;
- frame_probs[1] *= frame_probs[1];
+ compute_dense(&layer0, layer_out, features);
+ compute_gru(&layer1, tonal->rnn_state, layer_out);
+ compute_dense(&layer2, frame_probs, tonal->rnn_state);
/* Probability of speech or music vs noise */
info->activity_probability = frame_probs[1];
+ info->music_prob = frame_probs[0];
- /*printf("%f %f\n", 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;
-
- /* More silence transitions for speech than for music. */
- tau = .001f*tonal->music_prob + .01f*(1-tonal->music_prob);
- p = MAX16(.05f,MIN16(.95f,frame_probs[1]));
- q = MAX16(.05f,MIN16(.95f,tonal->vad_prob));
- beta = .02f+.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->vad_prob)*(1-tau) + tonal->vad_prob *tau;
- p1 = tonal->vad_prob *(1-tau) + (1-tonal->vad_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[1], beta);
- p1 *= (float)pow(frame_probs[1], beta);
- /* Normalise the probabilities to get the Marokv probability of music. */
- tonal->vad_prob = p1/(p0+p1);
- info->vad_prob = tonal->vad_prob;
- /* Consider that silence has a 50-50 probability of being speech or music. */
- frame_probs[0] = tonal->vad_prob*frame_probs[0] + (1-tonal->vad_prob)*.5f;
-
- /* One transition every 3 minutes of active audio */
- tau = .0001f;
- /* 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 = .02f+.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;
-
- /*printf("%f %f %f %f\n", frame_probs[0], frame_probs[1], tonal->music_prob, tonal->vad_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)
- {
- if (tonal->application == OPUS_APPLICATION_VOIP)
- tonal->pmusic[0] = .1f;
- else
- tonal->pmusic[0] = .625f;
- tonal->pspeech[0] = 1-tonal->pmusic[0];
- }
- /* 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);
- }
- }
- }
- tonal->last_music = tonal->music_prob>.5f;
+ /*printf("%f %f %f\n", frame_probs[0], frame_probs[1], info->music_prob);*/
#ifdef MLP_TRAINING
for (i=0;i<25;i++)
printf("%f ", features[i]);
#include "celt.h"
#include "opus_private.h"
+#include "mlp.h"
#define NB_FRAMES 8
#define NB_TBANDS 18
float mem[32];
float cmean[8];
float std[9];
- float music_prob;
- float vad_prob;
float Etracker;
float lowECount;
int E_count;
- int last_music;
int count;
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;
float hp_ener_accum;
+ float rnn_state[MAX_NEURONS];
opus_val32 downmix_state[3];
AnalysisInfo info[DETECT_SIZE];
} TonalityAnalysisState;
--- /dev/null
+/* Copyright (c) 2017 Google Inc.
+ Written by Andrew Allen */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "arch.h"
+#include "float_cast.h"
+#include "opus_private.h"
+#include "opus_defines.h"
+#include "mapping_matrix.h"
+
+#define MATRIX_INDEX(nb_rows, row, col) (nb_rows * col + row)
+
+opus_int32 mapping_matrix_get_size(int rows, int cols)
+{
+ opus_int32 size;
+
+ /* Mapping Matrix must only support up to 255 channels in or out.
+ * Additionally, the total cell count must be <= 65004 octets in order
+ * for the matrix to be stored in an OGG header.
+ */
+ if (rows > 255 || cols > 255)
+ return 0;
+ size = rows * (opus_int32)cols * sizeof(opus_int16);
+ if (size > 65004)
+ return 0;
+
+ return align(sizeof(MappingMatrix)) + align(size);
+}
+
+opus_int16 *mapping_matrix_get_data(const MappingMatrix *matrix)
+{
+ /* void* cast avoids clang -Wcast-align warning */
+ return (opus_int16*)(void*)((char*)matrix + align(sizeof(MappingMatrix)));
+}
+
+void mapping_matrix_init(MappingMatrix * const matrix,
+ int rows, int cols, int gain, const opus_int16 *data, opus_int32 data_size)
+{
+ int i;
+ opus_int16 *ptr;
+
+#if !defined(ENABLE_ASSERTIONS)
+ (void)data_size;
+#endif
+ celt_assert(align(data_size) == align(rows * cols * sizeof(opus_int16)));
+
+ matrix->rows = rows;
+ matrix->cols = cols;
+ matrix->gain = gain;
+ ptr = mapping_matrix_get_data(matrix);
+ for (i = 0; i < rows * cols; i++)
+ {
+ ptr[i] = data[i];
+ }
+}
+
+#ifndef DISABLE_FLOAT_API
+void mapping_matrix_multiply_channel_in_float(
+ const MappingMatrix *matrix,
+ const float *input,
+ int input_rows,
+ opus_val16 *output,
+ int output_row,
+ int output_rows,
+ int frame_size)
+{
+ /* Matrix data is ordered col-wise. */
+ opus_int16* matrix_data;
+ int i, col;
+
+ celt_assert(input_rows <= matrix->cols && output_rows <= matrix->rows);
+
+ matrix_data = mapping_matrix_get_data(matrix);
+
+ for (i = 0; i < frame_size; i++)
+ {
+ float tmp = 0;
+ for (col = 0; col < input_rows; col++)
+ {
+ tmp +=
+ matrix_data[MATRIX_INDEX(matrix->rows, output_row, col)] *
+ input[MATRIX_INDEX(input_rows, col, i)];
+ }
+#if defined(FIXED_POINT)
+ output[output_rows * i] = FLOAT2INT16((1/32768.f)*tmp);
+#else
+ output[output_rows * i] = (1/32768.f)*tmp;
+#endif
+ }
+}
+
+void mapping_matrix_multiply_channel_out_float(
+ const MappingMatrix *matrix,
+ const opus_val16 *input,
+ int input_row,
+ int input_rows,
+ float *output,
+ int output_rows,
+ int frame_size
+)
+{
+ /* Matrix data is ordered col-wise. */
+ opus_int16* matrix_data;
+ int i, row;
+ float input_sample;
+
+ celt_assert(input_rows <= matrix->cols && output_rows <= matrix->rows);
+
+ matrix_data = mapping_matrix_get_data(matrix);
+
+ for (i = 0; i < frame_size; i++)
+ {
+#if defined(FIXED_POINT)
+ input_sample = (1/32768.f)*input[input_rows * i];
+#else
+ input_sample = input[input_rows * i];
+#endif
+ for (row = 0; row < output_rows; row++)
+ {
+ float tmp =
+ (1/32768.f)*matrix_data[MATRIX_INDEX(matrix->rows, row, input_row)] *
+ input_sample;
+ output[MATRIX_INDEX(output_rows, row, i)] += tmp;
+ }
+ }
+}
+#endif /* DISABLE_FLOAT_API */
+
+void mapping_matrix_multiply_channel_in_short(
+ const MappingMatrix *matrix,
+ const opus_int16 *input,
+ int input_rows,
+ opus_val16 *output,
+ int output_row,
+ int output_rows,
+ int frame_size)
+{
+ /* Matrix data is ordered col-wise. */
+ opus_int16* matrix_data;
+ int i, col;
+
+ celt_assert(input_rows <= matrix->cols && output_rows <= matrix->rows);
+
+ matrix_data = mapping_matrix_get_data(matrix);
+
+ for (i = 0; i < frame_size; i++)
+ {
+ opus_val32 tmp = 0;
+ for (col = 0; col < input_rows; col++)
+ {
+#if defined(FIXED_POINT)
+ tmp +=
+ ((opus_int32)matrix_data[MATRIX_INDEX(matrix->rows, output_row, col)] *
+ (opus_int32)input[MATRIX_INDEX(input_rows, col, i)]) >> 8;
+#else
+ tmp +=
+ matrix_data[MATRIX_INDEX(matrix->rows, output_row, col)] *
+ input[MATRIX_INDEX(input_rows, col, i)];
+#endif
+ }
+#if defined(FIXED_POINT)
+ output[output_rows * i] = (opus_int16)((tmp + 64) >> 7);
+#else
+ output[output_rows * i] = (1/(32768.f*32768.f))*tmp;
+#endif
+ }
+}
+
+void mapping_matrix_multiply_channel_out_short(
+ const MappingMatrix *matrix,
+ const opus_val16 *input,
+ int input_row,
+ int input_rows,
+ opus_int16 *output,
+ int output_rows,
+ int frame_size)
+{
+ /* Matrix data is ordered col-wise. */
+ opus_int16* matrix_data;
+ int i, row;
+ opus_int32 input_sample;
+
+ celt_assert(input_rows <= matrix->cols && output_rows <= matrix->rows);
+
+ matrix_data = mapping_matrix_get_data(matrix);
+
+ for (i = 0; i < frame_size; i++)
+ {
+#if defined(FIXED_POINT)
+ input_sample = (opus_int32)input[input_rows * i];
+#else
+ input_sample = (opus_int32)FLOAT2INT16(input[input_rows * i]);
+#endif
+ for (row = 0; row < output_rows; row++)
+ {
+ opus_int32 tmp =
+ (opus_int32)matrix_data[MATRIX_INDEX(matrix->rows, row, input_row)] *
+ input_sample;
+ output[MATRIX_INDEX(output_rows, row, i)] += (tmp + 16384) >> 15;
+ }
+ }
+}
+
+const MappingMatrix mapping_matrix_foa_mixing = { 6, 6, 0 };
+const opus_int16 mapping_matrix_foa_mixing_data[36] = {
+ 16384, 0, -16384, 23170, 0, 0, 16384, 23170,
+ 16384, 0, 0, 0, 16384, 0, -16384, -23170,
+ 0, 0, 16384, -23170, 16384, 0, 0, 0,
+ 0, 0, 0, 0, 32767, 0, 0, 0,
+ 0, 0, 0, 32767
+};
+
+const MappingMatrix mapping_matrix_soa_mixing = { 11, 11, 0 };
+const opus_int16 mapping_matrix_soa_mixing_data[121] = {
+ 10923, 7723, 13377, -13377, 11585, 9459, 7723, -16384,
+ -6689, 0, 0, 10923, 7723, 13377, 13377, -11585,
+ 9459, 7723, 16384, -6689, 0, 0, 10923, -15447,
+ 13377, 0, 0, -18919, 7723, 0, 13377, 0,
+ 0, 10923, 7723, -13377, -13377, 11585, -9459, 7723,
+ 16384, -6689, 0, 0, 10923, -7723, 0, 13377,
+ -16384, 0, -15447, 0, 9459, 0, 0, 10923,
+ -7723, 0, -13377, 16384, 0, -15447, 0, 9459,
+ 0, 0, 10923, 15447, 0, 0, 0, 0,
+ -15447, 0, -18919, 0, 0, 10923, 7723, -13377,
+ 13377, -11585, -9459, 7723, -16384, -6689, 0, 0,
+ 10923, -15447, -13377, 0, 0, 18919, 7723, 0,
+ 13377, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 32767, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 32767
+};
+
+const MappingMatrix mapping_matrix_toa_mixing = { 18, 18, 0 };
+const opus_int16 mapping_matrix_toa_mixing_data[324] = {
+ 8208, 0, -881, 14369, 0, 0, -8192, -4163,
+ 13218, 0, 0, 0, 11095, -8836, -6218, 14833,
+ 0, 0, 8208, -10161, 881, 10161, -13218, -2944,
+ -8192, 2944, 0, -10488, -6218, 6248, -11095, -6248,
+ 0, -10488, 0, 0, 8208, 10161, 881, -10161,
+ -13218, 2944, -8192, -2944, 0, 10488, -6218, -6248,
+ -11095, 6248, 0, 10488, 0, 0, 8176, 5566,
+ -11552, 5566, 9681, -11205, 8192, -11205, 0, 4920,
+ -15158, 9756, -3334, 9756, 0, -4920, 0, 0,
+ 8176, 7871, 11552, 0, 0, 15846, 8192, 0,
+ -9681, -6958, 0, 13797, 3334, 0, -15158, 0,
+ 0, 0, 8176, 0, 11552, 7871, 0, 0,
+ 8192, 15846, 9681, 0, 0, 0, 3334, 13797,
+ 15158, 6958, 0, 0, 8176, 5566, -11552, -5566,
+ -9681, -11205, 8192, 11205, 0, 4920, 15158, 9756,
+ -3334, -9756, 0, 4920, 0, 0, 8208, 14369,
+ -881, 0, 0, -4163, -8192, 0, -13218, -14833,
+ 0, -8836, 11095, 0, 6218, 0, 0, 0,
+ 8208, 10161, 881, 10161, 13218, 2944, -8192, 2944,
+ 0, 10488, 6218, -6248, -11095, -6248, 0, -10488,
+ 0, 0, 8208, -14369, -881, 0, 0, 4163,
+ -8192, 0, -13218, 14833, 0, 8836, 11095, 0,
+ 6218, 0, 0, 0, 8208, 0, -881, -14369,
+ 0, 0, -8192, 4163, 13218, 0, 0, 0,
+ 11095, 8836, -6218, -14833, 0, 0, 8176, -5566,
+ -11552, 5566, -9681, 11205, 8192, -11205, 0, -4920,
+ 15158, -9756, -3334, 9756, 0, -4920, 0, 0,
+ 8176, 0, 11552, -7871, 0, 0, 8192, -15846,
+ 9681, 0, 0, 0, 3334, -13797, 15158, -6958,
+ 0, 0, 8176, -7871, 11552, 0, 0, -15846,
+ 8192, 0, -9681, 6958, 0, -13797, 3334, 0,
+ -15158, 0, 0, 0, 8176, -5566, -11552, -5566,
+ 9681, 11205, 8192, 11205, 0, -4920, -15158, -9756,
+ -3334, -9756, 0, 4920, 0, 0, 8208, -10161,
+ 881, -10161, 13218, -2944, -8192, -2944, 0, -10488,
+ 6218, 6248, -11095, 6248, 0, 10488, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 32767, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 32767
+};
+
+const MappingMatrix mapping_matrix_foa_demixing = { 6, 6, 0 };
+const opus_int16 mapping_matrix_foa_demixing_data[36] = {
+ 16384, 16384, 16384, 16384, 0, 0, 0, 23170,
+ 0, -23170, 0, 0, -16384, 16384, -16384, 16384,
+ 0, 0, 23170, 0, -23170, 0, 0, 0,
+ 0, 0, 0, 0, 32767, 0, 0, 0,
+ 0, 0, 0, 32767
+};
+
+const MappingMatrix mapping_matrix_soa_demixing = { 11, 11, 3050 };
+const opus_int16 mapping_matrix_soa_demixing_data[121] = {
+ 2771, 2771, 2771, 2771, 2771, 2771, 2771, 2771,
+ 2771, 0, 0, 10033, 10033, -20066, 10033, 14189,
+ 14189, -28378, 10033, -20066, 0, 0, 3393, 3393,
+ 3393, -3393, 0, 0, 0, -3393, -3393, 0,
+ 0, -17378, 17378, 0, -17378, -24576, 24576, 0,
+ 17378, 0, 0, 0, -14189, 14189, 0, -14189,
+ -28378, 28378, 0, 14189, 0, 0, 0, 2399,
+ 2399, -4799, -2399, 0, 0, 0, -2399, 4799,
+ 0, 0, 1959, 1959, 1959, 1959, -3918, -3918,
+ -3918, 1959, 1959, 0, 0, -4156, 4156, 0,
+ 4156, 0, 0, 0, -4156, 0, 0, 0,
+ 8192, 8192, -16384, 8192, 16384, 16384, -32768, 8192,
+ -16384, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 8312, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 8312
+};
+
+const MappingMatrix mapping_matrix_toa_demixing = { 18, 18, 0 };
+const opus_int16 mapping_matrix_toa_demixing_data[324] = {
+ 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192,
+ 8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192,
+ 0, 0, 0, -9779, 9779, 6263, 8857, 0,
+ 6263, 13829, 9779, -13829, 0, -6263, 0, -8857,
+ -6263, -9779, 0, 0, -3413, 3413, 3413, -11359,
+ 11359, 11359, -11359, -3413, 3413, -3413, -3413, -11359,
+ 11359, 11359, -11359, 3413, 0, 0, 13829, 9779,
+ -9779, 6263, 0, 8857, -6263, 0, 9779, 0,
+ -13829, 6263, -8857, 0, -6263, -9779, 0, 0,
+ 0, -15617, -15617, 6406, 0, 0, -6406, 0,
+ 15617, 0, 0, -6406, 0, 0, 6406, 15617,
+ 0, 0, 0, -5003, 5003, -10664, 15081, 0,
+ -10664, -7075, 5003, 7075, 0, 10664, 0, -15081,
+ 10664, -5003, 0, 0, -8176, -8176, -8176, 8208,
+ 8208, 8208, 8208, -8176, -8176, -8176, -8176, 8208,
+ 8208, 8208, 8208, -8176, 0, 0, -7075, 5003,
+ -5003, -10664, 0, 15081, 10664, 0, 5003, 0,
+ 7075, -10664, -15081, 0, 10664, -5003, 0, 0,
+ 15617, 0, 0, 0, -6406, 6406, 0, -15617,
+ 0, -15617, 15617, 0, 6406, -6406, 0, 0,
+ 0, 0, 0, -11393, 11393, 2993, -4233, 0,
+ 2993, -16112, 11393, 16112, 0, -2993, 0, 4233,
+ -2993, -11393, 0, 0, 0, -9974, -9974, -13617,
+ 0, 0, 13617, 0, 9974, 0, 0, 13617,
+ 0, 0, -13617, 9974, 0, 0, 0, 5579,
+ -5579, 10185, 14403, 0, 10185, -7890, -5579, 7890,
+ 0, -10185, 0, -14403, -10185, 5579, 0, 0,
+ 11826, -11826, -11826, -901, 901, 901, -901, 11826,
+ -11826, 11826, 11826, -901, 901, 901, -901, -11826,
+ 0, 0, -7890, -5579, 5579, 10185, 0, 14403,
+ -10185, 0, -5579, 0, 7890, 10185, -14403, 0,
+ -10185, 5579, 0, 0, -9974, 0, 0, 0,
+ -13617, 13617, 0, 9974, 0, 9974, -9974, 0,
+ 13617, -13617, 0, 0, 0, 0, 16112, -11393,
+ 11393, -2993, 0, 4233, 2993, 0, -11393, 0,
+ -16112, -2993, -4233, 0, 2993, 11393, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 32767, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 32767
+};
+
--- /dev/null
+/* Copyright (c) 2017 Google Inc.
+ Written by Andrew Allen */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/**
+ * @file mapping_matrix.h
+ * @brief Opus reference implementation mapping matrix API
+ */
+
+#ifndef MAPPING_MATRIX_H
+#define MAPPING_MATRIX_H
+
+#include "opus_types.h"
+#include "opus_projection.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct MappingMatrix
+{
+ int rows; /* number of channels outputted from matrix. */
+ int cols; /* number of channels inputted to matrix. */
+ int gain; /* in dB. S7.8-format. */
+ /* Matrix cell data goes here using col-wise ordering. */
+} MappingMatrix;
+
+opus_int32 mapping_matrix_get_size(int rows, int cols);
+
+opus_int16 *mapping_matrix_get_data(const MappingMatrix *matrix);
+
+void mapping_matrix_init(
+ MappingMatrix * const st,
+ int rows,
+ int cols,
+ int gain,
+ const opus_int16 *data,
+ opus_int32 data_size
+);
+
+#ifndef DISABLE_FLOAT_API
+void mapping_matrix_multiply_channel_in_float(
+ const MappingMatrix *matrix,
+ const float *input,
+ int input_rows,
+ opus_val16 *output,
+ int output_row,
+ int output_rows,
+ int frame_size
+);
+
+void mapping_matrix_multiply_channel_out_float(
+ const MappingMatrix *matrix,
+ const opus_val16 *input,
+ int input_row,
+ int input_rows,
+ float *output,
+ int output_rows,
+ int frame_size
+);
+#endif /* DISABLE_FLOAT_API */
+
+void mapping_matrix_multiply_channel_in_short(
+ const MappingMatrix *matrix,
+ const opus_int16 *input,
+ int input_rows,
+ opus_val16 *output,
+ int output_row,
+ int output_rows,
+ int frame_size
+);
+
+void mapping_matrix_multiply_channel_out_short(
+ const MappingMatrix *matrix,
+ const opus_val16 *input,
+ int input_row,
+ int input_rows,
+ opus_int16 *output,
+ int output_rows,
+ int frame_size
+);
+
+/* Pre-computed mixing and demixing matrices for 1st to 3rd-order ambisonics.
+ * foa: first-order ambisonics
+ * soa: second-order ambisonics
+ * toa: third-order ambisonics
+ */
+extern const MappingMatrix mapping_matrix_foa_mixing;
+extern const opus_int16 mapping_matrix_foa_mixing_data[36];
+
+extern const MappingMatrix mapping_matrix_soa_mixing;
+extern const opus_int16 mapping_matrix_soa_mixing_data[121];
+
+extern const MappingMatrix mapping_matrix_toa_mixing;
+extern const opus_int16 mapping_matrix_toa_mixing_data[324];
+
+extern const MappingMatrix mapping_matrix_foa_demixing;
+extern const opus_int16 mapping_matrix_foa_demixing_data[36];
+
+extern const MappingMatrix mapping_matrix_soa_demixing;
+extern const opus_int16 mapping_matrix_soa_demixing_data[121];
+
+extern const MappingMatrix mapping_matrix_toa_demixing;
+extern const opus_int16 mapping_matrix_toa_demixing_data[324];
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MAPPING_MATRIX_H */
/* Copyright (c) 2008-2011 Octasic Inc.
- Written by Jean-Marc Valin */
+ 2012-2017 Jean-Marc Valin */
/*
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
#include "config.h"
#endif
+#include <math.h>
#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
+#include "mlp.h"
-#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;
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)
+static OPUS_INLINE float sigmoid_approx(float x)
{
- 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)));
- }
+ return .5f + .5f*tansig_approx(.5f*x);
}
-#else
-void mlp_process(const MLP *m, const float *in, float *out)
+
+void compute_dense(const DenseLayer *layer, float *output, const float *input)
{
- 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);
- }
+ int i, j;
+ int N, M;
+ int stride;
+ M = layer->nb_inputs;
+ N = layer->nb_neurons;
+ stride = N;
+ for (i=0;i<N;i++)
+ {
+ /* Compute update gate. */
+ float sum = layer->bias[i];
+ for (j=0;j<M;j++)
+ sum += layer->input_weights[j*stride + i]*input[j];
+ output[i] = WEIGHTS_SCALE*sum;
+ }
+ if (layer->sigmoid) {
+ for (i=0;i<N;i++)
+ output[i] = sigmoid_approx(output[i]);
+ } else {
+ for (i=0;i<N;i++)
+ output[i] = tansig_approx(output[i]);
+ }
}
-#endif
+
+void compute_gru(const GRULayer *gru, float *state, const float *input)
+{
+ int i, j;
+ int N, M;
+ int stride;
+ float z[MAX_NEURONS];
+ float r[MAX_NEURONS];
+ float h[MAX_NEURONS];
+ M = gru->nb_inputs;
+ N = gru->nb_neurons;
+ stride = 3*N;
+ for (i=0;i<N;i++)
+ {
+ /* Compute update gate. */
+ float sum = gru->bias[i];
+ for (j=0;j<M;j++)
+ sum += gru->input_weights[j*stride + i]*input[j];
+ for (j=0;j<N;j++)
+ sum += gru->recurrent_weights[j*stride + i]*state[j];
+ z[i] = sigmoid_approx(WEIGHTS_SCALE*sum);
+ }
+ for (i=0;i<N;i++)
+ {
+ /* Compute reset gate. */
+ float sum = gru->bias[N + i];
+ for (j=0;j<M;j++)
+ sum += gru->input_weights[N + j*stride + i]*input[j];
+ for (j=0;j<N;j++)
+ sum += gru->recurrent_weights[N + j*stride + i]*state[j];
+ r[i] = sigmoid_approx(WEIGHTS_SCALE*sum);
+ }
+ for (i=0;i<N;i++)
+ {
+ /* Compute output. */
+ float sum = gru->bias[2*N + i];
+ for (j=0;j<M;j++)
+ sum += gru->input_weights[2*N + j*stride + i]*input[j];
+ for (j=0;j<N;j++)
+ sum += gru->recurrent_weights[2*N + j*stride + i]*state[j]*r[j];
+ h[i] = z[i]*state[i] + (1-z[i])*tansig_approx(WEIGHTS_SCALE*sum);
+ }
+ for (i=0;i<N;i++)
+ state[i] = h[i];
+}
+
-/* Copyright (c) 2008-2011 Octasic Inc.
- Written by Jean-Marc Valin */
+/* Copyright (c) 2017 Jean-Marc Valin */
/*
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
#ifndef _MLP_H_
#define _MLP_H_
-#include "arch.h"
+#include "opus_types.h"
+
+#define WEIGHTS_SCALE (1.f/128)
+
+#define MAX_NEURONS 32
typedef struct {
- int layers;
- const int *topo;
- const float *weights;
-} MLP;
+ const opus_int8 *bias;
+ const opus_int8 *input_weights;
+ int nb_inputs;
+ int nb_neurons;
+ int sigmoid;
+} DenseLayer;
+
+typedef struct {
+ const opus_int8 *bias;
+ const opus_int8 *input_weights;
+ const opus_int8 *recurrent_weights;
+ int nb_inputs;
+ int nb_neurons;
+} GRULayer;
+
+extern const DenseLayer layer0;
+extern const GRULayer layer1;
+extern const DenseLayer layer2;
-extern const MLP net;
+void compute_dense(const DenseLayer *layer, float *output, const float *input);
-void mlp_process(const MLP *m, const float *in, float *out);
+void compute_gru(const GRULayer *gru, float *state, const float *input);
#endif /* _MLP_H_ */
+/*This file is automatically generated from a Keras model*/
+
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "mlp.h"
-/* RMS error was 0.280492, seed was 1480478173 */
-/* 0.005976 0.031821 (0.280494 0.280492) done */
+static const opus_int8 layer0_weights[800] = {
+ -30, -9, 2, -12, 5, -1, 8, 9,
+ 9, 8, -13, 18, -17, -34, -5, 17,
+ -11, 0, -4, 10, 2, 10, 15, -8,
+ 2, -1, 0, 5, 13, -3, -16, 1,
+ -5, 3, 7, -28, -13, 6, 36, -3,
+ 19, -60, -17, -28, 7, -11, -30, -7,
+ 2, -42, -21, -3, 6, -22, 33, -9,
+ 7, -30, 21, -14, 24, -11, -20, -18,
+ -5, -12, 12, -49, -50, -49, 16, 9,
+ -37, -1, 9, 34, -13, -31, -31, 12,
+ 16, 44, -42, 2, -9, 8, -18, -6,
+ 9, 36, 19, 11, 13, 12, -21, 3,
+ -28, -12, 3, 33, 25, -14, 11, 1,
+ -94, -39, 18, -12, -11, -15, -7, 49,
+ 52, 10, -43, 9, 57, 8, 21, -6,
+ 14, -15, 44, -8, 7, -30, -13, -2,
+ -9, 25, -2, -127, 18, -11, -52, 26,
+ -27, 27, 10, -10, 7, 43, 6, -24,
+ 41, 10, -18, -27, 10, 17, 9, 10,
+ -17, -10, 20, -6, 22, 55, 35, -80,
+ 36, 25, -24, -36, 15, 9, -19, 88,
+ 19, 64, -51, -35, 17, 0, -7, 41,
+ -16, 27, 4, 15, -1, 18, -16, 47,
+ -39, -54, -8, 13, -25, -20, 102, -18,
+ -5, 44, 11, -28, 71, 2, -51, -5,
+ 5, 2, -83, -9, -29, 8, 21, -53,
+ 58, -37, -7, 13, 38, 9, 34, -1,
+ -41, 21, 4, -24, -36, -33, -21, 32,
+ 75, -2, 1, -68, -1, 47, -29, 32,
+ 20, 12, -65, -87, 5, 16, -12, 24,
+ 40, 15, 7, 19, -26, -17, 17, 6,
+ -2, -37, -30, -9, 32, -127, -39, 0,
+ -31, -27, 4, -22, 23, -6, -77, 35,
+ -61, 32, -37, -24, 13, -11, -1, -40,
+ -3, 17, -7, 13, 11, 59, -19, 10,
+ 6, -18, 0, 13, 3, -6, -23, 19,
+ 11, -17, 13, -1, -80, 40, -53, 69,
+ -29, -54, 0, -4, 33, -25, -2, 38,
+ 35, 36, -15, 46, 2, -13, -16, -8,
+ -8, 12, -24, -9, -55, -5, -9, 32,
+ 11, 7, 12, -18, -10, -86, -38, 54,
+ 37, -25, 18, -43, 7, -27, -27, -54,
+ 13, 9, 22, 70, 6, 35, -7, 23,
+ -15, -44, -6, 7, -66, -85, 32, 40,
+ -19, -9, -7, 12, -15, 7, 2, 6,
+ -35, 11, 28, 0, 26, 14, 1, 1,
+ 4, 12, 18, 35, 22, -18, -3, 14,
+ -1, 7, 14, -8, -14, -3, 4, -3,
+ -19, -7, -1, -25, -27, 25, -26, -2,
+ 33, -22, -27, -25, 4, -9, 7, 21,
+ 26, -30, 10, -9, -20, 11, 27, 10,
+ 5, -18, 14, -4, 2, -17, -5, -7,
+ -9, -13, 15, 29, 1, -10, -16, -10,
+ 35, 36, -7, -22, -44, 17, 30, 22,
+ 21, -1, 22, -11, 32, -8, -7, 5,
+ -10, 5, 30, -20, 29, -20, -34, 12,
+ -4, -6, 6, -13, 10, -5, -68, -1,
+ 24, 9, 19, -24, -64, 31, 19, 27,
+ -26, 75, -45, 41, 39, -42, 8, 6,
+ 23, -30, 16, -25, 30, 34, 8, -38,
+ -3, 18, 16, -31, 22, -4, -9, 1,
+ 20, 9, 38, -32, 0, -45, 0, -6,
+ -13, 11, -25, -32, -22, 31, -24, -11,
+ -11, -4, -4, 20, -34, 22, 20, 9,
+ -25, 27, -5, 28, -29, 29, 6, 21,
+ -6, -18, 54, 4, -46, 23, 21, -14,
+ -31, 36, -41, -24, 4, 22, 10, 11,
+ 7, 36, -32, -13, -52, -17, 24, 28,
+ -37, -36, -1, 24, 9, -38, 35, 48,
+ 18, 2, -1, 45, 10, 39, 24, -38,
+ 13, 8, -16, 8, 25, 11, 7, -29,
+ -11, 7, 20, -30, -38, -45, 14, -18,
+ -28, -9, 65, 61, 22, -53, -38, -16,
+ 36, 46, 20, -39, 32, -61, -6, -6,
+ -36, -33, -18, -28, 56, 101, 45, 11,
+ -28, -23, -29, -61, 20, -47, 2, 48,
+ 27, -17, 1, 40, 1, 3, -51, 15,
+ 35, 28, 22, 35, 53, -61, -29, 12,
+ -6, -21, 10, 3, -20, 2, -25, 1,
+ -6, 31, 11, -3, 1, -10, -52, 6,
+ 126, -105, 122, 127, -128, 127, 127, -128,
+ 127, 108, 12, 127, 48, -128, -36, -128,
+ 127, 127, -128, -128, 127, 89, -128, 127,
+ -128, -128, -128, 127, 127, -128, -128, -93,
+ -82, 20, 125, 65, -82, 127, 38, -74,
+ 81, 88, -88, 79, 51, -47, -111, -26,
+ 14, 83, -88, -112, 24, 35, -101, 98,
+ -99, -48, -45, 46, 83, -60, -79, 45,
+ -20, -41, 9, 4, 52, 54, 93, -10,
+ 4, 13, 3, 123, 6, 94, -111, -69,
+ -14, -31, 10, 12, 53, -79, -11, -21,
+ -2, -44, -72, 92, 65, -57, 56, -38,
+ 127, -56, -128, 127, 127, -128, 86, 117,
+ -75, -128, 127, -19, -99, -112, 127, -128,
+ 127, -48, 114, 118, -128, -128, 117, -17,
+ -6, 121, -128, 127, -128, 82, 54, -106,
+ 127, 127, -33, 100, -39, -23, 18, -78,
+ -34, -29, -1, -30, 127, -26, 127, -128,
+ 126, -128, 27, -23, -79, -120, -127, 127,
+ 72, 66, 29, 7, -66, -56, -117, -128
+};
+
+static const opus_int8 layer0_bias[32] = {
+ 51, -16, 1, 13, -5, -6, -16, -7,
+ 11, -6, 106, 26, 28, -14, 21, -29,
+ 7, 18, -18, -17, 21, -17, -9, 20,
+ -25, -3, -34, 48, 11, -13, -31, -20
+};
+
+static const opus_int8 layer1_weights[2304] = {
+ 22, -1, -7, 7, 29, -27, -31, -17,
+ -13, 33, 44, -8, 11, 33, 24, 78,
+ 15, 19, 30, -2, -24, 5, 49, 5,
+ 36, 29, -14, -11, -48, -33, 21, -42,
+ -38, -12, 55, -37, 54, -8, 1, 36,
+ 17, 0, 51, 31, 59, 7, -12, 53,
+ 4, 32, -14, 48, 5, -10, -16, -8,
+ 1, -16, -56, -24, -6, 18, -2, 23,
+ 6, 46, -6, -10, 20, 35, -44, -15,
+ -49, 36, 16, 5, -7, -79, -67, 12,
+ 70, -3, -79, -54, -85, -24, 47, -22,
+ 33, 21, 69, -1, 11, 22, 14, -16,
+ -16, -22, -28, -11, 11, -41, 31, -26,
+ -33, -19, -4, 27, 32, -50, 5, -10,
+ -38, -22, -8, 35, -31, 1, -41, -15,
+ -11, 44, 28, -17, -41, -23, 17, 2,
+ -23, -26, -13, -13, -17, 6, 14, -31,
+ -25, 9, -19, 39, -8, 4, 31, -1,
+ -45, -11, -28, -92, -46, -15, 21, 118,
+ -22, 45, -51, 11, -20, -20, -15, 13,
+ -21, -97, -29, -32, -23, -42, 94, 1,
+ 23, -8, 63, -3, -46, 19, -26, 32,
+ -40, -74, -26, 26, -4, -13, 30, -20,
+ -30, -25, -14, -31, -45, -43, 4, -60,
+ -48, -12, -34, 2, 2, 3, 13, 15,
+ 11, 16, 5, 46, -9, -55, -16, -57,
+ 29, 14, 38, -50, -2, -44, -11, -8,
+ 52, -27, -38, -7, 20, 47, 17, -59,
+ 0, 47, 46, -63, 35, -17, 19, 33,
+ 68, -19, 2, 15, -16, 28, -16, -103,
+ 26, -35, 47, -39, -60, 30, 31, -23,
+ -52, -13, 116, 47, -25, 30, 40, 30,
+ -22, 2, 12, -27, -18, 31, -10, 27,
+ -8, -66, 12, 14, 4, -26, -28, -13,
+ 3, 13, -26, -51, 37, 5, 2, -21,
+ 47, 3, 13, 25, -41, -27, -8, -4,
+ 5, -76, -33, 28, 10, 9, -46, -74,
+ 19, 28, 25, 31, 54, -55, 68, 38,
+ -24, -32, 2, 4, 68, 11, -1, 99,
+ 5, 16, -2, -74, 40, 26, -26, 33,
+ 31, -1, -68, 14, -6, 25, 9, 29,
+ 60, 61, 7, -7, 0, -24, 7, 77,
+ 4, -1, 16, -7, 13, -15, -19, 28,
+ -31, -24, -16, 37, 24, 13, 30, 10,
+ -30, 11, 11, -10, 22, 60, 28, 45,
+ -3, -40, -62, -5, -102, 9, -32, -27,
+ -54, 21, 15, -5, 37, -43, -11, 37,
+ -19, 47, -64, -128, -27, -114, 21, -66,
+ 59, 46, -3, -12, -87, -9, 4, 19,
+ -113, -36, 78, 57, -26, -38, -77, -10,
+ 6, 6, -75, 25, -97, -11, 33, -46,
+ 1, 13, -21, -33, -20, 16, -6, -3,
+ -11, -4, -27, 38, 8, -41, -2, -33,
+ 18, 19, -26, 1, -29, -22, -4, -14,
+ -55, -11, -80, -3, 11, 34, 90, 51,
+ 11, 17, 43, 36, 127, -32, 29, 103,
+ 9, 27, 13, 64, 56, 70, -14, 3,
+ -12, 10, 37, 3, 12, -22, -10, 46,
+ 28, 10, 20, 26, -24, 18, 9, 7,
+ 14, 34, -5, -7, 31, -14, -56, 11,
+ -18, -8, -17, -7, -10, -40, 10, -33,
+ -32, -43, 5, 9, 11, -4, 10, 50,
+ -12, -5, 46, 9, 7, 1, 11, 15,
+ 91, -17, 7, -50, 23, 6, -30, -99,
+ 0, -17, 14, 8, -10, -25, -30, -69,
+ -62, 31, 127, 114, -23, 101, -5, -54,
+ -6, -22, 7, -56, 39, 18, -29, 0,
+ 46, 8, -79, 4, -21, 18, -32, 62,
+ -12, -8, -12, -58, 31, -32, 17, 6,
+ -24, 25, 24, 9, -4, -19, 45, 6,
+ 17, -14, 5, -27, 16, -4, -41, 25,
+ -36, 5, 15, 12, 50, 27, 25, 23,
+ -44, -69, -9, -19, -48, -8, 4, 12,
+ -6, 13, -19, -30, -36, 26, 37, -1,
+ -3, -30, -42, -14, -10, -20, 26, -54,
+ -27, -44, 4, 73, -26, 90, 32, -69,
+ -29, -16, 3, 103, 15, -17, 37, 24,
+ -23, -31, 33, -37, -64, 25, 13, -81,
+ -28, -32, 27, 5, -35, -23, 15, -22,
+ 19, -7, 9, 30, 19, -23, 27, -13,
+ 43, 29, -29, -6, 9, -40, -33, -33,
+ -32, 9, 11, -48, -8, -23, -52, 46,
+ 17, -22, -42, 35, -15, -41, 16, 34,
+ 31, -42, -19, -11, 55, 7, -39, 89,
+ -11, -33, 20, -14, 22, 32, 3, -17,
+ -6, 14, 34, 1, 55, -21, -90, -8,
+ 18, 27, 13, -29, 21, 15, -33, -51,
+ -9, -11, 4, -16, -18, 23, -4, -4,
+ 48, 1, 7, 29, -14, -12, -16, 17,
+ 35, 8, 0, -7, -2, 9, 8, 17,
+ -6, 53, -32, -21, -50, 5, 99, -60,
+ -5, -53, 10, -31, 12, -5, 7, 80,
+ 36, 18, -31, 9, 98, 36, -63, -35,
+ 4, -13, -28, -24, 28, -13, 18, 16,
+ -1, -18, -34, 10, 20, 7, 4, 29,
+ 11, 25, -7, 36, 14, 45, 24, 1,
+ -16, 30, 6, 35, -6, -11, -24, 13,
+ -1, 27, 39, 20, 48, -11, -4, -13,
+ 28, 11, -31, -18, 31, -29, 22, -2,
+ -20, -16, 5, 30, -12, -28, -3, 93,
+ -16, 23, 18, -29, 6, -54, -37, 28,
+ -3, -3, -47, -3, -36, -55, -3, 41,
+ -10, 47, -2, 23, 42, -7, -71, -27,
+ 83, -64, 7, -24, 8, 26, -17, 15,
+ 12, 31, -30, -38, -13, -33, -56, 4,
+ -17, 20, 18, 1, -30, -5, -6, -31,
+ -14, -37, 0, 22, 10, -30, 37, -17,
+ 18, 6, 5, 23, -36, -32, 14, 18,
+ -13, -61, -52, -69, 44, -30, 16, 18,
+ -4, -25, 14, 81, 26, -8, -23, -59,
+ 52, -104, 17, 119, -32, 26, 17, 1,
+ 23, 45, 29, -64, -57, -14, 73, 21,
+ -13, -13, 9, -68, -7, -52, 3, 24,
+ -39, 44, -15, 27, 14, 19, -9, -28,
+ -11, 5, 3, -34, -2, 2, 22, -6,
+ -23, 4, 3, 13, -22, -13, -10, -18,
+ 29, 6, 44, -13, -24, -8, 2, 30,
+ 14, 43, 6, 17, -73, -6, -7, 20,
+ -80, -7, -7, -28, 15, -69, -38, -5,
+ -100, -35, 15, -79, 23, 29, -18, -27,
+ 21, -66, -37, 8, -22, -39, 48, 4,
+ -13, 1, -9, 11, -29, 22, 6, -49,
+ 32, -14, 47, -18, -4, 44, -52, -74,
+ 43, 30, 23, -14, 5, 0, -27, 4,
+ -7, 10, -4, 10, 1, -16, 11, -18,
+ -2, -5, 2, -11, 0, -20, -4, 38,
+ 74, 59, 39, 64, -10, 26, -3, -40,
+ -68, 3, -30, -51, 8, -19, -27, -46,
+ 51, 52, 54, 36, 90, 92, 14, 13,
+ -5, 0, 16, -62, 16, 11, -47, -37,
+ -6, -5, 21, 54, -57, 32, 42, -6,
+ 62, -9, 16, 21, 24, 9, -10, -4,
+ 33, 50, 13, -15, 1, -35, -48, 18,
+ -11, -17, -67, -13, 21, 38, -44, 36,
+ -16, 29, 17, 5, -10, 18, 17, -32,
+ 2, 8, 22, -56, -15, -32, 40, 43,
+ 19, 46, -7, -100, -96, 19, 53, 24,
+ 21, -26, -48, -101, -82, 61, 38, -85,
+ -28, -34, -1, 63, -5, -5, 39, 39,
+ -38, 32, -12, -28, 20, 40, -8, 2,
+ 31, 12, -35, -13, 20, -25, 30, 8,
+ 3, -13, -9, -20, 2, -13, 24, 37,
+ -10, 33, 6, 20, -16, -24, -6, -6,
+ -19, -5, 22, 21, 10, 11, -4, -39,
+ -1, 6, 49, 41, -15, -57, 21, -62,
+ 77, -69, -13, 0, -74, 1, -7, -38,
+ -8, 6, 63, 28, 4, 26, -52, 82,
+ 63, 13, 45, -33, 44, -52, -65, -21,
+ -46, -49, 64, -17, 32, 24, 68, -39,
+ -16, -5, -26, 28, 5, -61, -28, 2,
+ 24, 11, -12, -33, 9, -37, -3, -28,
+ 22, -37, -12, 19, 0, -18, -2, 14,
+ 1, 4, 8, -9, -2, 43, -17, -2,
+ -66, -31, 56, -40, -87, -36, -2, -4,
+ -42, -45, -1, 31, -43, -15, 27, 63,
+ -11, 32, -10, -33, 27, -19, 4, 15,
+ -26, -34, 29, -4, -39, -65, 14, -20,
+ -21, -17, -36, 13, 59, 47, -38, -33,
+ 13, -37, -8, -37, -7, -6, -76, -31,
+ -12, -46, 7, 24, -21, -30, -14, 9,
+ 15, -12, -13, 47, -27, -25, -1, -39,
+ 0, 20, -9, 6, 7, 4, 3, 7,
+ 39, 50, 22, -7, 14, -20, 1, 70,
+ -28, 29, -41, 10, -16, -5, -28, -2,
+ -37, 32, -18, 17, 62, -11, -20, -50,
+ 36, 21, -62, -12, -56, 52, 50, 17,
+ 3, 48, 44, -41, -25, 3, 16, -3,
+ 0, 33, -6, 15, 27, 34, -25, 22,
+ 9, 17, -11, 36, 16, -2, 12, 21,
+ -52, 45, -2, -10, 46, 21, -18, 67,
+ -28, -13, 30, 37, 42, 16, -9, 11,
+ 75, 7, -64, -40, -10, 29, 57, -23,
+ 5, 53, -77, 3, -17, -5, 47, -55,
+ -35, -36, -13, 52, -53, -71, 52, -111,
+ -23, -26, -28, 29, -43, 55, -19, 43,
+ -19, 54, -12, -33, -44, -39, -19, -10,
+ -31, -10, 21, 38, -57, -20, 2, -25,
+ 8, -6, 50, 12, 15, 25, -25, 15,
+ -30, -6, 9, 25, 37, 19, -4, 31,
+ -22, 2, 4, 2, 36, 7, 3, -34,
+ -80, 36, -10, -2, -5, 31, -36, 49,
+ -70, 20, -36, 21, 24, 25, -46, -51,
+ 36, -58, -48, -40, -10, 55, 71, 47,
+ 10, -1, 1, 2, -46, -68, 16, 13,
+ 0, -74, -29, 73, -52, -18, -11, 7,
+ -44, -82, -32, -70, -28, -1, -39, -68,
+ -6, -41, 12, -22, -16, 40, -11, -25,
+ 51, -9, 21, 4, 4, -34, 7, -78,
+ 16, 6, -38, -30, -2, -44, 32, 0,
+ 22, 64, 5, -72, -2, -14, -10, -16,
+ -8, -25, 12, 102, -58, 37, -10, -23,
+ 15, 49, 7, -7, 2, -20, -32, 45,
+ -6, 48, 28, 30, 33, -1, 22, -6,
+ 30, 65, -17, 29, 74, 37, -26, -10,
+ 15, -24, 19, -66, 22, -10, -31, -1,
+ -18, -9, 11, 37, -4, 45, 5, 41,
+ 17, 1, 1, 24, -58, 41, 5, -51,
+ 14, 8, 43, 16, -10, -1, 45, 32,
+ -64, 3, -33, -25, -3, -27, -68, 12,
+ 23, -11, -13, -37, -40, 4, -21, -12,
+ 32, -23, -19, 76, 41, -23, -24, -44,
+ -65, -1, -15, 1, 71, 63, 5, 20,
+ -3, 21, -23, 31, -32, 18, -2, 27,
+ 31, 46, -5, -39, -5, -35, 18, -18,
+ -40, -10, 3, 12, 2, -2, -22, 40,
+ 5, -6, 60, 36, 3, 29, -27, 10,
+ 25, -54, 5, 26, 39, 35, -24, -37,
+ 30, -91, 28, -4, -21, -27, -39, -6,
+ 5, 12, -128, 38, -16, 29, -95, -29,
+ 82, -2, 35, 2, 12, 8, -22, 10,
+ 80, -47, 2, -25, -73, -79, 16, -30,
+ -32, -66, 48, 21, -45, -11, -47, 14,
+ -27, -17, -7, 15, -44, -14, -44, -26,
+ -32, 26, -23, 17, -7, -28, 26, -6,
+ 28, 6, -26, 2, 13, -14, -23, -14,
+ 19, 46, 16, 2, -33, -21, 28, -17,
+ -42, 44, -37, 1, -39, 28, 84, -46,
+ 15, 10, 13, -44, 72, -26, 26, 32,
+ -28, -12, -83, 2, 10, -30, -44, -10,
+ -28, 53, 45, 65, 0, -25, 57, 36,
+ -33, 6, 29, 44, -53, 11, 19, -2,
+ -27, 35, 32, 49, 4, 23, 38, 36,
+ 24, 10, 51, -39, 4, -7, 26, 37,
+ -35, 11, -47, -18, 28, 16, -35, 42,
+ 17, -21, -41, 28, 14, -12, 11, -45,
+ 7, -43, -15, 18, -5, 38, -40, -50,
+ -30, -21, 9, -98, 13, 12, 23, 75,
+ -56, -7, -3, -4, -1, -34, 12, -49,
+ 11, 26, -18, -28, -17, 33, 13, -14,
+ 40, 24, -72, -37, 10, 17, -6, 22,
+ 16, 16, -6, -12, -30, -14, 10, 40,
+ -23, 12, 15, -3, -15, 13, -56, -4,
+ -30, 1, -3, -17, 27, 50, -5, 64,
+ -36, -19, 7, 29, 22, 25, 9, -16,
+ -58, -69, -40, -61, -71, -14, 42, 93,
+ 26, 11, -6, -58, -11, 70, -52, 19,
+ 9, -30, -33, 11, -37, -47, -21, -22,
+ -40, 10, 47, 4, -23, 17, 48, 41,
+ -48, 14, 10, 15, 34, -23, -2, -47,
+ 23, -32, -13, -10, -26, -26, -4, 16,
+ 38, -14, 0, -12, -7, -7, 20, 44,
+ -1, -32, -27, -16, 4, -6, -18, 14,
+ 5, 4, -29, 28, 7, -7, 15, -11,
+ -20, -45, -36, 16, 84, 34, -59, -30,
+ 22, 126, 8, 68, 79, -17, 21, -68,
+ 37, 5, 15, 63, 49, 127, -90, 85,
+ 43, 7, 16, 9, 6, -45, -57, -43,
+ 57, 11, -23, -11, -29, 60, -26, 0,
+ 7, 42, -24, 10, 23, -25, 8, -7,
+ -40, 19, -17, 35, 4, 27, -39, -91,
+ 27, -36, 34, 2, 16, -24, 25, 7,
+ -21, 5, 17, 10, -22, -30, 9, -17,
+ -61, -26, 33, 21, 58, -51, -14, 69,
+ -38, 20, 7, 80, -4, -65, -6, -27,
+ 53, -12, 47, -1, -15, 1, 60, 102,
+ -79, -4, 12, 9, 22, 37, -8, -4,
+ 37, 2, -3, -15, -16, -11, -5, 19,
+ -6, -43, 20, -25, -18, 10, -27, 0,
+ -28, -27, -11, 10, -18, -2, -4, -16,
+ 26, 14, -6, 7, -6, 1, 53, -2,
+ -29, 23, 9, -30, -6, -4, -6, 56,
+ 70, 0, -33, -20, -17, -9, -24, 46,
+ -5, -105, 47, -46, -51, 20, 20, -53,
+ -81, -1, -7, 75, -5, -21, -65, 12,
+ -52, 22, -50, -12, 49, 54, 76, -81,
+ 10, 45, -41, -59, 18, -19, 25, 14,
+ -31, -53, -5, 12, 31, 84, -23, 2,
+ 7, 2, 10, -32, 39, -2, -12, 1,
+ -9, 0, -10, -11, 9, 15, -8, -2,
+ 2, -1, 10, 14, -5, -40, 19, -7,
+ -7, 26, -4, 2, 1, -27, 35, 32,
+ 21, -31, 26, 43, -9, 4, -32, 40,
+ -62, -52, 36, 22, 38, 22, 36, -96,
+ 6, -10, -23, -49, 15, -33, -18, -3,
+ 0, 41, 21, -19, 21, 23, -39, -23,
+ -6, 6, 47, 56, 4, 74, 0, -98,
+ 29, -47, -14, -36, 21, -22, 22, 16,
+ 13, 12, 16, -5, 13, 17, -13, -15,
+ 1, -34, -26, 26, 12, 32, 27, 13,
+ -67, 27, 2, 8, 10, 18, 16, 20,
+ -17, -17, 57, -64, 5, 14, 19, 31,
+ -18, -44, -46, -16, 4, -25, 17, -126,
+ -24, 39, 4, 8, 55, -25, -34, 39,
+ -16, 3, 9, 71, 72, -31, -55, 6,
+ 10, -25, 32, -85, -21, 18, -8, 15,
+ 12, -27, -7, 1, -21, -2, -5, 48,
+ -16, 18, 1, -22, -26, 16, 14, -31,
+ 27, -6, -15, -21, 4, -14, 18, -36
+};
+
+static const opus_int8 layer1_recur_weights[1728] = {
+ 20, 67, -99, 12, 41, -25, 49, -44,
+ 35, 81, 110, 47, 34, -66, -14, 14,
+ -60, 34, 29, -73, 10, 41, 35, 89,
+ 7, -35, 22, 7, 27, -20, -6, 56,
+ 26, 66, 6, 33, -55, 53, 1, -21,
+ 14, 17, 68, 55, 59, 0, 18, -9,
+ 5, -41, 6, -5, -114, -12, 29, 42,
+ -23, 10, 81, -27, 20, -53, -30, -62,
+ 40, 95, 25, -4, 3, 18, -8, -15,
+ -29, -82, 2, -57, -3, -61, -29, -29,
+ 49, 2, -55, 5, -69, -99, -49, -51,
+ 6, -25, 12, 89, 44, -33, 5, 41,
+ 1, 23, -37, -37, -28, -48, 3, 4,
+ -41, -30, -57, -35, -39, -1, -13, -56,
+ -5, 50, 49, 41, -4, -4, 33, -22,
+ -1, 33, 34, 18, 40, -42, 12, 1,
+ -6, -2, 18, 17, 39, 44, 11, 65,
+ -60, -45, 10, 91, 21, 9, -62, -11,
+ 8, 69, 37, 24, -30, 21, 26, -27,
+ 1, -28, 24, 66, -8, 6, -71, 34,
+ 24, 44, 58, -78, -19, 57, 17, -60,
+ 1, 12, -3, -1, -40, 22, 11, -5,
+ 25, 12, 1, 72, 79, 7, -50, 23,
+ 18, 13, 21, -11, -20, 5, 77, -94,
+ 24, 15, 57, -51, 3, 36, 53, -1,
+ 4, 14, 30, -31, 22, 40, 32, -11,
+ -34, -36, -59, 58, 25, 21, -54, -23,
+ 40, 46, 18, 0, 12, 54, -96, -99,
+ -59, 5, 119, -38, 50, 55, 12, -16,
+ 67, 0, 34, 35, 39, 35, -1, 69,
+ 24, 27, -30, -35, -4, -70, 2, -44,
+ -7, -6, 19, -9, 60, 44, -21, -10,
+ 37, 43, -16, -3, 30, -15, -65, 31,
+ -55, 18, -98, 76, 64, 25, 24, -18,
+ -7, -68, -10, 38, 27, -60, 36, 33,
+ 16, 30, 34, -39, -37, 31, 12, 53,
+ -54, 14, -26, -49, -128, -13, -5, -22,
+ -11, -85, 55, -8, -51, -11, -33, -10,
+ -31, -76, -41, 23, 44, -40, -54, -127,
+ -101, 19, -23, -15, 15, 27, 58, -60,
+ 8, 14, -33, 1, 48, -9, -11, -123,
+ 3, 53, 23, 4, -28, 22, 2, -29,
+ -67, 36, 12, 7, 55, -21, 88, 20,
+ -1, -21, -17, 3, 41, 32, -10, -14,
+ -5, -57, 67, 57, 21, 23, -2, -27,
+ -73, -24, 120, 21, 18, -35, 42, -7,
+ 3, -45, -25, 76, -34, 50, 11, -54,
+ -91, 3, -113, -20, -5, 47, 15, -47,
+ 17, 27, -3, -26, -7, 10, 7, 74,
+ -40, 64, -7, -5, -24, -49, -24, -3,
+ -10, 27, -17, -8, -3, 14, -27, 33,
+ 13, 39, 28, -7, -38, 29, 16, 44,
+ 19, 55, -3, 9, -13, -57, 43, 43,
+ 31, 0, -93, -17, 19, -56, 4, -12,
+ -25, 37, -85, -13, -118, 33, -17, 56,
+ 71, -80, -4, 6, -11, -18, 47, -52,
+ 25, 9, 48, -107, 1, 21, 20, -3,
+ 10, -16, -4, 24, 17, 31, -61, -18,
+ -50, 24, -10, 12, 71, 26, 11, -3,
+ 4, 1, 0, -7, -40, 18, 38, -34,
+ 38, 17, 8, -34, 2, 21, 123, -32,
+ -26, 43, 14, -34, -1, -9, 37, -16,
+ 6, -17, -62, 68, 22, 17, 11, -75,
+ 33, -80, 62, -9, -75, 76, 36, -41,
+ -8, -40, -11, -71, 40, -39, 62, -49,
+ -81, 16, -9, -52, 52, 61, 17, -103,
+ -27, -10, -8, -54, -57, 21, 23, -16,
+ -52, 36, 18, 10, -5, 8, 15, -29,
+ 5, -19, -37, 8, -53, 6, 19, -37,
+ 38, -17, 48, 10, 0, 81, 46, 70,
+ -29, 101, 11, 44, -44, -3, 24, 11,
+ 3, 14, -9, 11, 14, -45, 13, 46,
+ -3, -57, 68, 44, 63, 98, 25, -28,
+ -23, 15, 32, -10, 53, -6, -2, -9,
+ -6, 16, -107, -11, -11, -28, 59, 57,
+ -22, 38, 42, 83, 27, 5, 29, -30,
+ 12, -21, -13, 31, 38, -21, 58, -10,
+ -10, -15, -2, -5, 11, 12, -73, -28,
+ -38, 22, 2, -25, 73, -52, -12, -55,
+ 32, -63, 21, 51, 33, 52, -26, 55,
+ -26, -26, 57, -32, -4, -52, -61, 21,
+ -33, -91, -51, 69, -90, -53, -38, -44,
+ 12, -76, -20, 77, -45, -7, 86, 43,
+ -109, -33, -105, -40, -121, -10, 0, -72,
+ 45, -51, -75, -49, -38, -1, -62, 18,
+ -1, 30, -44, -14, -10, -67, 40, -10,
+ -34, 46, -64, -32, 29, -13, 33, 3,
+ -32, -5, 28, -27, -25, 93, 24, 68,
+ -40, 57, 23, -3, -21, -58, 17, -39,
+ -17, -22, -89, 11, 18, -46, 27, 24,
+ 46, 127, 61, 87, 31, 127, -36, 47,
+ -23, 47, 127, -24, 110, 122, 30, 100,
+ 0, 96, -12, 6, 50, 44, -13, 73,
+ 4, 55, -11, -15, 49, 42, -6, 20,
+ -35, 58, 18, 38, 42, 72, 19, -21,
+ 11, 9, -37, 7, 29, 31, 16, -17,
+ 13, -50, 19, 5, -23, 51, -16, -5,
+ 4, -24, 76, 10, -53, -28, -7, -65,
+ 74, 40, -16, -29, 32, -16, -49, -35,
+ -3, 59, -96, -50, -43, -43, -61, -15,
+ -8, -36, -34, -33, -14, 11, -3, -39,
+ 4, -114, -123, -11, -49, -21, 14, -56,
+ 1, 43, -63, 26, 40, 18, -10, -26,
+ -14, -15, -35, -35, -11, 32, -44, -67,
+ 2, 22, 7, 3, -9, -30, -51, -28,
+ 28, 6, -22, 16, 34, -25, -52, -54,
+ -8, -6, 5, 8, 20, -16, -17, -44,
+ 27, 3, 31, -5, -48, -1, -3, 116,
+ 11, 71, -31, -47, 109, 50, -22, -12,
+ -57, 32, 66, 8, -25, -93, -54, -10,
+ 19, -76, -34, 97, 48, -36, -18, -30,
+ -39, -26, -12, 28, 14, 12, -12, -31,
+ 38, 2, 10, 4, -40, 20, 16, -61,
+ 2, 64, 39, 5, 15, 33, 40, -61,
+ -49, 93, -10, 33, 28, -11, -27, -18,
+ 39, -62, -6, -6, 62, 11, -8, 38,
+ -67, 12, 27, 39, -27, 123, -18, -6,
+ -65, 83, -64, 20, 19, -11, 33, 24,
+ 17, 56, 78, 7, -15, 54, -101, -9,
+ 115, -96, 50, 51, 35, 34, 27, 37,
+ -40, -11, 8, -36, 42, -45, 2, -23,
+ 0, 67, -8, -9, -13, 50, -14, -27,
+ 4, 0, -8, -14, 30, -9, 29, 15,
+ 9, -38, 37, -8, 50, -46, 54, 41,
+ -11, -8, -11, -26, 39, 45, 14, -26,
+ -17, -27, 69, 38, 39, 98, 66, 0,
+ 42, 123, -101, -19, -83, 117, -32, 56,
+ 10, 12, -88, 79, -53, 56, 63, 95,
+ -62, 9, 36, -13, -79, -16, 37, -46,
+ 35, -34, 14, 17, -54, 5, 21, -7,
+ 7, 63, 56, 15, 27, -76, -25, 4,
+ -26, -63, 28, -67, -52, 43, -47, -70,
+ 40, -12, 40, -66, -37, 0, 35, 37,
+ -53, 4, -17, -51, 11, 21, 14, -34,
+ -4, 24, -42, 29, 22, 7, 28, 12,
+ 37, 39, -39, -19, 65, -60, -50, -2,
+ 1, 82, 39, 19, -23, -43, -22, -67,
+ -35, -34, 32, 102, 81, 127, 36, 67,
+ -45, 1, -67, -52, -4, 35, 20, 28,
+ 71, 86, -35, -9, -83, -34, 12, 9,
+ -23, 2, 14, 28, -23, 7, -25, 45,
+ 7, 17, -37, 0, -19, 31, 26, 40,
+ -27, -16, 17, 5, -21, 23, 24, 96,
+ -55, 52, -19, -14, -6, 1, 50, -34,
+ 86, -53, 38, 2, -52, -36, -13, 60,
+ -85, -120, 32, 7, -12, 22, 70, -7,
+ -94, 38, -76, -31, -20, 15, -28, 7,
+ 6, 40, 53, 88, 3, 38, 18, -8,
+ -22, -23, 51, 37, -9, 13, -32, 25,
+ -21, 27, 31, 20, 18, -9, -13, 1,
+ 21, -24, -13, 39, 15, -11, -29, -36,
+ 18, 15, 8, 27, 21, -94, -1, -22,
+ 49, 66, -1, 6, -3, -40, -18, 6,
+ 28, 12, 33, -59, 62, 60, -48, 90,
+ -1, 108, 9, 18, -2, 27, 77, -65,
+ 82, -48, -38, -19, -11, 127, 50, 66,
+ 18, -13, -22, 60, -38, 40, -14, -26,
+ -13, 38, 67, 57, 30, 33, 26, 36,
+ 38, -17, 27, -28, 20, 12, -64, 18,
+ 5, -33, -27, 13, -26, 32, 35, -5,
+ -48, -14, 92, 43, -47, -14, 40, 11,
+ 51, 66, 22, -63, -16, -61, 4, -28,
+ 27, 20, -33, -30, -21, -29, -53, 31,
+ -40, 24, 43, -4, -19, 21, 67, 20,
+ 100, -16, -93, 78, -6, -18, -52, -37,
+ -9, 66, -31, -8, 26, 18, 4, 24,
+ -22, 17, -2, -13, 27, 0, 8, -18,
+ -25, 5, -21, -24, -7, 18, -93, 21,
+ 7, 2, -75, 69, 50, -5, -15, -17,
+ 60, -42, 55, 1, -4, 3, 10, 46,
+ 16, -13, 45, -7, -10, -44, -108, 49,
+ 2, -15, -64, -12, -72, 32, -38, -45,
+ 10, -54, 13, -13, -27, -36, -64, 58,
+ -62, -101, 88, -86, -71, -39, -9, -128,
+ 32, 15, -4, 54, -16, -39, -26, -36,
+ 46, 48, -64, -10, 19, 30, -13, 34,
+ -8, 50, 60, -22, -6, -11, -30, 5,
+ 50, 32, 56, 0, 25, 6, 68, 11,
+ -29, 45, -9, -12, 4, 1, 18, -49,
+ 0, -38, -19, 90, 29, 35, 51, 8,
+ -48, 96, -1, -12, -9, -32, -63, -65,
+ -7, 38, 89, 28, -85, -28, -23, -25,
+ -128, 56, 79, -36, 99, -6, -37, 7,
+ -13, -69, -46, -29, 25, 64, -21, 17,
+ 1, 42, -66, 1, 80, 26, -32, 21,
+ 15, 15, 6, 6, -10, 15, 127, 5,
+ 38, 27, 87, -57, -25, 11, 72, -21,
+ -5, 11, -13, -66, 78, 36, -3, 41,
+ -21, 8, -33, 23, 73, 28, 57, -25,
+ -5, 4, -22, -47, 15, 4, -57, -72,
+ 33, 1, 18, 2, 53, -71, -99, -21,
+ -3, -111, 108, 71, -14, 82, 25, 61,
+ -48, 5, 9, -51, -20, -25, -3, 14,
+ -33, 14, -3, -34, 22, 12, -19, -38,
+ -16, 2, 21, 16, 26, -31, 75, 44,
+ -31, 16, 26, 66, 17, -9, -22, -22,
+ 22, -44, 22, 27, 2, 58, -14, 10,
+ -73, -42, 55, -25, -61, 72, -1, 30,
+ -58, -25, 63, 26, -48, -40, 26, -30,
+ 60, 8, -17, -1, -18, -20, 43, -20,
+ -4, -28, 127, -106, 29, 70, 64, -27,
+ 39, -33, -5, -88, -40, -52, 26, 44,
+ -17, 23, 2, -49, 22, -9, -8, 86,
+ 49, -43, -60, 1, 10, 45, 36, -53,
+ -4, 33, 38, 48, -72, 1, 19, 21,
+ -65, 4, -5, -62, 27, -25, 17, -6,
+ 6, -45, -39, -46, 4, 26, 127, -9,
+ 18, -33, -18, -3, 33, 2, -5, 15,
+ -26, -22, -117, -63, -17, -59, 61, -74,
+ 7, -47, -58, -128, -67, 15, -16, -128,
+ 12, 2, 20, 9, -48, -40, 43, 3,
+ -40, -16, -38, -6, -22, -28, -16, -59,
+ -22, 6, -5, 11, -12, -66, -40, 27,
+ -62, -44, -19, 38, -3, 39, -8, 40,
+ -24, 13, 21, 50, -60, -22, 53, -29,
+ -6, 1, 22, -59, 0, 17, -39, 115
+};
+
+static const opus_int8 layer1_bias[72] = {
+ -42, 20, 16, 0, 105, 60, 1, -97,
+ 24, 60, 18, 13, 62, 25, 127, 34,
+ 79, 55, 118, 127, 95, 31, -4, 87,
+ 21, 12, 2, -14, 18, 23, 8, 17,
+ -1, -8, 5, 4, 24, 37, 21, 13,
+ 36, 13, 17, 18, 37, 30, 33, 1,
+ 8, -16, -11, -5, -31, -3, -5, 0,
+ 6, 3, 58, -7, -1, -16, 5, -13,
+ 16, 10, -2, -14, 11, -4, 3, -11
+};
+
+static const opus_int8 layer2_weights[48] = {
+ -113, -88, 31, -128, -126, -61, 85, -35,
+ 118, -128, -61, 127, -128, -17, -128, 127,
+ 104, -9, -128, 33, 45, 127, 5, 83,
+ 84, -128, -85, -128, -45, 48, -53, -128,
+ 46, 127, -17, 125, 117, -41, -117, -91,
+ -127, -68, -1, -89, -80, 32, 106, 7
+};
-static const float weights[450] = {
+static const opus_int8 layer2_bias[2] = {
+ 14, 117
+};
-/* hidden layer */
--0.514624f, 0.0234227f, -0.14329f, -0.0878216f, -0.00187827f,
--0.0257443f, 0.108524f, 0.00333881f, 0.00585017f, -0.0246132f,
-0.142723f, -0.00436494f, 0.0101354f, -0.11124f, -0.0809367f,
--0.0750772f, 0.0295524f, 0.00823944f, 0.150392f, 0.0320876f,
--0.0710564f, -1.43818f, 0.652076f, 0.0650744f, -1.54821f,
-0.168949f, -1.92724f, 0.0517976f, -0.0670737f, -0.0690121f,
-0.00247528f, -0.0522024f, 0.0631368f, 0.0532776f, 0.047751f,
--0.011715f, 0.142374f, -0.0290885f, -0.279263f, -0.433499f,
--0.0795174f, -0.380458f, -0.051263f, 0.218537f, -0.322478f,
-1.06667f, -0.104607f, -4.70108f, 0.312037f, 0.277397f,
--2.71859f, 1.70037f, -0.141845f, 0.0115618f, 0.0629883f,
-0.0403871f, 0.0139428f, -0.00430733f, -0.0429038f, -0.0590318f,
--0.0501526f, -0.0284802f, -0.0415686f, -0.0438999f, 0.0822666f,
-0.197194f, 0.0363275f, -0.0584307f, 0.0752364f, -0.0799796f,
--0.146275f, 0.161661f, -0.184585f, 0.145568f, 0.442823f,
-1.61221f, 1.11162f, 2.62177f, -2.482f, -0.112599f,
--0.110366f, -0.140794f, -0.181694f, 0.0648674f, 0.0842248f,
-0.0933993f, 0.150122f, 0.129171f, 0.176848f, 0.141758f,
--0.271822f, 0.235113f, 0.0668579f, -0.433957f, 0.113633f,
--0.169348f, -1.40091f, 0.62861f, -0.134236f, 0.402173f,
-1.86373f, 1.53998f, -4.32084f, 0.735343f, 0.800214f,
--0.00968415f, 0.0425904f, 0.0196811f, -0.018426f, -0.000343953f,
--0.00416389f, 0.00111558f, 0.0173069f, -0.00998596f, -0.025898f,
-0.00123764f, -0.00520373f, -0.0565033f, 0.0637394f, 0.0051213f,
-0.0221361f, 0.00819962f, -0.0467061f, -0.0548258f, -0.00314063f,
--1.18332f, 1.88091f, -0.41148f, -2.95727f, -0.521449f,
--0.271641f, 0.124946f, -0.0532936f, 0.101515f, 0.000208564f,
--0.0488748f, 0.0642388f, -0.0383848f, 0.0135046f, -0.0413592f,
--0.0326402f, -0.0137421f, -0.0225219f, -0.0917294f, -0.277759f,
--0.185418f, 0.0471128f, -0.125879f, 0.262467f, -0.212794f,
--0.112931f, -1.99885f, -0.404787f, 0.224402f, 0.637962f,
--0.27808f, -0.0723953f, -0.0537655f, -0.0336359f, -0.0906601f,
--0.0641309f, -0.0713542f, 0.0524317f, 0.00608819f, 0.0754101f,
--0.0488401f, -0.00671865f, 0.0418239f, 0.0536284f, -0.132639f,
-0.0267648f, -0.248432f, -0.0104153f, 0.035544f, -0.212753f,
--0.302895f, -0.0357854f, 0.376838f, 0.597025f, -0.664647f,
-0.268422f, -0.376772f, -1.05472f, 0.0144178f, 0.179122f,
-0.0360155f, 0.220262f, -0.0056381f, 0.0317197f, 0.0621066f,
--0.00779298f, 0.00789378f, 0.00350605f, 0.0104809f, 0.0362871f,
--0.157708f, -0.0659779f, -0.0926278f, 0.00770791f, 0.0631621f,
-0.0817343f, -0.424295f, -0.0437727f, -0.24251f, 0.711217f,
--0.736455f, -2.194f, -0.107612f, -0.175156f, -0.0366573f,
--0.0123156f, -0.0628516f, -0.0218977f, -0.00693699f, 0.00695185f,
-0.00507362f, 0.00359334f, 0.0052661f, 0.035561f, 0.0382701f,
-0.0342179f, -0.00790271f, -0.0170925f, 0.047029f, 0.0197362f,
--0.0153435f, 0.0644152f, -0.36862f, -0.0674876f, -2.82672f,
-1.34122f, -0.0788029f, -3.47792f, 0.507246f, -0.816378f,
--0.0142383f, -0.127349f, -0.106926f, -0.0359524f, 0.105045f,
-0.291554f, 0.195413f, 0.0866214f, -0.066577f, -0.102188f,
-0.0979466f, -0.12982f, 0.400181f, -0.409336f, -0.0593326f,
--0.0656203f, -0.204474f, 0.179802f, 0.000509084f, 0.0995954f,
--2.377f, -0.686359f, 0.934861f, 1.10261f, 1.3901f,
--4.33616f, -0.00264017f, 0.00713045f, 0.106264f, 0.143726f,
--0.0685305f, -0.054656f, -0.0176725f, -0.0772669f, -0.0264526f,
--0.0103824f, -0.0269872f, -0.00687f, 0.225804f, 0.407751f,
--0.0612611f, -0.0576863f, -0.180131f, -0.222772f, -0.461742f,
-0.335236f, 1.03399f, 4.24112f, -0.345796f, -0.594549f,
--76.1407f, -0.265276f, 0.0507719f, 0.0643044f, 0.0384832f,
-0.0424459f, -0.0387817f, -0.0235996f, -0.0740556f, -0.0270029f,
-0.00882177f, -0.0552371f, -0.00485851f, 0.314295f, 0.360431f,
--0.0787085f, 0.110355f, -0.415958f, -0.385088f, -0.272224f,
--1.55108f, -0.141848f, 0.448877f, -0.563447f, -2.31403f,
--0.120077f, -1.49918f, -0.817726f, -0.0495854f, -0.0230782f,
--0.0224014f, 0.117076f, 0.0393216f, 0.051997f, 0.0330763f,
--0.110796f, 0.0211117f, -0.0197258f, 0.0187461f, 0.0125183f,
-0.14876f, 0.0920565f, -0.342475f, 0.135272f, -0.168155f,
--0.033423f, -0.0604611f, -0.128835f, 0.664947f, -0.144997f,
-2.27649f, 1.28663f, 0.841217f, -2.42807f, 0.0230471f,
-0.226709f, -0.0374803f, 0.155436f, 0.0400342f, -0.184686f,
-0.128488f, -0.0939518f, -0.0578559f, 0.0265967f, -0.0999322f,
--0.0322768f, -0.322994f, -0.189371f, -0.738069f, -0.0754914f,
-0.214717f, -0.093728f, -0.695741f, 0.0899298f, -2.06188f,
--0.273719f, -0.896977f, 0.130553f, 0.134638f, 1.29355f,
-0.00520749f, -0.0324224f, 0.00530451f, 0.0192385f, 0.00328708f,
-0.0250838f, 0.0053365f, -0.0177321f, 0.00618789f, 0.00525364f,
-0.00104596f, -0.0360459f, 0.0402403f, -0.0406351f, 0.0136883f,
-0.0880722f, -0.0197449f, 0.089938f, 0.0100456f, -0.0475638f,
--0.73267f, 0.037433f, -0.146551f, -0.230221f, -3.06489f,
--1.40194f, 0.0198483f, 0.0397953f, -0.0190239f, 0.0470715f,
--0.131363f, -0.191721f, -0.0176224f, -0.0480352f, -0.221799f,
--0.26794f, -0.0292615f, 0.0612127f, -0.129877f, 0.00628332f,
--0.085918f, 0.0175379f, 0.0541011f, -0.0810874f, -0.380809f,
--0.222056f, -0.508859f, -0.473369f, 0.484958f, -2.28411f,
-0.0139516f,
-/* output layer */
-3.90017f, 1.71789f, -1.43372f, -2.70839f, 1.77107f,
-5.48006f, 1.44661f, 2.01134f, -1.88383f, -3.64958f,
--1.26351f, 0.779421f, 2.11357f, 3.10409f, 1.68846f,
--4.46197f, -1.61455f, 3.59832f, 2.43531f, -1.26458f,
-0.417941f, 1.47437f, 2.16635f, -1.909f, -0.828869f,
-1.38805f, -2.67975f, -0.110044f, 1.95596f, 0.697931f,
--0.313226f, -0.889315f, 0.283236f, 0.946102f, };
+const DenseLayer layer0 = {
+ layer0_bias,
+ layer0_weights,
+ 25, 32, 0
+};
-static const int topo[3] = {25, 16, 2};
+const GRULayer layer1 = {
+ layer1_bias,
+ layer1_weights,
+ layer1_recur_weights,
+ 32, 24
+};
-const MLP net = {
- 3,
- topo,
- weights
+const DenseLayer layer2 = {
+ layer2_bias,
+ layer2_weights,
+ 24, 2, 1
};
+
/* Number of frames encoded in bits 0 to 5 */
ch = *data++;
count = ch&0x3F;
- if (count <= 0 || framesize*count > 5760)
+ if (count <= 0 || framesize*(opus_int32)count > 5760)
return OPUS_INVALID_PACKET;
len--;
/* Padding flag is bit 6 */
opus_uint32 rangeFinal;
};
+#if defined(ENABLE_HARDENING) || defined(ENABLE_ASSERTIONS)
+static void validate_opus_decoder(OpusDecoder *st)
+{
+ celt_assert(st->channels == 1 || st->channels == 2);
+ celt_assert(st->Fs == 48000 || st->Fs == 24000 || st->Fs == 16000 || st->Fs == 12000 || st->Fs == 8000);
+ celt_assert(st->DecControl.API_sampleRate == st->Fs);
+ celt_assert(st->DecControl.internalSampleRate == 0 || st->DecControl.internalSampleRate == 16000 || st->DecControl.internalSampleRate == 12000 || st->DecControl.internalSampleRate == 8000);
+ celt_assert(st->DecControl.nChannelsAPI == st->channels);
+ celt_assert(st->DecControl.nChannelsInternal == 0 || st->DecControl.nChannelsInternal == 1 || st->DecControl.nChannelsInternal == 2);
+ celt_assert(st->DecControl.payloadSize_ms == 0 || st->DecControl.payloadSize_ms == 10 || st->DecControl.payloadSize_ms == 20 || st->DecControl.payloadSize_ms == 40 || st->DecControl.payloadSize_ms == 60);
+#ifdef OPUS_ARCHMASK
+ celt_assert(st->arch >= 0);
+ celt_assert(st->arch <= OPUS_ARCHMASK);
+#endif
+ celt_assert(st->stream_channels == 1 || st->stream_channels == 2);
+}
+#define VALIDATE_OPUS_DECODER(st) validate_opus_decoder(st)
+#else
+#define VALIDATE_OPUS_DECODER(st)
+#endif
int opus_decoder_get_size(int channels)
{
return OPUS_BAD_ARG;
OPUS_CLEAR((char*)st, opus_decoder_get_size(channels));
- /* Initialize SILK encoder */
+ /* Initialize SILK decoder */
ret = silk_Get_Decoder_Size(&silkDecSizeBytes);
if (ret)
return OPUS_INTERNAL_ERROR;
int audiosize;
int mode;
+ int bandwidth;
int transition=0;
int start_band;
int redundancy=0;
{
audiosize = st->frame_size;
mode = st->mode;
+ bandwidth = st->bandwidth;
ec_dec_init(&dec,(unsigned char*)data,len);
} else {
audiosize = frame_size;
mode = st->prev_mode;
+ bandwidth = 0;
if (mode == 0)
{
{
st->DecControl.nChannelsInternal = st->stream_channels;
if( mode == MODE_SILK_ONLY ) {
- if( st->bandwidth == OPUS_BANDWIDTH_NARROWBAND ) {
+ if( bandwidth == OPUS_BANDWIDTH_NARROWBAND ) {
st->DecControl.internalSampleRate = 8000;
- } else if( st->bandwidth == OPUS_BANDWIDTH_MEDIUMBAND ) {
+ } else if( bandwidth == OPUS_BANDWIDTH_MEDIUMBAND ) {
st->DecControl.internalSampleRate = 12000;
- } else if( st->bandwidth == OPUS_BANDWIDTH_WIDEBAND ) {
+ } else if( bandwidth == OPUS_BANDWIDTH_WIDEBAND ) {
st->DecControl.internalSampleRate = 16000;
} else {
st->DecControl.internalSampleRate = 16000;
- silk_assert( 0 );
+ celt_assert( 0 );
}
} else {
/* Hybrid mode */
if (mode != MODE_CELT_ONLY)
start_band = 17;
+ 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);
+ }
+
+
+ if (bandwidth)
{
int endband=21;
- switch(st->bandwidth)
+ switch(bandwidth)
{
case OPUS_BANDWIDTH_NARROWBAND:
endband = 13;
case OPUS_BANDWIDTH_FULLBAND:
endband = 21;
break;
+ default:
+ celt_assert(0);
+ 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);
+ MUST_SUCCEED(celt_decoder_ctl(celt_dec, CELT_SET_END_BAND(endband)));
}
+ MUST_SUCCEED(celt_decoder_ctl(celt_dec, CELT_SET_CHANNELS(st->stream_channels)));
/* Only allocation memory for redundancy if/when needed */
redundant_audio_size = redundancy ? F5*st->channels : ALLOC_NONE;
/* 5 ms redundant frame for CELT->SILK*/
if (redundancy && celt_to_silk)
{
- celt_decoder_ctl(celt_dec, CELT_SET_START_BAND(0));
+ MUST_SUCCEED(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_SUCCEED(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));
+ MUST_SUCCEED(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);
+ MUST_SUCCEED(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);
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));
+ MUST_SUCCEED(celt_decoder_ctl(celt_dec, CELT_SET_START_BAND(0)));
celt_decode_with_ec(celt_dec, silence, 2, pcm, F2_5, NULL, celt_accum);
}
}
{
const CELTMode *celt_mode;
- celt_decoder_ctl(celt_dec, CELT_GET_MODE(&celt_mode));
+ MUST_SUCCEED(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));
+ MUST_SUCCEED(celt_decoder_ctl(celt_dec, OPUS_RESET_STATE));
+ MUST_SUCCEED(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_SUCCEED(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);
}
int packet_frame_size, packet_bandwidth, packet_mode, packet_stream_channels;
/* 48 x 2.5 ms = 120 ms */
opus_int16 size[48];
+ VALIDATE_OPUS_DECODER(st);
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 */
else
return OPUS_INVALID_PACKET;
}
+ celt_assert(st->channels == 1 || st->channels == 2);
ALLOC(out, frame_size*st->channels, opus_int16);
ret = opus_decode_native(st, data, len, out, frame_size, decode_fec, 0, NULL, 0);
else
return OPUS_INVALID_PACKET;
}
+ celt_assert(st->channels == 1 || st->channels == 2);
ALLOC(out, frame_size*st->channels, float);
ret = opus_decode_native(st, data, len, out, frame_size, decode_fec, 0, NULL, 1);
goto bad_arg;
}
if (st->prev_mode == MODE_CELT_ONLY)
- celt_decoder_ctl(celt_dec, OPUS_GET_PITCH(value));
+ ret = celt_decoder_ctl(celt_dec, OPUS_GET_PITCH(value));
else
*value = st->DecControl.prevPitchLag;
}
{
goto bad_arg;
}
- celt_decoder_ctl(celt_dec, OPUS_SET_PHASE_INVERSION_DISABLED(value));
+ ret = celt_decoder_ctl(celt_dec, OPUS_SET_PHASE_INVERSION_DISABLED(value));
}
break;
case OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST:
{
goto bad_arg;
}
- celt_decoder_ctl(celt_dec, OPUS_GET_PHASE_INVERSION_DISABLED(value));
+ ret = celt_decoder_ctl(celt_dec, OPUS_GET_PHASE_INVERSION_DISABLED(value));
}
break;
default:
| ((opus_uint32)ch[2]<< 8) | (opus_uint32)ch[3];
}
-static void check_encoder_option(int decode_only, const char *opt)
-{
- if (decode_only)
- {
- fprintf(stderr, "option %s is only for encoding\n", opt);
- exit(EXIT_FAILURE);
- }
-}
+#define check_encoder_option(decode_only, opt) do {if (decode_only) {fprintf(stderr, "option %s is only for encoding\n", opt); goto failure;}} while(0)
static const int silk8_test[][4] = {
{MODE_SILK_ONLY, OPUS_BANDWIDTH_NARROWBAND, 960*3, 1},
{
int err;
char *inFile, *outFile;
- FILE *fin, *fout;
+ FILE *fin=NULL;
+ FILE *fout=NULL;
OpusEncoder *enc=NULL;
OpusDecoder *dec=NULL;
int args;
int len[2];
int frame_size, channels;
opus_int32 bitrate_bps=0;
- unsigned char *data[2];
- unsigned char *fbytes;
+ unsigned char *data[2] = {NULL, NULL};
+ unsigned char *fbytes=NULL;
opus_int32 sampling_rate;
int use_vbr;
int max_payload_bytes;
int k;
opus_int32 skip=0;
int stop=0;
- short *in, *out;
+ short *in=NULL;
+ short *out=NULL;
int application=OPUS_APPLICATION_AUDIO;
double bits=0.0, bits_max=0.0, bits_act=0.0, bits2=0.0, nrg;
double tot_samples=0;
int remaining=0;
int variable_duration=OPUS_FRAMESIZE_ARG;
int delayed_decision=0;
+ int ret = EXIT_FAILURE;
if (argc < 5 )
{
print_usage( argv );
- return EXIT_FAILURE;
+ goto failure;
}
tot_in=tot_out=0;
if (!decode_only && argc < 7 )
{
print_usage( argv );
- return EXIT_FAILURE;
+ goto failure;
}
if (!decode_only)
else if (strcmp(argv[args], "audio")!=0) {
fprintf(stderr, "unknown application: %s\n", argv[args]);
print_usage(argv);
- return EXIT_FAILURE;
+ goto failure;
}
args++;
}
{
fprintf(stderr, "Supported sampling rates are 8000, 12000, "
"16000, 24000 and 48000.\n");
- return EXIT_FAILURE;
+ goto failure;
}
frame_size = sampling_rate/50;
if (channels < 1 || channels > 2)
{
fprintf(stderr, "Opus_demo supports only 1 or 2 channels.\n");
- return EXIT_FAILURE;
+ goto failure;
}
if (!decode_only)
fprintf(stderr, "Unknown bandwidth %s. "
"Supported are NB, MB, WB, SWB, FB.\n",
argv[ args + 1 ]);
- return EXIT_FAILURE;
+ goto failure;
}
args += 2;
} else if( strcmp( argv[ args ], "-framesize" ) == 0 ) {
fprintf(stderr, "Unsupported frame size: %s ms. "
"Supported are 2.5, 5, 10, 20, 40, 60, 80, 100, 120.\n",
argv[ args + 1 ]);
- return EXIT_FAILURE;
+ goto failure;
}
args += 2;
} else if( strcmp( argv[ args ], "-max_payload" ) == 0 ) {
} else {
printf( "Error: unrecognized setting: %s\n\n", argv[ args ] );
print_usage( argv );
- return EXIT_FAILURE;
+ goto failure;
}
}
{
fprintf (stderr, "max_payload_bytes must be between 0 and %d\n",
MAX_PACKET);
- return EXIT_FAILURE;
+ goto failure;
}
inFile = argv[argc-2];
if (!fin)
{
fprintf (stderr, "Could not open input file %s\n", argv[argc-2]);
- return EXIT_FAILURE;
+ goto failure;
}
if (mode_list)
{
if (!fout)
{
fprintf (stderr, "Could not open output file %s\n", argv[argc-1]);
- fclose(fin);
- return EXIT_FAILURE;
+ goto failure;
}
if (!decode_only)
if (err != OPUS_OK)
{
fprintf(stderr, "Cannot create encoder: %s\n", opus_strerror(err));
- fclose(fin);
- fclose(fout);
- return EXIT_FAILURE;
+ goto failure;
}
opus_encoder_ctl(enc, OPUS_SET_BITRATE(bitrate_bps));
opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(bandwidth));
if (err != OPUS_OK)
{
fprintf(stderr, "Cannot create decoder: %s\n", opus_strerror(err));
- fclose(fin);
- fclose(fout);
- return EXIT_FAILURE;
+ goto failure;
}
}
if (len[toggle] < 0)
{
fprintf (stderr, "opus_encode() returned %d\n", len[toggle]);
- fclose(fin);
- fclose(fout);
- return EXIT_FAILURE;
+ goto failure;
}
curr_mode_count += frame_size;
if (curr_mode_count > mode_switch_time && curr_mode < nb_modes_in_list-1)
if ((err = opus_packet_pad(data[toggle], len[toggle], new_len)) != OPUS_OK)
{
fprintf(stderr, "padding failed: %s\n", opus_strerror(err));
- return EXIT_FAILURE;
+ goto failure;
}
len[toggle] = new_len;
}
int_to_char(len[toggle], int_field);
if (fwrite(int_field, 1, 4, fout) != 4) {
fprintf(stderr, "Error writing.\n");
- return EXIT_FAILURE;
+ goto failure;
}
int_to_char(enc_final_range[toggle], int_field);
if (fwrite(int_field, 1, 4, fout) != 4) {
fprintf(stderr, "Error writing.\n");
- return EXIT_FAILURE;
+ goto failure;
}
if (fwrite(data[toggle], 1, len[toggle], fout) != (unsigned)len[toggle]) {
fprintf(stderr, "Error writing.\n");
- return EXIT_FAILURE;
+ goto failure;
}
tot_samples += nb_encoded;
} else {
}
if (fwrite(fbytes, sizeof(short)*channels, output_samples-skip, fout) != (unsigned)(output_samples-skip)){
fprintf(stderr, "Error writing.\n");
- return EXIT_FAILURE;
+ goto failure;
}
tot_out += output_samples-skip;
}
(long)count,
(unsigned long)enc_final_range[toggle^use_inbandfec],
(unsigned long)dec_final_range);
- fclose(fin);
- fclose(fout);
- return EXIT_FAILURE;
+ goto failure;
}
lost_prev = lost;
toggle = (toggle + use_inbandfec) & 1;
}
- /* Print out bitrate statistics */
- if(decode_only)
+ if(decode_only && count > 0)
frame_size = (int)(tot_samples / count);
count -= use_inbandfec;
- fprintf (stderr, "average bitrate: %7.3f kb/s\n",
- 1e-3*bits*sampling_rate/tot_samples);
- fprintf (stderr, "maximum bitrate: %7.3f kb/s\n",
- 1e-3*bits_max*sampling_rate/frame_size);
- if (!decode_only)
- fprintf (stderr, "active bitrate: %7.3f kb/s\n",
- 1e-3*bits_act*sampling_rate/(1e-15+frame_size*(double)count_act));
- fprintf (stderr, "bitrate standard deviation: %7.3f kb/s\n",
- 1e-3*sqrt(bits2/count - bits*bits/(count*(double)count))*sampling_rate/frame_size);
+ if (tot_samples >= 1 && count > 0 && frame_size)
+ {
+ /* Print out bitrate statistics */
+ double var;
+ fprintf (stderr, "average bitrate: %7.3f kb/s\n",
+ 1e-3*bits*sampling_rate/tot_samples);
+ fprintf (stderr, "maximum bitrate: %7.3f kb/s\n",
+ 1e-3*bits_max*sampling_rate/frame_size);
+ if (!decode_only)
+ fprintf (stderr, "active bitrate: %7.3f kb/s\n",
+ 1e-3*bits_act*sampling_rate/(1e-15+frame_size*(double)count_act));
+ var = bits2/count - bits*bits/(count*(double)count);
+ if (var < 0)
+ var = 0;
+ fprintf (stderr, "bitrate standard deviation: %7.3f kb/s\n",
+ 1e-3*sqrt(var)*sampling_rate/frame_size);
+ } else {
+ fprintf(stderr, "bitrate statistics are undefined\n");
+ }
silk_TimerSave("opus_timing.txt");
+ ret = EXIT_SUCCESS;
+failure:
opus_encoder_destroy(enc);
opus_decoder_destroy(dec);
free(data[0]);
- if (use_inbandfec)
- free(data[1]);
- fclose(fin);
- fclose(fout);
+ free(data[1]);
+ if (fin)
+ fclose(fin);
+ if (fout)
+ fclose(fout);
free(in);
free(out);
free(fbytes);
- return EXIT_SUCCESS;
+ return ret;
}
middle (memoriless) threshold. The second column is the hysteresis
(difference with the middle) */
static const opus_int32 mono_voice_bandwidth_thresholds[8] = {
- 10000, 1000, /* NB<->MB */
- 11000, 1000, /* MB<->WB */
+ 9000, 700, /* NB<->MB */
+ 9000, 700, /* MB<->WB */
13500, 1000, /* WB<->SWB */
14000, 2000, /* SWB<->FB */
};
static const opus_int32 mono_music_bandwidth_thresholds[8] = {
- 10000, 1000, /* NB<->MB */
- 11000, 1000, /* MB<->WB */
- 13500, 1000, /* WB<->SWB */
- 14000, 2000, /* SWB<->FB */
+ 9000, 700, /* NB<->MB */
+ 9000, 700, /* MB<->WB */
+ 11000, 1000, /* WB<->SWB */
+ 12000, 2000, /* SWB<->FB */
};
static const opus_int32 stereo_voice_bandwidth_thresholds[8] = {
- 10000, 1000, /* NB<->MB */
- 11000, 1000, /* MB<->WB */
+ 9000, 700, /* NB<->MB */
+ 9000, 700, /* MB<->WB */
13500, 1000, /* WB<->SWB */
14000, 2000, /* SWB<->FB */
};
static const opus_int32 stereo_music_bandwidth_thresholds[8] = {
- 10000, 1000, /* NB<->MB */
- 11000, 1000, /* MB<->WB */
- 13500, 1000, /* WB<->SWB */
- 14000, 2000, /* SWB<->FB */
+ 9000, 700, /* NB<->MB */
+ 9000, 700, /* MB<->WB */
+ 11000, 1000, /* WB<->SWB */
+ 12000, 2000, /* SWB<->FB */
};
/* Threshold bit-rates for switching between mono and stereo */
-static const opus_int32 stereo_voice_threshold = 24000;
-static const opus_int32 stereo_music_threshold = 24000;
+static const opus_int32 stereo_voice_threshold = 19000;
+static const opus_int32 stereo_music_threshold = 17000;
/* Threshold bit-rate for switching between SILK/hybrid and CELT-only */
static const opus_int32 mode_thresholds[2][2] = {
/* voice */ /* music */
- { 64000, 16000}, /* mono */
- { 36000, 16000}, /* stereo */
+ { 64000, 10000}, /* mono */
+ { 44000, 10000}, /* stereo */
};
static const opus_int32 fec_thresholds[] = {
int c, i;
int shift;
- /* Approximates -round(log2(4.*cutoff_Hz/Fs)) */
- shift=celt_ilog2(Fs/(cutoff_Hz*3));
+ /* Approximates -round(log2(6.3*cutoff_Hz/Fs)) */
+ shift=celt_ilog2(Fs/(cutoff_Hz*4));
for (c=0;c<channels;c++)
{
for (i=0;i<len;i++)
{
- opus_val32 x, tmp, y;
+ opus_val32 x, y;
x = SHL32(EXTEND32(in[channels*i+c]), 14);
- /* First stage */
- tmp = x-hp_mem[2*c];
+ y = x-hp_mem[2*c];
hp_mem[2*c] = hp_mem[2*c] + PSHR32(x - hp_mem[2*c], shift);
- /* Second stage */
- y = tmp - hp_mem[2*c+1];
- hp_mem[2*c+1] = hp_mem[2*c+1] + PSHR32(tmp - hp_mem[2*c+1], shift);
out[channels*i+c] = EXTRACT16(SATURATE(PSHR32(y, 14), 32767));
}
}
{
int i;
float coef, coef2;
- coef = 4.0f*cutoff_Hz/Fs;
+ coef = 6.3f*cutoff_Hz/Fs;
coef2 = 1-coef;
if (channels==2)
{
- float m0, m1, m2, m3;
+ float m0, m2;
m0 = hp_mem[0];
- m1 = hp_mem[1];
m2 = hp_mem[2];
- m3 = hp_mem[3];
for (i=0;i<len;i++)
{
- opus_val32 x0, x1, tmp0, tmp1, out0, out1;
+ opus_val32 x0, x1, out0, out1;
x0 = in[2*i+0];
x1 = in[2*i+1];
- /* First stage */
- tmp0 = x0-m0;
- tmp1 = x1-m2;
+ out0 = x0-m0;
+ out1 = x1-m2;
m0 = coef*x0 + VERY_SMALL + coef2*m0;
m2 = coef*x1 + VERY_SMALL + coef2*m2;
- /* Second stage */
- out0 = tmp0 - m1;
- out1 = tmp1 - m3;
- m1 = coef*tmp0 + VERY_SMALL + coef2*m1;
- m3 = coef*tmp1 + VERY_SMALL + coef2*m3;
out[2*i+0] = out0;
out[2*i+1] = out1;
}
hp_mem[0] = m0;
- hp_mem[1] = m1;
hp_mem[2] = m2;
- hp_mem[3] = m3;
} else {
- float m0, m1;
+ float m0;
m0 = hp_mem[0];
- m1 = hp_mem[1];
for (i=0;i<len;i++)
{
- opus_val32 x, tmp, y;
+ opus_val32 x, y;
x = in[i];
- /* First stage */
- tmp = x-m0;
+ y = x-m0;
m0 = coef*x + VERY_SMALL + coef2*m0;
- /* Second stage */
- y = tmp - m1;
- m1 = coef*tmp + VERY_SMALL + coef2*m1;
out[i] = y;
}
hp_mem[0] = m0;
- hp_mem[1] = m1;
}
}
#endif
xy += SHR32(pxy, 10);
yy += SHR32(pyy, 10);
}
+#ifndef FIXED_POINT
+ if (!(xx < 1e9f) || celt_isnan(xx) || !(yy < 1e9f) || celt_isnan(yy))
+ {
+ xy = xx = yy = 0;
+ }
+#endif
mem->XX += MULT16_32_Q15(short_alpha, xx-mem->XX);
mem->XY += MULT16_32_Q15(short_alpha, xy-mem->XY);
mem->YY += MULT16_32_Q15(short_alpha, yy-mem->YY);
return 0;
}
-static int compute_silk_rate_for_hybrid(int rate, int bandwidth, int frame20ms, int vbr, int fec) {
+static int compute_silk_rate_for_hybrid(int rate, int bandwidth, int frame20ms, int vbr, int fec, int channels) {
int entry;
int i;
int N;
{32000, 22000, 22000, 28000, 28000},
{64000, 38000, 38000, 50000, 50000}
};
+ /* Do the allocation per-channel. */
+ rate /= channels;
entry = 1 + frame20ms + 2*fec;
N = sizeof(rate_table)/sizeof(rate_table[0]);
for (i=1;i<N;i++)
}
if (bandwidth==OPUS_BANDWIDTH_SUPERWIDEBAND)
silk_rate += 300;
+ silk_rate *= channels;
+ /* Small adjustment for stereo (calibrated for 32 kb/s, haven't tried other bitrates). */
+ if (channels == 2 && rate >= 12000)
+ silk_rate -= 1000;
return silk_rate;
}
opus_int32 equiv;
equiv = bitrate;
/* Take into account overhead from smaller frames. */
- equiv -= (40*channels+20)*(frame_rate - 50);
+ if (frame_rate > 50)
+ equiv -= (40*channels+20)*(frame_rate - 50);
/* CBR is about a 8% penalty for both SILK and CELT. */
if (!vbr)
equiv -= equiv/12;
int arch
)
{
- int is_noise;
opus_val32 noise_energy;
- int is_sufficiently_quiet;
if (!is_silence)
{
- is_noise = activity_probability < DTX_ACTIVITY_THRESHOLD;
- if (is_noise)
+ if (activity_probability < DTX_ACTIVITY_THRESHOLD) /* is noise */
{
noise_energy = compute_frame_energy(pcm, frame_size, channels, arch);
- is_sufficiently_quiet = peak_signal_energy >= (PSEUDO_SNR_THRESHOLD * noise_energy);
+
+ /* but is sufficiently quiet */
+ is_silence = peak_signal_energy >= (PSEUDO_SNR_THRESHOLD * noise_energy);
}
}
- if (is_silence || (is_noise && is_sufficiently_quiet))
+ if (is_silence)
{
/* The number of consecutive DTX frames should be within the allowed bounds */
(*nb_no_activity_frames)++;
{
int analysis_bandwidth;
if (st->signal_type == OPUS_AUTO)
- st->voice_ratio = (int)floor(.5+100*(1-analysis_info.music_prob));
+ {
+ float prob;
+ if (st->prev_mode == 0)
+ prob = analysis_info.music_prob;
+ else if (st->prev_mode == MODE_CELT_ONLY)
+ prob = analysis_info.music_prob_max;
+ else
+ prob = analysis_info.music_prob_min;
+ st->voice_ratio = (int)floor(.5+100*(1-prob));
+ }
analysis_bandwidth = analysis_info.bandwidth;
if (analysis_bandwidth<=12)
if (equiv_rate >= threshold)
break;
} while (--bandwidth>OPUS_BANDWIDTH_NARROWBAND);
+ /* We don't use mediumband anymore, except when explicitly requested or during
+ mode transitions. */
+ if (bandwidth == OPUS_BANDWIDTH_MEDIUMBAND)
+ bandwidth = OPUS_BANDWIDTH_WIDEBAND;
st->bandwidth = st->auto_bandwidth = bandwidth;
/* Prevents any transition to SWB/FB until the SILK layer has fully
switched to WB mode and turned the variable LP filter off */
redundancy = 1;
celt_to_silk = 1;
st->silk_bw_switch = 0;
- prefill=1;
+ /* Do a prefill without reseting the sampling rate control. */
+ prefill=2;
}
/* If we decided to go with CELT, make sure redundancy is off, no matter what
if (st->mode != MODE_CELT_ONLY)
{
opus_int32 total_bitRate, celt_rate;
+ opus_int activity;
#ifdef FIXED_POINT
const opus_int16 *pcm_silk;
#else
ALLOC(pcm_silk, st->channels*frame_size, opus_int16);
#endif
+ activity = VAD_NO_DECISION;
+#ifndef DISABLE_FLOAT_API
+ if( analysis_info.valid ) {
+ /* Inform SILK about the Opus VAD decision */
+ activity = ( analysis_info.activity_probability >= DTX_ACTIVITY_THRESHOLD );
+ }
+#endif
+
/* Distribute bits between SILK and CELT */
total_bitRate = 8 * bytes_target * frame_rate;
if( st->mode == MODE_HYBRID ) {
/* Base rate for SILK */
st->silk_mode.bitRate = compute_silk_rate_for_hybrid(total_bitRate,
- curr_bandwidth, st->Fs == 50 * frame_size, st->use_vbr, st->silk_mode.LBRR_coded);
+ curr_bandwidth, st->Fs == 50 * frame_size, st->use_vbr, st->silk_mode.LBRR_coded,
+ st->stream_channels);
if (!st->energy_masking)
{
/* Increasingly attenuate high band when it gets allocated fewer bits */
} else if (curr_bandwidth == OPUS_BANDWIDTH_MEDIUMBAND) {
st->silk_mode.desiredInternalSampleRate = 12000;
} else {
- silk_assert( st->mode == MODE_HYBRID || curr_bandwidth == OPUS_BANDWIDTH_WIDEBAND );
+ celt_assert( st->mode == MODE_HYBRID || curr_bandwidth == OPUS_BANDWIDTH_WIDEBAND );
st->silk_mode.desiredInternalSampleRate = 16000;
}
if( st->mode == MODE_HYBRID ) {
{
/* Compute SILK bitrate corresponding to the max total bits available */
opus_int32 maxBitRate = compute_silk_rate_for_hybrid(st->silk_mode.maxBits*st->Fs / frame_size,
- curr_bandwidth, st->Fs == 50 * frame_size, st->use_vbr, st->silk_mode.LBRR_coded);
+ curr_bandwidth, st->Fs == 50 * frame_size, st->use_vbr, st->silk_mode.LBRR_coded,
+ st->stream_channels);
st->silk_mode.maxBits = maxBitRate * frame_size / st->Fs;
}
}
for (i=0;i<st->encoder_buffer*st->channels;i++)
pcm_silk[i] = FLOAT2INT16(st->delay_buffer[i]);
#endif
- silk_Encode( silk_enc, &st->silk_mode, pcm_silk, st->encoder_buffer, NULL, &zero, 1 );
+ silk_Encode( silk_enc, &st->silk_mode, pcm_silk, st->encoder_buffer, NULL, &zero, prefill, activity );
+ /* Prevent a second switch in the real encode call. */
+ st->silk_mode.opusCanSwitch = 0;
}
#ifdef FIXED_POINT
for (i=0;i<frame_size*st->channels;i++)
pcm_silk[i] = FLOAT2INT16(pcm_buf[total_buffer*st->channels + i]);
#endif
- ret = silk_Encode( silk_enc, &st->silk_mode, pcm_silk, frame_size, &enc, &nBytes, 0 );
+ ret = silk_Encode( silk_enc, &st->silk_mode, pcm_silk, frame_size, &enc, &nBytes, 0, activity );
if( ret ) {
/*fprintf (stderr, "SILK encode error: %d\n", ret);*/
/* Handle error */
curr_bandwidth = OPUS_BANDWIDTH_WIDEBAND;
}
} else {
- silk_assert( st->silk_mode.internalSampleRate == 16000 );
+ celt_assert( st->silk_mode.internalSampleRate == 16000 );
}
st->silk_mode.opusCanSwitch = st->silk_mode.switchReady && !st->nonfinal_frame;
}
st->prev_HB_gain = HB_gain;
if (st->mode != MODE_HYBRID || st->stream_channels==1)
- st->silk_mode.stereoWidth_Q14 = IMIN((1<<14),2*IMAX(0,equiv_rate-24000));
+ {
+ if (equiv_rate > 32000)
+ st->silk_mode.stereoWidth_Q14 = 16384;
+ else if (equiv_rate < 16000)
+ st->silk_mode.stereoWidth_Q14 = 0;
+ else
+ st->silk_mode.stereoWidth_Q14 = 16384 - 2048*(opus_int32)(32000-equiv_rate)/(equiv_rate-14000);
+ }
if( !st->energy_masking && st->channels == 2 ) {
/* Apply stereo width reduction (at low bitrates) */
if( st->hybrid_stereo_width_Q14 < (1 << 14) || st->silk_mode.stereoWidth_Q14 < (1 << 14) ) {
info.signalType = st->silk_mode.signalType;
info.offset = st->silk_mode.offset;
celt_encoder_ctl(celt_enc, CELT_SET_SILK_INFO(&info));
- } else {
- celt_encoder_ctl(celt_enc, CELT_SET_SILK_INFO((SILKInfo*)NULL));
}
/* 5 ms redundant frame for CELT->SILK */
#include "float_cast.h"
#include "os_support.h"
-struct OpusMSDecoder {
- ChannelLayout layout;
- /* Decoder states go here */
-};
-
-
+/* DECODER */
+#if defined(ENABLE_HARDENING) || defined(ENABLE_ASSERTIONS)
+static void validate_ms_decoder(OpusMSDecoder *st)
+{
+ validate_layout(&st->layout);
+}
+#define VALIDATE_MS_DECODER(st) validate_ms_decoder(st)
+#else
+#define VALIDATE_MS_DECODER(st)
+#endif
-/* DECODER */
opus_int32 opus_multistream_decoder_get_size(int nb_streams, int nb_coupled_streams)
{
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)
{
return samples;
}
-static int opus_multistream_decode_native(
+int opus_multistream_decode_native(
OpusMSDecoder *st,
const unsigned char *data,
opus_int32 len,
opus_copy_channel_out_func copy_channel_out,
int frame_size,
int decode_fec,
- int soft_clip
+ int soft_clip,
+ void *user_data
)
{
opus_int32 Fs;
VARDECL(opus_val16, buf);
ALLOC_STACK;
+ VALIDATE_MS_DECODER(st);
+ if (frame_size <= 0)
+ {
+ RESTORE_STACK;
+ return OPUS_BAD_ARG;
+ }
/* Limit frame_size to avoid excessive stack allocations. */
- opus_multistream_decoder_ctl(st, OPUS_GET_SAMPLE_RATE(&Fs));
+ MUST_SUCCEED(opus_multistream_decoder_ctl(st, OPUS_GET_SAMPLE_RATE(&Fs)));
frame_size = IMIN(frame_size, Fs/25*3);
ALLOC(buf, 2*frame_size, opus_val16);
ptr = (char*)st + align(sizeof(OpusMSDecoder));
while ( (chan = get_left_channel(&st->layout, s, prev)) != -1)
{
(*copy_channel_out)(pcm, st->layout.nb_channels, chan,
- buf, 2, frame_size);
+ buf, 2, frame_size, user_data);
prev = chan;
}
prev = -1;
while ( (chan = get_right_channel(&st->layout, s, prev)) != -1)
{
(*copy_channel_out)(pcm, st->layout.nb_channels, chan,
- buf+1, 2, frame_size);
+ buf+1, 2, frame_size, user_data);
prev = chan;
}
} else {
while ( (chan = get_mono_channel(&st->layout, s, prev)) != -1)
{
(*copy_channel_out)(pcm, st->layout.nb_channels, chan,
- buf, 1, frame_size);
+ buf, 1, frame_size, user_data);
prev = chan;
}
}
if (st->layout.mapping[c] == 255)
{
(*copy_channel_out)(pcm, st->layout.nb_channels, c,
- NULL, 0, frame_size);
+ NULL, 0, frame_size, user_data);
}
}
RESTORE_STACK;
int dst_channel,
const opus_val16 *src,
int src_stride,
- int frame_size
+ int frame_size,
+ void *user_data
)
{
float *float_dst;
opus_int32 i;
+ (void)user_data;
float_dst = (float*)dst;
if (src != NULL)
{
int dst_channel,
const opus_val16 *src,
int src_stride,
- int frame_size
+ int frame_size,
+ void *user_data
)
{
opus_int16 *short_dst;
opus_int32 i;
+ (void)user_data;
short_dst = (opus_int16*)dst;
if (src != NULL)
{
)
{
return opus_multistream_decode_native(st, data, len,
- pcm, opus_copy_channel_out_short, frame_size, decode_fec, 0);
+ pcm, opus_copy_channel_out_short, frame_size, decode_fec, 0, NULL);
}
#ifndef DISABLE_FLOAT_API
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);
+ pcm, opus_copy_channel_out_float, frame_size, decode_fec, 0, NULL);
}
#endif
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);
+ pcm, opus_copy_channel_out_short, frame_size, decode_fec, 1, NULL);
}
int opus_multistream_decode_float(
OpusMSDecoder *st,
const unsigned char *data,
opus_int32 len,
- float *pcm,
+ opus_val16 *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);
+ pcm, opus_copy_channel_out_float, frame_size, decode_fec, 0, NULL);
}
#endif
-int opus_multistream_decoder_ctl(OpusMSDecoder *st, int request, ...)
+int opus_multistream_decoder_ctl_va_list(OpusMSDecoder *st, int request,
+ va_list ap)
{
- 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));
ret = OPUS_UNIMPLEMENTED;
break;
}
-
- va_end(ap);
return ret;
bad_arg:
- va_end(ap);
return OPUS_BAD_ARG;
}
+int opus_multistream_decoder_ctl(OpusMSDecoder *st, int request, ...)
+{
+ int ret;
+ va_list ap;
+ va_start(ap, request);
+ ret = opus_multistream_decoder_ctl_va_list(st, request, ap);
+ va_end(ap);
+ return ret;
+}
void opus_multistream_decoder_destroy(OpusMSDecoder *st)
{
{5, 3, {0, 6, 1, 2, 3, 4, 5, 7}}, /* 8: 7.1 surround */
};
-typedef void (*opus_copy_channel_in_func)(
- opus_val16 *dst,
- int dst_stride,
- const void *src,
- int src_stride,
- int src_channel,
- int frame_size
-);
-
-typedef enum {
- MAPPING_TYPE_NONE,
- MAPPING_TYPE_SURROUND
-#ifdef ENABLE_EXPERIMENTAL_AMBISONICS
- , /* Do not include comma at end of enumerator list */
- MAPPING_TYPE_AMBISONICS
-#endif
-} MappingType;
-
-struct OpusMSEncoder {
- ChannelLayout layout;
- int arch;
- int lfe_stream;
- int application;
- int variable_duration;
- MappingType mapping_type;
- opus_int32 bitrate_bps;
- /* Encoder states go here */
- /* then opus_val32 window_mem[channels*120]; */
- /* then opus_val32 preemph_mem[channels]; */
-};
-
static opus_val32 *ms_get_preemph_mem(OpusMSEncoder *st)
{
int s;
return (opus_val32*)(void*)ptr;
}
-#ifdef ENABLE_EXPERIMENTAL_AMBISONICS
static int validate_ambisonics(int nb_channels, int *nb_streams, int *nb_coupled_streams)
{
int order_plus_one;
int acn_channels;
int nondiegetic_channels;
+ if (nb_channels < 1 || nb_channels > 227)
+ return 0;
+
order_plus_one = isqrt32(nb_channels);
acn_channels = order_plus_one * order_plus_one;
nondiegetic_channels = nb_channels - acn_channels;
- if (order_plus_one < 1 || order_plus_one > 15 ||
- (nondiegetic_channels != 0 && nondiegetic_channels != 2))
+ if (nondiegetic_channels != 0 && nondiegetic_channels != 2)
return 0;
if (nb_streams)
*nb_coupled_streams = nondiegetic_channels != 0;
return 1;
}
-#endif
static int validate_encoder_layout(const ChannelLayout *layout)
{
int nb_frames = frame_size/freq_size;
celt_assert(nb_frames*freq_size == frame_size);
OPUS_COPY(in, mem+c*overlap, overlap);
- (*copy_channel_in)(x, 1, pcm, channels, c, len);
+ (*copy_channel_in)(x, 1, pcm, channels, c, len, NULL);
celt_preemphasis(x, in+overlap, frame_size, 1, upsample, celt_mode->preemph, preemph_mem+c, 0);
#ifndef FIXED_POINT
{
{
nb_streams=channels;
nb_coupled_streams=0;
-#ifdef ENABLE_EXPERIMENTAL_AMBISONICS
- } else if (mapping_family==254)
+ } else if (mapping_family==2)
{
if (!validate_ambisonics(channels, &nb_streams, &nb_coupled_streams))
return 0;
-#endif
} else
return 0;
size = opus_multistream_encoder_get_size(nb_streams, nb_coupled_streams);
if (mapping_type == MAPPING_TYPE_SURROUND &&
!validate_encoder_layout(&st->layout))
return OPUS_BAD_ARG;
-#ifdef ENABLE_EXPERIMENTAL_AMBISONICS
if (mapping_type == MAPPING_TYPE_AMBISONICS &&
!validate_ambisonics(st->layout.nb_channels, NULL, NULL))
return OPUS_BAD_ARG;
-#endif
ptr = (char*)st + align(sizeof(OpusMSEncoder));
coupled_size = opus_encoder_get_size(2);
mono_size = opus_encoder_get_size(1);
*coupled_streams=0;
for(i=0;i<channels;i++)
mapping[i] = i;
-#ifdef ENABLE_EXPERIMENTAL_AMBISONICS
- } else if (mapping_family==254)
+ } else if (mapping_family==2)
{
int i;
if (!validate_ambisonics(channels, streams, coupled_streams))
mapping[i] = i + (*coupled_streams * 2);
for(i = 0; i < *coupled_streams * 2; i++)
mapping[i + (*streams - *coupled_streams)] = i;
-#endif
} else
return OPUS_UNIMPLEMENTED;
if (channels>2 && mapping_family==1) {
mapping_type = MAPPING_TYPE_SURROUND;
-#ifdef ENABLE_EXPERIMENTAL_AMBISONICS
- } else if (mapping_family==254)
+ } else if (mapping_family==2)
{
mapping_type = MAPPING_TYPE_AMBISONICS;
-#endif
} else
{
mapping_type = MAPPING_TYPE_NONE;
}
}
-#ifdef ENABLE_EXPERIMENTAL_AMBISONICS
static void ambisonics_rate_allocation(
OpusMSEncoder *st,
opus_int32 *rate,
)
{
int i;
- int total_rate;
- int directional_rate;
- int nondirectional_rate;
- int leftover_bits;
-
- /* Each nondirectional channel gets (rate_ratio_num / rate_ratio_den) times
- * as many bits as all other ambisonics channels.
- */
- const int rate_ratio_num = 4;
- const int rate_ratio_den = 3;
+ opus_int32 total_rate;
+ opus_int32 per_stream_rate;
+
const int nb_channels = st->layout.nb_streams + st->layout.nb_coupled_streams;
- const int nb_nondirectional_channels = st->layout.nb_coupled_streams * 2 + 1;
- const int nb_directional_channels = st->layout.nb_streams - 1;
if (st->bitrate_bps==OPUS_AUTO)
{
total_rate = (st->layout.nb_coupled_streams + st->layout.nb_streams) *
- (Fs+60*Fs/frame_size) + st->layout.nb_streams * 15000;
+ (Fs+60*Fs/frame_size) + st->layout.nb_streams * (opus_int32)15000;
} else if (st->bitrate_bps==OPUS_BITRATE_MAX)
{
total_rate = nb_channels * 320000;
total_rate = st->bitrate_bps;
}
- /* Let y be the directional rate, m be the num of nondirectional channels
- * m = (s + 1)
- * and let p, q be integers such that the nondirectional rate is
- * m_rate = (p / q) * y
- * Also let T be the total bitrate to allocate. Then
- * T = (n - m) * y + m * m_rate
- * Solving for y,
- * y = (q * T) / (m * (p - q) + n * q)
- */
- directional_rate =
- total_rate * rate_ratio_den
- / (nb_nondirectional_channels * (rate_ratio_num - rate_ratio_den)
- + nb_channels * rate_ratio_den);
-
- /* Calculate the nondirectional rate.
- * m_rate = y * (p / q)
- */
- nondirectional_rate = directional_rate * rate_ratio_num / rate_ratio_den;
-
- /* Calculate the leftover from truncation error.
- * leftover = T - y * (n - m) - m_rate * m
- * Place leftover bits in omnidirectional channel.
- */
- leftover_bits = total_rate
- - directional_rate * nb_directional_channels
- - nondirectional_rate * nb_nondirectional_channels;
-
- /* Calculate rates for each channel */
+ /* Allocate equal number of bits to Ambisonic (uncoupled) and non-diegetic
+ * (coupled) streams */
+ per_stream_rate = total_rate / st->layout.nb_streams;
for (i = 0; i < st->layout.nb_streams; i++)
{
- if (i < st->layout.nb_coupled_streams)
- {
- rate[i] = nondirectional_rate * 2;
- } else if (i == st->layout.nb_coupled_streams)
- {
- rate[i] = nondirectional_rate + leftover_bits;
- } else
- {
- rate[i] = directional_rate;
- }
+ rate[i] = per_stream_rate;
}
}
-#endif /* ENABLE_EXPERIMENTAL_AMBISONICS */
static opus_int32 rate_allocation(
OpusMSEncoder *st,
ptr = (char*)st + align(sizeof(OpusMSEncoder));
opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_SAMPLE_RATE(&Fs));
-#ifdef ENABLE_EXPERIMENTAL_AMBISONICS
if (st->mapping_type == MAPPING_TYPE_AMBISONICS) {
ambisonics_rate_allocation(st, rate, frame_size, Fs);
} else
-#endif
{
surround_rate_allocation(st, rate, frame_size, Fs);
}
/* Max size in case the encoder decides to return six frames (6 x 20 ms = 120 ms) */
#define MS_FRAME_TMP (6*1275+12)
-static int opus_multistream_encode_native
+int opus_multistream_encode_native
(
OpusMSEncoder *st,
opus_copy_channel_in_func copy_channel_in,
opus_int32 max_data_bytes,
int lsb_depth,
downmix_func downmix,
- int float_api
+ int float_api,
+ void *user_data
)
{
opus_int32 Fs;
opus_encoder_ctl(enc, OPUS_SET_FORCE_CHANNELS(2));
}
}
-#ifdef ENABLE_EXPERIMENTAL_AMBISONICS
else if (st->mapping_type == MAPPING_TYPE_AMBISONICS) {
opus_encoder_ctl(enc, OPUS_SET_FORCE_MODE(MODE_CELT_ONLY));
}
-#endif
}
ptr = (char*)st + align(sizeof(OpusMSEncoder));
left = get_left_channel(&st->layout, s, -1);
right = get_right_channel(&st->layout, s, -1);
(*copy_channel_in)(buf, 2,
- pcm, st->layout.nb_channels, left, frame_size);
+ pcm, st->layout.nb_channels, left, frame_size, user_data);
(*copy_channel_in)(buf+1, 2,
- pcm, st->layout.nb_channels, right, frame_size);
+ pcm, st->layout.nb_channels, right, frame_size, user_data);
ptr += align(coupled_size);
if (st->mapping_type == MAPPING_TYPE_SURROUND)
{
int i;
int chan = get_mono_channel(&st->layout, s, -1);
(*copy_channel_in)(buf, 1,
- pcm, st->layout.nb_channels, chan, frame_size);
+ pcm, st->layout.nb_channels, chan, frame_size, user_data);
ptr += align(mono_size);
if (st->mapping_type == MAPPING_TYPE_SURROUND)
{
const void *src,
int src_stride,
int src_channel,
- int frame_size
+ int frame_size,
+ void *user_data
)
{
const float *float_src;
opus_int32 i;
+ (void)user_data;
float_src = (const float *)src;
for (i=0;i<frame_size;i++)
#if defined(FIXED_POINT)
const void *src,
int src_stride,
int src_channel,
- int frame_size
+ int frame_size,
+ void *user_data
)
{
const opus_int16 *short_src;
opus_int32 i;
+ (void)user_data;
short_src = (const opus_int16 *)src;
for (i=0;i<frame_size;i++)
#if defined(FIXED_POINT)
)
{
return opus_multistream_encode_native(st, opus_copy_channel_in_short,
- pcm, frame_size, data, max_data_bytes, 16, downmix_int, 0);
+ pcm, frame_size, data, max_data_bytes, 16, downmix_int, 0, NULL);
}
#ifndef DISABLE_FLOAT_API
)
{
return opus_multistream_encode_native(st, opus_copy_channel_in_float,
- pcm, frame_size, data, max_data_bytes, 16, downmix_float, 1);
+ pcm, frame_size, data, max_data_bytes, 16, downmix_float, 1, NULL);
}
#endif
)
{
return opus_multistream_encode_native(st, opus_copy_channel_in_float,
- pcm, frame_size, data, max_data_bytes, 24, downmix_float, 1);
+ pcm, frame_size, data, max_data_bytes, 24, downmix_float, 1, NULL);
}
int opus_multistream_encode(
)
{
return opus_multistream_encode_native(st, opus_copy_channel_in_short,
- pcm, frame_size, data, max_data_bytes, 16, downmix_int, 0);
+ pcm, frame_size, data, max_data_bytes, 16, downmix_int, 0, NULL);
}
#endif
-int opus_multistream_encoder_ctl(OpusMSEncoder *st, int request, ...)
+int opus_multistream_encoder_ctl_va_list(OpusMSEncoder *st, int request,
+ va_list ap)
{
- va_list ap;
int coupled_size, mono_size;
char *ptr;
int ret = OPUS_OK;
- va_start(ap, request);
-
coupled_size = opus_encoder_get_size(2);
mono_size = opus_encoder_get_size(1);
ptr = (char*)st + align(sizeof(OpusMSEncoder));
ret = OPUS_UNIMPLEMENTED;
break;
}
-
- va_end(ap);
return ret;
bad_arg:
- va_end(ap);
return OPUS_BAD_ARG;
}
+int opus_multistream_encoder_ctl(OpusMSEncoder *st, int request, ...)
+{
+ int ret;
+ va_list ap;
+ va_start(ap, request);
+ ret = opus_multistream_encoder_ctl_va_list(st, request, ap);
+ va_end(ap);
+ return ret;
+}
+
void opus_multistream_encoder_destroy(OpusMSEncoder *st)
{
opus_free(st);
#include "opus.h"
#include "celt.h"
+#include <stdarg.h> /* va_list */
#include <stddef.h> /* offsetof */
struct OpusRepacketizer {
unsigned char mapping[256];
} ChannelLayout;
+typedef enum {
+ MAPPING_TYPE_NONE,
+ MAPPING_TYPE_SURROUND,
+ MAPPING_TYPE_AMBISONICS
+} MappingType;
+
+struct OpusMSEncoder {
+ ChannelLayout layout;
+ int arch;
+ int lfe_stream;
+ int application;
+ int variable_duration;
+ MappingType mapping_type;
+ opus_int32 bitrate_bps;
+ /* Encoder states go here */
+ /* then opus_val32 window_mem[channels*120]; */
+ /* then opus_val32 preemph_mem[channels]; */
+};
+
+struct OpusMSDecoder {
+ ChannelLayout layout;
+ /* Decoder states go here */
+};
+
+int opus_multistream_encoder_ctl_va_list(struct OpusMSEncoder *st, int request,
+ va_list ap);
+int opus_multistream_decoder_ctl_va_list(struct OpusMSDecoder *st, int request,
+ va_list ap);
+
int validate_layout(const ChannelLayout *layout);
int get_left_channel(const ChannelLayout *layout, int stream_id, int prev);
int get_right_channel(const ChannelLayout *layout, int stream_id, int prev);
int get_mono_channel(const ChannelLayout *layout, int stream_id, int prev);
-
+typedef void (*opus_copy_channel_in_func)(
+ opus_val16 *dst,
+ int dst_stride,
+ const void *src,
+ int src_stride,
+ int src_channel,
+ int frame_size,
+ void *user_data
+);
+
+typedef void (*opus_copy_channel_out_func)(
+ void *dst,
+ int dst_stride,
+ int dst_channel,
+ const opus_val16 *src,
+ int src_stride,
+ int frame_size,
+ void *user_data
+);
#define MODE_SILK_ONLY 1000
#define MODE_HYBRID 1001
int pad_frame(unsigned char *data, opus_int32 len, opus_int32 new_len);
+int opus_multistream_encode_native
+(
+ struct OpusMSEncoder *st,
+ opus_copy_channel_in_func copy_channel_in,
+ const void *pcm,
+ int analysis_frame_size,
+ unsigned char *data,
+ opus_int32 max_data_bytes,
+ int lsb_depth,
+ downmix_func downmix,
+ int float_api,
+ void *user_data
+);
+
+int opus_multistream_decode_native(
+ struct OpusMSDecoder *st,
+ const unsigned char *data,
+ opus_int32 len,
+ void *pcm,
+ opus_copy_channel_out_func copy_channel_out,
+ int frame_size,
+ int decode_fec,
+ int soft_clip,
+ void *user_data
+);
+
#endif /* OPUS_PRIVATE_H */
--- /dev/null
+/* Copyright (c) 2017 Google Inc.
+ Written by Andrew Allen */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "mathops.h"
+#include "os_support.h"
+#include "opus_private.h"
+#include "opus_defines.h"
+#include "opus_projection.h"
+#include "opus_multistream.h"
+#include "mapping_matrix.h"
+#include "stack_alloc.h"
+
+struct OpusProjectionDecoder
+{
+ opus_int32 demixing_matrix_size_in_bytes;
+ /* Encoder states go here */
+};
+
+#if !defined(DISABLE_FLOAT_API)
+static void opus_projection_copy_channel_out_float(
+ void *dst,
+ int dst_stride,
+ int dst_channel,
+ const opus_val16 *src,
+ int src_stride,
+ int frame_size,
+ void *user_data)
+{
+ float *float_dst;
+ const MappingMatrix *matrix;
+ float_dst = (float *)dst;
+ matrix = (const MappingMatrix *)user_data;
+
+ if (dst_channel == 0)
+ OPUS_CLEAR(float_dst, frame_size * dst_stride);
+
+ if (src != NULL)
+ mapping_matrix_multiply_channel_out_float(matrix, src, dst_channel,
+ src_stride, float_dst, dst_stride, frame_size);
+}
+#endif
+
+static void opus_projection_copy_channel_out_short(
+ void *dst,
+ int dst_stride,
+ int dst_channel,
+ const opus_val16 *src,
+ int src_stride,
+ int frame_size,
+ void *user_data)
+{
+ opus_int16 *short_dst;
+ const MappingMatrix *matrix;
+ short_dst = (opus_int16 *)dst;
+ matrix = (const MappingMatrix *)user_data;
+ if (dst_channel == 0)
+ OPUS_CLEAR(short_dst, frame_size * dst_stride);
+
+ if (src != NULL)
+ mapping_matrix_multiply_channel_out_short(matrix, src, dst_channel,
+ src_stride, short_dst, dst_stride, frame_size);
+}
+
+static MappingMatrix *get_dec_demixing_matrix(OpusProjectionDecoder *st)
+{
+ /* void* cast avoids clang -Wcast-align warning */
+ return (MappingMatrix*)(void*)((char*)st +
+ align(sizeof(OpusProjectionDecoder)));
+}
+
+static OpusMSDecoder *get_multistream_decoder(OpusProjectionDecoder *st)
+{
+ /* void* cast avoids clang -Wcast-align warning */
+ return (OpusMSDecoder*)(void*)((char*)st +
+ align(sizeof(OpusProjectionDecoder) +
+ st->demixing_matrix_size_in_bytes));
+}
+
+opus_int32 opus_projection_decoder_get_size(int channels, int streams,
+ int coupled_streams)
+{
+ opus_int32 matrix_size;
+ opus_int32 decoder_size;
+
+ matrix_size =
+ mapping_matrix_get_size(streams + coupled_streams, channels);
+ if (!matrix_size)
+ return 0;
+
+ decoder_size = opus_multistream_decoder_get_size(streams, coupled_streams);
+ if (!decoder_size)
+ return 0;
+
+ return align(sizeof(OpusProjectionDecoder)) + matrix_size + decoder_size;
+}
+
+int opus_projection_decoder_init(OpusProjectionDecoder *st, opus_int32 Fs,
+ int channels, int streams, int coupled_streams,
+ unsigned char *demixing_matrix, opus_int32 demixing_matrix_size)
+{
+ int nb_input_streams;
+ opus_int32 expected_matrix_size;
+ int i, ret;
+ unsigned char mapping[255];
+ VARDECL(opus_int16, buf);
+ ALLOC_STACK;
+
+ /* Verify supplied matrix size. */
+ nb_input_streams = streams + coupled_streams;
+ expected_matrix_size = nb_input_streams * channels * sizeof(opus_int16);
+ if (expected_matrix_size != demixing_matrix_size)
+ {
+ RESTORE_STACK;
+ return OPUS_BAD_ARG;
+ }
+
+ /* Convert demixing matrix input into internal format. */
+ ALLOC(buf, nb_input_streams * channels, opus_int16);
+ for (i = 0; i < nb_input_streams * channels; i++)
+ {
+ int s = demixing_matrix[2*i + 1] << 8 | demixing_matrix[2*i];
+ s = ((s & 0xFFFF) ^ 0x8000) - 0x8000;
+ buf[i] = (opus_int16)s;
+ }
+
+ /* Assign demixing matrix. */
+ st->demixing_matrix_size_in_bytes =
+ mapping_matrix_get_size(channels, nb_input_streams);
+ if (!st->demixing_matrix_size_in_bytes)
+ {
+ RESTORE_STACK;
+ return OPUS_BAD_ARG;
+ }
+
+ mapping_matrix_init(get_dec_demixing_matrix(st), channels, nb_input_streams, 0,
+ buf, demixing_matrix_size);
+
+ /* Set trivial mapping so each input channel pairs with a matrix column. */
+ for (i = 0; i < channels; i++)
+ mapping[i] = i;
+
+ ret = opus_multistream_decoder_init(
+ get_multistream_decoder(st), Fs, channels, streams, coupled_streams, mapping);
+ RESTORE_STACK;
+ return ret;
+}
+
+OpusProjectionDecoder *opus_projection_decoder_create(
+ opus_int32 Fs, int channels, int streams, int coupled_streams,
+ unsigned char *demixing_matrix, opus_int32 demixing_matrix_size, int *error)
+{
+ int size;
+ int ret;
+ OpusProjectionDecoder *st;
+
+ /* Allocate space for the projection decoder. */
+ size = opus_projection_decoder_get_size(channels, streams, coupled_streams);
+ if (!size) {
+ if (error)
+ *error = OPUS_ALLOC_FAIL;
+ return NULL;
+ }
+ st = (OpusProjectionDecoder *)opus_alloc(size);
+ if (!st)
+ {
+ if (error)
+ *error = OPUS_ALLOC_FAIL;
+ return NULL;
+ }
+
+ /* Initialize projection decoder with provided settings. */
+ ret = opus_projection_decoder_init(st, Fs, channels, streams, coupled_streams,
+ demixing_matrix, demixing_matrix_size);
+ if (ret != OPUS_OK)
+ {
+ opus_free(st);
+ st = NULL;
+ }
+ if (error)
+ *error = ret;
+ return st;
+}
+
+#ifdef FIXED_POINT
+int opus_projection_decode(OpusProjectionDecoder *st, const unsigned char *data,
+ opus_int32 len, opus_int16 *pcm, int frame_size,
+ int decode_fec)
+{
+ return opus_multistream_decode_native(get_multistream_decoder(st), data, len,
+ pcm, opus_projection_copy_channel_out_short, frame_size, decode_fec, 0,
+ get_dec_demixing_matrix(st));
+}
+#else
+int opus_projection_decode(OpusProjectionDecoder *st, const unsigned char *data,
+ opus_int32 len, opus_int16 *pcm, int frame_size,
+ int decode_fec)
+{
+ return opus_multistream_decode_native(get_multistream_decoder(st), data, len,
+ pcm, opus_projection_copy_channel_out_short, frame_size, decode_fec, 1,
+ get_dec_demixing_matrix(st));
+}
+#endif
+
+#ifndef DISABLE_FLOAT_API
+int opus_projection_decode_float(OpusProjectionDecoder *st, const unsigned char *data,
+ opus_int32 len, float *pcm, int frame_size, int decode_fec)
+{
+ return opus_multistream_decode_native(get_multistream_decoder(st), data, len,
+ pcm, opus_projection_copy_channel_out_float, frame_size, decode_fec, 0,
+ get_dec_demixing_matrix(st));
+}
+#endif
+
+int opus_projection_decoder_ctl(OpusProjectionDecoder *st, int request, ...)
+{
+ va_list ap;
+ int ret = OPUS_OK;
+
+ va_start(ap, request);
+ ret = opus_multistream_decoder_ctl_va_list(get_multistream_decoder(st),
+ request, ap);
+ va_end(ap);
+ return ret;
+}
+
+void opus_projection_decoder_destroy(OpusProjectionDecoder *st)
+{
+ opus_free(st);
+}
+
--- /dev/null
+/* Copyright (c) 2017 Google Inc.
+ Written by Andrew Allen */
+/*
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "mathops.h"
+#include "os_support.h"
+#include "opus_private.h"
+#include "opus_defines.h"
+#include "opus_projection.h"
+#include "opus_multistream.h"
+#include "stack_alloc.h"
+#include "mapping_matrix.h"
+
+struct OpusProjectionEncoder
+{
+ opus_int32 mixing_matrix_size_in_bytes;
+ opus_int32 demixing_matrix_size_in_bytes;
+ /* Encoder states go here */
+};
+
+#if !defined(DISABLE_FLOAT_API)
+static void opus_projection_copy_channel_in_float(
+ opus_val16 *dst,
+ int dst_stride,
+ const void *src,
+ int src_stride,
+ int src_channel,
+ int frame_size,
+ void *user_data
+)
+{
+ mapping_matrix_multiply_channel_in_float((const MappingMatrix*)user_data,
+ (const float*)src, src_stride, dst, src_channel, dst_stride, frame_size);
+}
+#endif
+
+static void opus_projection_copy_channel_in_short(
+ opus_val16 *dst,
+ int dst_stride,
+ const void *src,
+ int src_stride,
+ int src_channel,
+ int frame_size,
+ void *user_data
+)
+{
+ mapping_matrix_multiply_channel_in_short((const MappingMatrix*)user_data,
+ (const opus_int16*)src, src_stride, dst, src_channel, dst_stride, frame_size);
+}
+
+static int get_order_plus_one_from_channels(int channels, int *order_plus_one)
+{
+ int order_plus_one_;
+ int acn_channels;
+ int nondiegetic_channels;
+
+ /* Allowed numbers of channels:
+ * (1 + n)^2 + 2j, for n = 0...14 and j = 0 or 1.
+ */
+ if (channels < 1 || channels > 227)
+ return OPUS_BAD_ARG;
+
+ order_plus_one_ = isqrt32(channels);
+ acn_channels = order_plus_one_ * order_plus_one_;
+ nondiegetic_channels = channels - acn_channels;
+ if (nondiegetic_channels != 0 && nondiegetic_channels != 2)
+ return OPUS_BAD_ARG;
+
+ if (order_plus_one)
+ *order_plus_one = order_plus_one_;
+ return OPUS_OK;
+}
+
+static int get_streams_from_channels(int channels, int mapping_family,
+ int *streams, int *coupled_streams,
+ int *order_plus_one)
+{
+ if (mapping_family == 3)
+ {
+ if (get_order_plus_one_from_channels(channels, order_plus_one) != OPUS_OK)
+ return OPUS_BAD_ARG;
+ if (streams)
+ *streams = (channels + 1) / 2;
+ if (coupled_streams)
+ *coupled_streams = channels / 2;
+ return OPUS_OK;
+ }
+ return OPUS_BAD_ARG;
+}
+
+static MappingMatrix *get_mixing_matrix(OpusProjectionEncoder *st)
+{
+ /* void* cast avoids clang -Wcast-align warning */
+ return (MappingMatrix *)(void*)((char*)st +
+ align(sizeof(OpusProjectionEncoder)));
+}
+
+static MappingMatrix *get_enc_demixing_matrix(OpusProjectionEncoder *st)
+{
+ /* void* cast avoids clang -Wcast-align warning */
+ return (MappingMatrix *)(void*)((char*)st +
+ align(sizeof(OpusProjectionEncoder) +
+ st->mixing_matrix_size_in_bytes));
+}
+
+static OpusMSEncoder *get_multistream_encoder(OpusProjectionEncoder *st)
+{
+ /* void* cast avoids clang -Wcast-align warning */
+ return (OpusMSEncoder *)(void*)((char*)st +
+ align(sizeof(OpusProjectionEncoder) +
+ st->mixing_matrix_size_in_bytes +
+ st->demixing_matrix_size_in_bytes));
+}
+
+opus_int32 opus_projection_ambisonics_encoder_get_size(int channels,
+ int mapping_family)
+{
+ int nb_streams;
+ int nb_coupled_streams;
+ int order_plus_one;
+ int mixing_matrix_rows, mixing_matrix_cols;
+ int demixing_matrix_rows, demixing_matrix_cols;
+ opus_int32 mixing_matrix_size, demixing_matrix_size;
+ opus_int32 encoder_size;
+ int ret;
+
+ ret = get_streams_from_channels(channels, mapping_family, &nb_streams,
+ &nb_coupled_streams, &order_plus_one);
+ if (ret != OPUS_OK)
+ return 0;
+
+ if (order_plus_one == 2)
+ {
+ mixing_matrix_rows = mapping_matrix_foa_mixing.rows;
+ mixing_matrix_cols = mapping_matrix_foa_mixing.cols;
+ demixing_matrix_rows = mapping_matrix_foa_demixing.rows;
+ demixing_matrix_cols = mapping_matrix_foa_demixing.cols;
+ }
+ else if (order_plus_one == 3)
+ {
+ mixing_matrix_rows = mapping_matrix_soa_mixing.rows;
+ mixing_matrix_cols = mapping_matrix_soa_mixing.cols;
+ demixing_matrix_rows = mapping_matrix_soa_demixing.rows;
+ demixing_matrix_cols = mapping_matrix_soa_demixing.cols;
+ }
+ else if (order_plus_one == 4)
+ {
+ mixing_matrix_rows = mapping_matrix_toa_mixing.rows;
+ mixing_matrix_cols = mapping_matrix_toa_mixing.cols;
+ demixing_matrix_rows = mapping_matrix_toa_demixing.rows;
+ demixing_matrix_cols = mapping_matrix_toa_demixing.cols;
+ }
+ else
+ return 0;
+
+ mixing_matrix_size =
+ mapping_matrix_get_size(mixing_matrix_rows, mixing_matrix_cols);
+ if (!mixing_matrix_size)
+ return 0;
+
+ demixing_matrix_size =
+ mapping_matrix_get_size(demixing_matrix_rows, demixing_matrix_cols);
+ if (!demixing_matrix_size)
+ return 0;
+
+ encoder_size =
+ opus_multistream_encoder_get_size(nb_streams, nb_coupled_streams);
+ if (!encoder_size)
+ return 0;
+
+ return align(sizeof(OpusProjectionEncoder)) +
+ mixing_matrix_size + demixing_matrix_size + encoder_size;
+}
+
+int opus_projection_ambisonics_encoder_init(OpusProjectionEncoder *st, opus_int32 Fs,
+ int channels, int mapping_family,
+ int *streams, int *coupled_streams,
+ int application)
+{
+ MappingMatrix *mixing_matrix;
+ MappingMatrix *demixing_matrix;
+ OpusMSEncoder *ms_encoder;
+ int i;
+ int ret;
+ int order_plus_one;
+ unsigned char mapping[255];
+
+ if (streams == NULL || coupled_streams == NULL) {
+ return OPUS_BAD_ARG;
+ }
+
+ if (get_streams_from_channels(channels, mapping_family, streams,
+ coupled_streams, &order_plus_one) != OPUS_OK)
+ return OPUS_BAD_ARG;
+
+ if (mapping_family == 3)
+ {
+ /* Assign mixing matrix based on available pre-computed matrices. */
+ mixing_matrix = get_mixing_matrix(st);
+ if (order_plus_one == 2)
+ {
+ mapping_matrix_init(mixing_matrix, mapping_matrix_foa_mixing.rows,
+ mapping_matrix_foa_mixing.cols, mapping_matrix_foa_mixing.gain,
+ mapping_matrix_foa_mixing_data,
+ sizeof(mapping_matrix_foa_mixing_data));
+ }
+ else if (order_plus_one == 3)
+ {
+ mapping_matrix_init(mixing_matrix, mapping_matrix_soa_mixing.rows,
+ mapping_matrix_soa_mixing.cols, mapping_matrix_soa_mixing.gain,
+ mapping_matrix_soa_mixing_data,
+ sizeof(mapping_matrix_soa_mixing_data));
+ }
+ else if (order_plus_one == 4)
+ {
+ mapping_matrix_init(mixing_matrix, mapping_matrix_toa_mixing.rows,
+ mapping_matrix_toa_mixing.cols, mapping_matrix_toa_mixing.gain,
+ mapping_matrix_toa_mixing_data,
+ sizeof(mapping_matrix_toa_mixing_data));
+ }
+ else
+ return OPUS_BAD_ARG;
+
+ st->mixing_matrix_size_in_bytes = mapping_matrix_get_size(
+ mixing_matrix->rows, mixing_matrix->cols);
+ if (!st->mixing_matrix_size_in_bytes)
+ return OPUS_BAD_ARG;
+
+ /* Assign demixing matrix based on available pre-computed matrices. */
+ demixing_matrix = get_enc_demixing_matrix(st);
+ if (order_plus_one == 2)
+ {
+ mapping_matrix_init(demixing_matrix, mapping_matrix_foa_demixing.rows,
+ mapping_matrix_foa_demixing.cols, mapping_matrix_foa_demixing.gain,
+ mapping_matrix_foa_demixing_data,
+ sizeof(mapping_matrix_foa_demixing_data));
+ }
+ else if (order_plus_one == 3)
+ {
+ mapping_matrix_init(demixing_matrix, mapping_matrix_soa_demixing.rows,
+ mapping_matrix_soa_demixing.cols, mapping_matrix_soa_demixing.gain,
+ mapping_matrix_soa_demixing_data,
+ sizeof(mapping_matrix_soa_demixing_data));
+ }
+ else if (order_plus_one == 4)
+ {
+ mapping_matrix_init(demixing_matrix, mapping_matrix_toa_demixing.rows,
+ mapping_matrix_toa_demixing.cols, mapping_matrix_toa_demixing.gain,
+ mapping_matrix_toa_demixing_data,
+ sizeof(mapping_matrix_toa_demixing_data));
+ }
+ else
+ return OPUS_BAD_ARG;
+
+ st->demixing_matrix_size_in_bytes = mapping_matrix_get_size(
+ demixing_matrix->rows, demixing_matrix->cols);
+ if (!st->demixing_matrix_size_in_bytes)
+ return OPUS_BAD_ARG;
+ }
+ else
+ return OPUS_UNIMPLEMENTED;
+
+ /* Ensure matrices are large enough for desired coding scheme. */
+ if (*streams + *coupled_streams > mixing_matrix->rows ||
+ channels > mixing_matrix->cols ||
+ channels > demixing_matrix->rows ||
+ *streams + *coupled_streams > demixing_matrix->cols)
+ return OPUS_BAD_ARG;
+
+ /* Set trivial mapping so each input channel pairs with a matrix column. */
+ for (i = 0; i < channels; i++)
+ mapping[i] = i;
+
+ /* Initialize multistream encoder with provided settings. */
+ ms_encoder = get_multistream_encoder(st);
+ ret = opus_multistream_encoder_init(ms_encoder, Fs, channels, *streams,
+ *coupled_streams, mapping, application);
+ return ret;
+}
+
+OpusProjectionEncoder *opus_projection_ambisonics_encoder_create(
+ opus_int32 Fs, int channels, int mapping_family, int *streams,
+ int *coupled_streams, int application, int *error)
+{
+ int size;
+ int ret;
+ OpusProjectionEncoder *st;
+
+ /* Allocate space for the projection encoder. */
+ size = opus_projection_ambisonics_encoder_get_size(channels, mapping_family);
+ if (!size) {
+ if (error)
+ *error = OPUS_ALLOC_FAIL;
+ return NULL;
+ }
+ st = (OpusProjectionEncoder *)opus_alloc(size);
+ if (!st)
+ {
+ if (error)
+ *error = OPUS_ALLOC_FAIL;
+ return NULL;
+ }
+
+ /* Initialize projection encoder with provided settings. */
+ ret = opus_projection_ambisonics_encoder_init(st, Fs, channels,
+ mapping_family, streams, coupled_streams, application);
+ if (ret != OPUS_OK)
+ {
+ opus_free(st);
+ st = NULL;
+ }
+ if (error)
+ *error = ret;
+ return st;
+}
+
+int opus_projection_encode(OpusProjectionEncoder *st, const opus_int16 *pcm,
+ int frame_size, unsigned char *data,
+ opus_int32 max_data_bytes)
+{
+ return opus_multistream_encode_native(get_multistream_encoder(st),
+ opus_projection_copy_channel_in_short, pcm, frame_size, data,
+ max_data_bytes, 16, downmix_int, 0, get_mixing_matrix(st));
+}
+
+#ifndef DISABLE_FLOAT_API
+#ifdef FIXED_POINT
+int opus_projection_encode_float(OpusProjectionEncoder *st, const float *pcm,
+ int frame_size, unsigned char *data,
+ opus_int32 max_data_bytes)
+{
+ return opus_multistream_encode_native(get_multistream_encoder(st),
+ opus_projection_copy_channel_in_float, pcm, frame_size, data,
+ max_data_bytes, 16, downmix_float, 1, get_mixing_matrix(st));
+}
+#else
+int opus_projection_encode_float(OpusProjectionEncoder *st, const float *pcm,
+ int frame_size, unsigned char *data,
+ opus_int32 max_data_bytes)
+{
+ return opus_multistream_encode_native(get_multistream_encoder(st),
+ opus_projection_copy_channel_in_float, pcm, frame_size, data,
+ max_data_bytes, 24, downmix_float, 1, get_mixing_matrix(st));
+}
+#endif
+#endif
+
+void opus_projection_encoder_destroy(OpusProjectionEncoder *st)
+{
+ opus_free(st);
+}
+
+int opus_projection_encoder_ctl(OpusProjectionEncoder *st, int request, ...)
+{
+ va_list ap;
+ MappingMatrix *demixing_matrix;
+ OpusMSEncoder *ms_encoder;
+ int ret = OPUS_OK;
+
+ ms_encoder = get_multistream_encoder(st);
+ demixing_matrix = get_enc_demixing_matrix(st);
+
+ va_start(ap, request);
+ switch(request)
+ {
+ case OPUS_PROJECTION_GET_DEMIXING_MATRIX_SIZE_REQUEST:
+ {
+ opus_int32 *value = va_arg(ap, opus_int32*);
+ if (!value)
+ {
+ goto bad_arg;
+ }
+ *value =
+ ms_encoder->layout.nb_channels * (ms_encoder->layout.nb_streams
+ + ms_encoder->layout.nb_coupled_streams) * sizeof(opus_int16);
+ }
+ break;
+ case OPUS_PROJECTION_GET_DEMIXING_MATRIX_GAIN_REQUEST:
+ {
+ opus_int32 *value = va_arg(ap, opus_int32*);
+ if (!value)
+ {
+ goto bad_arg;
+ }
+ *value = demixing_matrix->gain;
+ }
+ break;
+ case OPUS_PROJECTION_GET_DEMIXING_MATRIX_REQUEST:
+ {
+ int i, j, k, l;
+ int nb_input_streams;
+ int nb_output_streams;
+ unsigned char *external_char;
+ opus_int16 *internal_short;
+ opus_int32 external_size;
+ opus_int32 internal_size;
+
+ /* (I/O is in relation to the decoder's perspective). */
+ nb_input_streams = ms_encoder->layout.nb_streams +
+ ms_encoder->layout.nb_coupled_streams;
+ nb_output_streams = ms_encoder->layout.nb_channels;
+
+ external_char = va_arg(ap, unsigned char *);
+ external_size = va_arg(ap, opus_int32);
+ if (!external_char)
+ {
+ goto bad_arg;
+ }
+ internal_short = mapping_matrix_get_data(demixing_matrix);
+ internal_size = nb_input_streams * nb_output_streams * sizeof(opus_int16);
+ if (external_size != internal_size)
+ {
+ goto bad_arg;
+ }
+
+ /* Copy demixing matrix subset to output destination. */
+ l = 0;
+ for (i = 0; i < nb_input_streams; i++) {
+ for (j = 0; j < nb_output_streams; j++) {
+ k = demixing_matrix->rows * i + j;
+ external_char[2*l] = (unsigned char)internal_short[k];
+ external_char[2*l+1] = (unsigned char)(internal_short[k] >> 8);
+ l++;
+ }
+ }
+ }
+ break;
+ default:
+ {
+ ret = opus_multistream_encoder_ctl_va_list(ms_encoder, request, ap);
+ }
+ break;
+ }
+ va_end(ap);
+ return ret;
+
+bad_arg:
+ va_end(ap);
+ return OPUS_BAD_ARG;
+}
+
{
/* 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]);
+ /* assert disabled because it's not valid in C. */
+ /* celt_assert(frames[i] + len[i] <= data || ptr <= frames[i]); */
OPUS_MOVE(ptr, frames[i], len[i]);
ptr += len[i];
}
--- /dev/null
+/* 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define MAX_PACKETOUT 32000
+
+void usage(char *argv0)
+{
+ fprintf(stderr, "usage: %s [options] input_file output_file\n", argv0);
+}
+
+static void int_to_char(opus_uint32 i, unsigned char ch[4])
+{
+ ch[0] = i>>24;
+ ch[1] = (i>>16)&0xFF;
+ ch[2] = (i>>8)&0xFF;
+ ch[3] = i&0xFF;
+}
+
+static opus_uint32 char_to_int(unsigned char ch[4])
+{
+ return ((opus_uint32)ch[0]<<24) | ((opus_uint32)ch[1]<<16)
+ | ((opus_uint32)ch[2]<< 8) | (opus_uint32)ch[3];
+}
+
+int main(int argc, char *argv[])
+{
+ int i, eof=0;
+ FILE *fin, *fout;
+ unsigned char packets[48][1500];
+ int len[48];
+ int rng[48];
+ OpusRepacketizer *rp;
+ unsigned char output_packet[MAX_PACKETOUT];
+ int merge = 1, split=0;
+
+ if (argc < 3)
+ {
+ usage(argv[0]);
+ return EXIT_FAILURE;
+ }
+ for (i=1;i<argc-2;i++)
+ {
+ if (strcmp(argv[i], "-merge")==0)
+ {
+ merge = atoi(argv[i+1]);
+ if(merge<1)
+ {
+ fprintf(stderr, "-merge parameter must be at least 1.\n");
+ return EXIT_FAILURE;
+ }
+ if(merge>48)
+ {
+ fprintf(stderr, "-merge parameter must be less than 48.\n");
+ return EXIT_FAILURE;
+ }
+ i++;
+ } else if (strcmp(argv[i], "-split")==0)
+ split = 1;
+ else
+ {
+ fprintf(stderr, "Unknown option: %s\n", argv[i]);
+ usage(argv[0]);
+ return EXIT_FAILURE;
+ }
+ }
+ fin = fopen(argv[argc-2], "r");
+ if(fin==NULL)
+ {
+ fprintf(stderr, "Error opening input file: %s\n", argv[argc-2]);
+ return EXIT_FAILURE;
+ }
+ fout = fopen(argv[argc-1], "w");
+ if(fout==NULL)
+ {
+ fprintf(stderr, "Error opening output file: %s\n", argv[argc-1]);
+ fclose(fin);
+ return EXIT_FAILURE;
+ }
+
+ rp = opus_repacketizer_create();
+ while (!eof)
+ {
+ int err;
+ int nb_packets=merge;
+ opus_repacketizer_init(rp);
+ for (i=0;i<nb_packets;i++)
+ {
+ unsigned char ch[4];
+ err = fread(ch, 1, 4, fin);
+ len[i] = char_to_int(ch);
+ /*fprintf(stderr, "in len = %d\n", len[i]);*/
+ if (len[i]>1500 || len[i]<0)
+ {
+ if (feof(fin))
+ {
+ eof = 1;
+ } else {
+ fprintf(stderr, "Invalid payload length\n");
+ fclose(fin);
+ fclose(fout);
+ return EXIT_FAILURE;
+ }
+ break;
+ }
+ err = fread(ch, 1, 4, fin);
+ rng[i] = char_to_int(ch);
+ err = fread(packets[i], 1, len[i], fin);
+ if (feof(fin))
+ {
+ eof = 1;
+ break;
+ }
+ err = opus_repacketizer_cat(rp, packets[i], len[i]);
+ if (err!=OPUS_OK)
+ {
+ fprintf(stderr, "opus_repacketizer_cat() failed: %s\n", opus_strerror(err));
+ break;
+ }
+ }
+ nb_packets = i;
+
+ if (eof)
+ break;
+
+ if (!split)
+ {
+ err = opus_repacketizer_out(rp, output_packet, MAX_PACKETOUT);
+ if (err>0) {
+ unsigned char int_field[4];
+ int_to_char(err, int_field);
+ if(fwrite(int_field, 1, 4, fout)!=4){
+ fprintf(stderr, "Error writing.\n");
+ return EXIT_FAILURE;
+ }
+ int_to_char(rng[nb_packets-1], int_field);
+ if (fwrite(int_field, 1, 4, fout)!=4) {
+ fprintf(stderr, "Error writing.\n");
+ return EXIT_FAILURE;
+ }
+ if (fwrite(output_packet, 1, err, fout)!=(unsigned)err) {
+ fprintf(stderr, "Error writing.\n");
+ return EXIT_FAILURE;
+ }
+ /*fprintf(stderr, "out len = %d\n", err);*/
+ } else {
+ fprintf(stderr, "opus_repacketizer_out() failed: %s\n", opus_strerror(err));
+ }
+ } else {
+ int nb_frames = opus_repacketizer_get_nb_frames(rp);
+ for (i=0;i<nb_frames;i++)
+ {
+ err = opus_repacketizer_out_range(rp, i, i+1, output_packet, MAX_PACKETOUT);
+ if (err>0) {
+ unsigned char int_field[4];
+ int_to_char(err, int_field);
+ if (fwrite(int_field, 1, 4, fout)!=4) {
+ fprintf(stderr, "Error writing.\n");
+ return EXIT_FAILURE;
+ }
+ if (i==nb_frames-1)
+ int_to_char(rng[nb_packets-1], int_field);
+ else
+ int_to_char(0, int_field);
+ if (fwrite(int_field, 1, 4, fout)!=4) {
+ fprintf(stderr, "Error writing.\n");
+ return EXIT_FAILURE;
+ }
+ if (fwrite(output_packet, 1, err, fout)!=(unsigned)err) {
+ fprintf(stderr, "Error writing.\n");
+ return EXIT_FAILURE;
+ }
+ /*fprintf(stderr, "out len = %d\n", err);*/
+ } else {
+ fprintf(stderr, "opus_repacketizer_out() failed: %s\n", opus_strerror(err));
+ }
+
+ }
+ }
+ }
+
+ fclose(fin);
+ fclose(fout);
+ return EXIT_SUCCESS;
+}