Browse Source

Update opus to 1.3.1 and opusfile to 0.11

unknown 5 years ago
parent
commit
e00426c512
100 changed files with 6466 additions and 4082 deletions
  1. 7 7
      modules/opus/SCsub
  2. 4 2
      thirdparty/README.md
  3. 543 234
      thirdparty/opus/analysis.c
  4. 19 19
      thirdparty/opus/analysis.h
  5. 8 8
      thirdparty/opus/celt/_kiss_fft_guts.h
  6. 44 8
      thirdparty/opus/celt/arch.h
  7. 2 2
      thirdparty/opus/celt/arm/arm2gnu.pl
  8. 19 2
      thirdparty/opus/celt/arm/arm_celt_map.c
  9. 1 2
      thirdparty/opus/celt/arm/celt_fft_ne10.c
  10. 1 1
      thirdparty/opus/celt/arm/celt_mdct_ne10.c
  11. 5 105
      thirdparty/opus/celt/arm/celt_neon_intr.c
  12. 0 551
      thirdparty/opus/celt/arm/celt_pitch_xcorr_arm-gnu.S
  13. 5 1
      thirdparty/opus/celt/arm/celt_pitch_xcorr_arm.s
  14. 0 1
      thirdparty/opus/celt/arm/fft_arm.h
  15. 3 3
      thirdparty/opus/celt/arm/fixed_armv4.h
  16. 2 2
      thirdparty/opus/celt/arm/fixed_armv5e.h
  17. 0 1
      thirdparty/opus/celt/arm/mdct_arm.h
  18. 45 11
      thirdparty/opus/celt/arm/pitch_arm.h
  19. 290 0
      thirdparty/opus/celt/arm/pitch_neon_intr.c
  20. 233 90
      thirdparty/opus/celt/bands.c
  21. 6 3
      thirdparty/opus/celt/bands.h
  22. 21 4
      thirdparty/opus/celt/celt.c
  23. 27 5
      thirdparty/opus/celt/celt.h
  24. 157 33
      thirdparty/opus/celt/celt_decoder.c
  25. 298 101
      thirdparty/opus/celt/celt_encoder.c
  26. 22 40
      thirdparty/opus/celt/celt_lpc.c
  27. 2 3
      thirdparty/opus/celt/celt_lpc.h
  28. 1 1
      thirdparty/opus/celt/cwrs.c
  29. 2 2
      thirdparty/opus/celt/entcode.h
  30. 1 1
      thirdparty/opus/celt/entdec.h
  31. 1 1
      thirdparty/opus/celt/entenc.h
  32. 79 0
      thirdparty/opus/celt/fixed_c5x.h
  33. 70 0
      thirdparty/opus/celt/fixed_c6x.h
  34. 10 3
      thirdparty/opus/celt/fixed_debug.h
  35. 11 0
      thirdparty/opus/celt/fixed_generic.h
  36. 10 4
      thirdparty/opus/celt/float_cast.h
  37. 28 28
      thirdparty/opus/celt/kiss_fft.c
  38. 3 2
      thirdparty/opus/celt/mathops.c
  39. 34 2
      thirdparty/opus/celt/mathops.h
  40. 8 8
      thirdparty/opus/celt/mdct.c
  41. 1 0
      thirdparty/opus/celt/mips/celt_mipsr1.h
  42. 1 10
      thirdparty/opus/celt/mips/vq_mipsr1.h
  43. 1 1
      thirdparty/opus/celt/modes.c
  44. 13 33
      thirdparty/opus/celt/pitch.c
  45. 3 11
      thirdparty/opus/celt/pitch.h
  46. 9 2
      thirdparty/opus/celt/quant_bands.c
  47. 9 4
      thirdparty/opus/celt/rate.c
  48. 1 1
      thirdparty/opus/celt/rate.h
  49. 1 1
      thirdparty/opus/celt/static_modes_fixed_arm_ne10.h
  50. 1 1
      thirdparty/opus/celt/static_modes_float_arm_ne10.h
  51. 0 161
      thirdparty/opus/celt/tests/test_unit_cwrs32.c
  52. 0 189
      thirdparty/opus/celt/tests/test_unit_dft.c
  53. 0 382
      thirdparty/opus/celt/tests/test_unit_entropy.c
  54. 0 93
      thirdparty/opus/celt/tests/test_unit_laplace.c
  55. 0 304
      thirdparty/opus/celt/tests/test_unit_mathops.c
  56. 0 230
      thirdparty/opus/celt/tests/test_unit_mdct.c
  57. 0 120
      thirdparty/opus/celt/tests/test_unit_rotation.c
  58. 76 42
      thirdparty/opus/celt/vq.c
  59. 12 8
      thirdparty/opus/celt/vq.h
  60. 4 6
      thirdparty/opus/celt/x86/celt_lpc_sse.h
  61. 7 50
      thirdparty/opus/celt/x86/celt_lpc_sse4_1.c
  62. 23 23
      thirdparty/opus/celt/x86/vq_sse.h
  63. 217 0
      thirdparty/opus/celt/x86/vq_sse2.c
  64. 13 1
      thirdparty/opus/celt/x86/x86_celt_map.c
  65. 3 1
      thirdparty/opus/celt/x86/x86cpu.h
  66. 118 3
      thirdparty/opus/config.h
  67. 44 31
      thirdparty/opus/info.c
  68. 14 9
      thirdparty/opus/internal.h
  69. 378 0
      thirdparty/opus/mapping_matrix.c
  70. 133 0
      thirdparty/opus/mapping_matrix.h
  71. 77 78
      thirdparty/opus/mlp.c
  72. 26 9
      thirdparty/opus/mlp.h
  73. 659 96
      thirdparty/opus/mlp_data.c
  74. 2 2
      thirdparty/opus/opus.c
  75. 1 1
      thirdparty/opus/opus/opus.h
  76. 49 3
      thirdparty/opus/opus/opus_defines.h
  77. 2 2
      thirdparty/opus/opus/opus_multistream.h
  78. 568 0
      thirdparty/opus/opus/opus_projection.h
  79. 17 10
      thirdparty/opus/opus/opus_types.h
  80. 33 26
      thirdparty/opus/opus/opusfile.h
  81. 3 0
      thirdparty/opus/opus_compare.c
  82. 84 33
      thirdparty/opus/opus_decoder.c
  83. 497 339
      thirdparty/opus/opus_encoder.c
  84. 51 39
      thirdparty/opus/opus_multistream_decoder.c
  85. 164 187
      thirdparty/opus/opus_multistream_encoder.c
  86. 76 9
      thirdparty/opus/opus_private.h
  87. 258 0
      thirdparty/opus/opus_projection_decoder.c
  88. 468 0
      thirdparty/opus/opus_projection_encoder.c
  89. 162 102
      thirdparty/opus/opusfile.c
  90. 2 1
      thirdparty/opus/repacketizer.c
  91. 4 4
      thirdparty/opus/silk/A2NLSF.c
  92. 2 1
      thirdparty/opus/silk/API.h
  93. 6 6
      thirdparty/opus/silk/CNG.c
  94. 14 11
      thirdparty/opus/silk/LPC_analysis_filter.c
  95. 81 0
      thirdparty/opus/silk/LPC_fit.c
  96. 42 55
      thirdparty/opus/silk/LPC_inv_pred_gain.c
  97. 1 1
      thirdparty/opus/silk/LP_variable_cutoff.c
  98. 1 9
      thirdparty/opus/silk/MacroCount.h
  99. 1 2
      thirdparty/opus/silk/MacroDebug.h
  100. 11 48
      thirdparty/opus/silk/NLSF2A.c

+ 7 - 7
modules/opus/SCsub

@@ -20,6 +20,9 @@ if env['builtin_opus']:
         "opus_multistream.c",
         "opus_multistream_encoder.c",
         "opus_multistream_decoder.c",
+        "opus_projection_encoder.c",
+        "opus_projection_decoder.c",
+        "mapping_matrix.c",
         "repacketizer.c",
 
         "analysis.c",
@@ -53,9 +56,10 @@ if env['builtin_opus']:
         "celt/vq.c",
         #"celt/arm/arm_celt_map.c",
         #"celt/arm/armcpu.c",
-        #"celt/arm/celt_ne10_fft.c",
-        #"celt/arm/celt_ne10_mdct.c",
+        #"celt/arm/celt_fft_ne10.c",
+        #"celt/arm/celt_mdct_ne10.c",
         #"celt/arm/celt_neon_intr.c",
+        #"celt/arm/pitch_neon_intr.c",
 
         # Sync with silk_sources.mk
         "silk/CNG.c",
@@ -113,6 +117,7 @@ if env['builtin_opus']:
         "silk/lin2log.c",
         "silk/log2lin.c",
         "silk/LPC_analysis_filter.c",
+        "silk/LPC_fit.c",
         "silk/LPC_inv_pred_gain.c",
         "silk/table_LSF_cos.c",
         "silk/NLSF2A.c",
@@ -150,12 +155,10 @@ if env['builtin_opus']:
             "silk/fixed/find_pitch_lags_FIX.c",
             "silk/fixed/find_pred_coefs_FIX.c",
             "silk/fixed/noise_shape_analysis_FIX.c",
-            "silk/fixed/prefilter_FIX.c",
             "silk/fixed/process_gains_FIX.c",
             "silk/fixed/regularize_correlations_FIX.c",
             "silk/fixed/residual_energy16_FIX.c",
             "silk/fixed/residual_energy_FIX.c",
-            "silk/fixed/solve_LS_FIX.c",
             "silk/fixed/warped_autocorrelation_FIX.c",
             "silk/fixed/apply_sine_window_FIX.c",
             "silk/fixed/autocorr_FIX.c",
@@ -180,11 +183,9 @@ if env['builtin_opus']:
             "silk/float/LTP_analysis_filter_FLP.c",
             "silk/float/LTP_scale_ctrl_FLP.c",
             "silk/float/noise_shape_analysis_FLP.c",
-            "silk/float/prefilter_FLP.c",
             "silk/float/process_gains_FLP.c",
             "silk/float/regularize_correlations_FLP.c",
             "silk/float/residual_energy_FLP.c",
-            "silk/float/solve_LS_FLP.c",
             "silk/float/warped_autocorrelation_FLP.c",
             "silk/float/wrappers_FLP.c",
             "silk/float/autocorrelation_FLP.c",
@@ -193,7 +194,6 @@ if env['builtin_opus']:
             "silk/float/energy_FLP.c",
             "silk/float/inner_product_FLP.c",
             "silk/float/k2a_FLP.c",
-            "silk/float/levinsondurbin_FLP.c",
             "silk/float/LPC_inv_pred_gain_FLP.c",
             "silk/float/pitch_analysis_core_FLP.c",
             "silk/float/scale_copy_vector_FLP.c",

+ 4 - 2
thirdparty/README.md

@@ -395,17 +395,19 @@ Files extracted from the upstream source:
 ## opus
 
 - Upstream: https://opus-codec.org
-- Version: 1.1.5 (opus) and 0.8 (opusfile)
+- Version: 1.3.1 (opus) and 0.11 (opusfile)
 - License: BSD-3-Clause
 
 Files extracted from upstream source:
 
+- Run `opus/configure` and copy/sync changes to `config.h`
+  (note that this file may have Godot-specific options enabled)
 - all .c and .h files in src/ (both opus and opusfile)
 - all .h files in include/ (both opus and opusfile) as opus/
 - remove unused `opus_demo.c`,
 - remove `http.c`, `wincerts.c` and `winerrno.h` (part of
   unused libopusurl)
-- celt/ and silk/ subfolders
+- celt/ and silk/ subfolders (minus tests folders)
 - COPYING
 
 

+ 543 - 234
thirdparty/opus/analysis.c

@@ -29,20 +29,29 @@
 #include "config.h"
 #endif
 
+#define ANALYSIS_C
+
+#include <stdio.h>
+
+#include "mathops.h"
 #include "kiss_fft.h"
 #include "celt.h"
 #include "modes.h"
 #include "arch.h"
 #include "quant_bands.h"
-#include <stdio.h>
 #include "analysis.h"
 #include "mlp.h"
 #include "stack_alloc.h"
+#include "float_cast.h"
 
 #ifndef M_PI
 #define M_PI 3.141592653
 #endif
 
+#ifndef DISABLE_FLOAT_API
+
+#define TRANSITION_PENALTY 10
+
 static const float dct_table[128] = {
         0.250000f, 0.250000f, 0.250000f, 0.250000f, 0.250000f, 0.250000f, 0.250000f, 0.250000f,
         0.250000f, 0.250000f, 0.250000f, 0.250000f, 0.250000f, 0.250000f, 0.250000f, 0.250000f,
@@ -96,52 +105,118 @@ static const float analysis_window[240] = {
 };
 
 static const int tbands[NB_TBANDS+1] = {
-       2,  4,  6,  8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, 68, 80, 96, 120
-};
-
-static const int extra_bands[NB_TOT_BANDS+1] = {
-      1, 2,  4,  6,  8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, 68, 80, 96, 120, 160, 200
+      4, 8, 12, 16, 20, 24, 28, 32, 40, 48, 56, 64, 80, 96, 112, 136, 160, 192, 240
 };
 
-/*static const float tweight[NB_TBANDS+1] = {
-      .3, .4, .5, .6, .7, .8, .9, 1., 1., 1., 1., 1., 1., 1., .8, .7, .6, .5
-};*/
-
 #define NB_TONAL_SKIP_BANDS 9
 
-#define cA 0.43157974f
-#define cB 0.67848403f
-#define cC 0.08595542f
-#define cE ((float)M_PI/2)
-static OPUS_INLINE float fast_atan2f(float y, float x) {
-   float x2, y2;
-   /* Should avoid underflow on the values we'll get */
-   if (ABS16(x)+ABS16(y)<1e-9f)
+static opus_val32 silk_resampler_down2_hp(
+    opus_val32                  *S,                 /* I/O  State vector [ 2 ]                                          */
+    opus_val32                  *out,               /* O    Output signal [ floor(len/2) ]                              */
+    const opus_val32            *in,                /* I    Input signal [ len ]                                        */
+    int                         inLen               /* I    Number of input samples                                     */
+)
+{
+    int k, len2 = inLen/2;
+    opus_val32 in32, out32, out32_hp, Y, X;
+    opus_val64 hp_ener = 0;
+    /* Internal variables and state are in Q10 format */
+    for( k = 0; k < len2; k++ ) {
+        /* Convert to Q10 */
+        in32 = in[ 2 * k ];
+
+        /* All-pass section for even input sample */
+        Y      = SUB32( in32, S[ 0 ] );
+        X      = MULT16_32_Q15(QCONST16(0.6074371f, 15), Y);
+        out32  = ADD32( S[ 0 ], X );
+        S[ 0 ] = ADD32( in32, X );
+        out32_hp = out32;
+        /* Convert to Q10 */
+        in32 = in[ 2 * k + 1 ];
+
+        /* All-pass section for odd input sample, and add to output of previous section */
+        Y      = SUB32( in32, S[ 1 ] );
+        X      = MULT16_32_Q15(QCONST16(0.15063f, 15), Y);
+        out32  = ADD32( out32, S[ 1 ] );
+        out32  = ADD32( out32, X );
+        S[ 1 ] = ADD32( in32, X );
+
+        Y      = SUB32( -in32, S[ 2 ] );
+        X      = MULT16_32_Q15(QCONST16(0.15063f, 15), Y);
+        out32_hp  = ADD32( out32_hp, S[ 2 ] );
+        out32_hp  = ADD32( out32_hp, X );
+        S[ 2 ] = ADD32( -in32, X );
+
+        hp_ener += out32_hp*(opus_val64)out32_hp;
+        /* Add, convert back to int16 and store to output */
+        out[ k ] = HALF32(out32);
+    }
+#ifdef FIXED_POINT
+    /* len2 can be up to 480, so we shift by 8 more to make it fit. */
+    hp_ener = hp_ener >> (2*SIG_SHIFT + 8);
+#endif
+    return (opus_val32)hp_ener;
+}
+
+static opus_val32 downmix_and_resample(downmix_func downmix, const void *_x, opus_val32 *y, opus_val32 S[3], int subframe, int offset, int c1, int c2, int C, int Fs)
+{
+   VARDECL(opus_val32, tmp);
+   opus_val32 scale;
+   int j;
+   opus_val32 ret = 0;
+   SAVE_STACK;
+
+   if (subframe==0) return 0;
+   if (Fs == 48000)
    {
-      x*=1e12f;
-      y*=1e12f;
+      subframe *= 2;
+      offset *= 2;
+   } else if (Fs == 16000) {
+      subframe = subframe*2/3;
+      offset = offset*2/3;
    }
-   x2 = x*x;
-   y2 = y*y;
-   if(x2<y2){
-      float den = (y2 + cB*x2) * (y2 + cC*x2);
-      if (den!=0)
-         return -x*y*(y2 + cA*x2) / den + (y<0 ? -cE : cE);
-      else
-         return (y<0 ? -cE : cE);
-   }else{
-      float den = (x2 + cB*y2) * (x2 + cC*y2);
-      if (den!=0)
-         return  x*y*(x2 + cA*y2) / den + (y<0 ? -cE : cE) - (x*y<0 ? -cE : cE);
-      else
-         return (y<0 ? -cE : cE) - (x*y<0 ? -cE : cE);
+   ALLOC(tmp, subframe, opus_val32);
+
+   downmix(_x, tmp, subframe, offset, c1, c2, C);
+#ifdef FIXED_POINT
+   scale = (1<<SIG_SHIFT);
+#else
+   scale = 1.f/32768;
+#endif
+   if (c2==-2)
+      scale /= C;
+   else if (c2>-1)
+      scale /= 2;
+   for (j=0;j<subframe;j++)
+      tmp[j] *= scale;
+   if (Fs == 48000)
+   {
+      ret = silk_resampler_down2_hp(S, y, tmp, subframe);
+   } else if (Fs == 24000) {
+      OPUS_COPY(y, tmp, subframe);
+   } else if (Fs == 16000) {
+      VARDECL(opus_val32, tmp3x);
+      ALLOC(tmp3x, 3*subframe, opus_val32);
+      /* Don't do this at home! This resampler is horrible and it's only (barely)
+         usable for the purpose of the analysis because we don't care about all
+         the aliasing between 8 kHz and 12 kHz. */
+      for (j=0;j<subframe;j++)
+      {
+         tmp3x[3*j] = tmp[j];
+         tmp3x[3*j+1] = tmp[j];
+         tmp3x[3*j+2] = tmp[j];
+      }
+      silk_resampler_down2_hp(S, y, tmp3x, 3*subframe);
    }
+   RESTORE_STACK;
+   return ret;
 }
 
-void tonality_analysis_init(TonalityAnalysisState *tonal)
+void tonality_analysis_init(TonalityAnalysisState *tonal, opus_int32 Fs)
 {
   /* Initialize reusable fields. */
   tonal->arch = opus_select_arch();
+  tonal->Fs = Fs;
   /* Clear remaining fields. */
   tonality_analysis_reset(tonal);
 }
@@ -157,15 +232,34 @@ void tonality_get_info(TonalityAnalysisState *tonal, AnalysisInfo *info_out, int
 {
    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;
    if (curr_lookahead<0)
       curr_lookahead += DETECT_SIZE;
 
-   if (len > 480 && pos != tonal->write_pos)
+   tonal->read_subframe += len/(tonal->Fs/400);
+   while (tonal->read_subframe>=8)
+   {
+      tonal->read_subframe -= 8;
+      tonal->read_pos++;
+   }
+   if (tonal->read_pos>=DETECT_SIZE)
+      tonal->read_pos-=DETECT_SIZE;
+
+   /* On long frames, look at the second analysis window rather than the first. */
+   if (len > tonal->Fs/50 && pos != tonal->write_pos)
    {
       pos++;
       if (pos==DETECT_SIZE)
@@ -175,33 +269,178 @@ void tonality_get_info(TonalityAnalysisState *tonal, AnalysisInfo *info_out, int
       pos--;
    if (pos<0)
       pos = DETECT_SIZE-1;
+   pos0 = pos;
    OPUS_COPY(info_out, &tonal->info[pos], 1);
-   tonal->read_subframe += len/120;
-   while (tonal->read_subframe>=4)
+   if (!info_out->valid)
+      return;
+   tonality_max = tonality_avg = info_out->tonality;
+   tonality_count = 1;
+   /* Look at the neighbouring frames and pick largest bandwidth found (to be safe). */
+   bandwidth_span = 6;
+   /* If possible, look ahead for a tone to compensate for the delay in the tone detector. */
+   for (i=0;i<3;i++)
    {
-      tonal->read_subframe -= 4;
-      tonal->read_pos++;
+      pos++;
+      if (pos==DETECT_SIZE)
+         pos = 0;
+      if (pos == tonal->write_pos)
+         break;
+      tonality_max = MAX32(tonality_max, tonal->info[pos].tonality);
+      tonality_avg += tonal->info[pos].tonality;
+      tonality_count++;
+      info_out->bandwidth = IMAX(info_out->bandwidth, tonal->info[pos].bandwidth);
+      bandwidth_span--;
    }
-   if (tonal->read_pos>=DETECT_SIZE)
-      tonal->read_pos-=DETECT_SIZE;
+   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;
 
-   /* Compensate for the delay in the features themselves.
-      FIXME: Need a better estimate the 10 I just made up */
-   curr_lookahead = IMAX(curr_lookahead-10, 0);
-
-   psum=0;
-   /* Summing the probability of transition patterns that involve music at
-      time (DETECT_SIZE-curr_lookahead-1) */
-   for (i=0;i<DETECT_SIZE-curr_lookahead;i++)
-      psum += tonal->pmusic[i];
-   for (;i<DETECT_SIZE;i++)
-      psum += tonal->pspeech[i];
-   psum = psum*tonal->music_confidence + (1-psum)*tonal->speech_confidence;
-   /*printf("%f %f %f\n", psum, info_out->music_prob, info_out->tonality);*/
-
-   info_out->music_prob = psum;
+   /* printf("%f %f %f %f %f\n", prob_min, prob_max, prob_avg/prob_count, vad_prob, info_out->music_prob); */
 }
 
+static const float std_feature_bias[9] = {
+      5.684947f, 3.475288f, 1.770634f, 1.599784f, 3.773215f,
+      2.163313f, 1.260756f, 1.116868f, 1.918795f
+};
+
+#define LEAKAGE_OFFSET 2.5f
+#define LEAKAGE_SLOPE 2.f
+
+#ifdef FIXED_POINT
+/* For fixed-point, the input is +/-2^15 shifted up by SIG_SHIFT, so we need to
+   compensate for that in the energy. */
+#define SCALE_COMPENS (1.f/((opus_int32)1<<(15+SIG_SHIFT)))
+#define SCALE_ENER(e) ((SCALE_COMPENS*SCALE_COMPENS)*(e))
+#else
+#define SCALE_ENER(e) (e)
+#endif
+
+#ifdef FIXED_POINT
+static int is_digital_silence32(const opus_val32* pcm, int frame_size, int channels, int lsb_depth)
+{
+   int silence = 0;
+   opus_val32 sample_max = 0;
+#ifdef MLP_TRAINING
+   return 0;
+#endif
+   sample_max = celt_maxabs32(pcm, frame_size*channels);
+
+   silence = (sample_max == 0);
+   (void)lsb_depth;
+   return silence;
+}
+#else
+#define is_digital_silence32(pcm, frame_size, channels, lsb_depth) is_digital_silence(pcm, frame_size, channels, lsb_depth)
+#endif
+
 static void tonality_analysis(TonalityAnalysisState *tonal, const CELTMode *celt_mode, const void *x, int len, int offset, int c1, int c2, int C, int lsb_depth, downmix_func downmix)
 {
     int i, b;
@@ -230,24 +469,50 @@ static void tonality_analysis(TonalityAnalysisState *tonal, const CELTMode *celt
     float alpha, alphaE, alphaE2;
     float frame_loudness;
     float bandwidth_mask;
+    int is_masked[NB_TBANDS+1];
     int bandwidth=0;
     float maxE = 0;
     float noise_floor;
     int remaining;
     AnalysisInfo *info;
+    float hp_ener;
+    float tonality2[240];
+    float midE[8];
+    float spec_variability=0;
+    float band_log2[NB_TBANDS+1];
+    float leakage_from[NB_TBANDS+1];
+    float leakage_to[NB_TBANDS+1];
+    float layer_out[MAX_NEURONS];
+    float below_max_pitch;
+    float above_max_pitch;
+    int is_silence;
     SAVE_STACK;
 
-    tonal->last_transition++;
-    alpha = 1.f/IMIN(20, 1+tonal->count);
-    alphaE = 1.f/IMIN(50, 1+tonal->count);
-    alphaE2 = 1.f/IMIN(1000, 1+tonal->count);
+    if (!tonal->initialized)
+    {
+       tonal->mem_fill = 240;
+       tonal->initialized = 1;
+    }
+    alpha = 1.f/IMIN(10, 1+tonal->count);
+    alphaE = 1.f/IMIN(25, 1+tonal->count);
+    /* Noise floor related decay for bandwidth detection: -2.2 dB/second */
+    alphaE2 = 1.f/IMIN(100, 1+tonal->count);
+    if (tonal->count <= 1) alphaE2 = 1;
+
+    if (tonal->Fs == 48000)
+    {
+       /* len and offset are now at 24 kHz. */
+       len/= 2;
+       offset /= 2;
+    } else if (tonal->Fs == 16000) {
+       len = 3*len/2;
+       offset = 3*offset/2;
+    }
 
-    if (tonal->count<4)
-       tonal->music_prob = .5;
     kfft = celt_mode->mdct.kfft[0];
-    if (tonal->count==0)
-       tonal->mem_fill = 240;
-    downmix(x, &tonal->inmem[tonal->mem_fill], IMIN(len, ANALYSIS_BUF_SIZE-tonal->mem_fill), offset, c1, c2, C);
+    tonal->hp_ener_accum += (float)downmix_and_resample(downmix, x,
+          &tonal->inmem[tonal->mem_fill], tonal->downmix_state,
+          IMIN(len, ANALYSIS_BUF_SIZE-tonal->mem_fill), offset, c1, c2, C, tonal->Fs);
     if (tonal->mem_fill+len < ANALYSIS_BUF_SIZE)
     {
        tonal->mem_fill += len;
@@ -255,10 +520,13 @@ static void tonality_analysis(TonalityAnalysisState *tonal, const CELTMode *celt
        RESTORE_STACK;
        return;
     }
+    hp_ener = tonal->hp_ener_accum;
     info = &tonal->info[tonal->write_pos++];
     if (tonal->write_pos>=DETECT_SIZE)
        tonal->write_pos-=DETECT_SIZE;
 
+    is_silence = is_digital_silence32(tonal->inmem, ANALYSIS_BUF_SIZE, 1, lsb_depth);
+
     ALLOC(in, 480, kiss_fft_cpx);
     ALLOC(out, 480, kiss_fft_cpx);
     ALLOC(tonality, 240, float);
@@ -273,8 +541,20 @@ static void tonality_analysis(TonalityAnalysisState *tonal, const CELTMode *celt
     }
     OPUS_MOVE(tonal->inmem, tonal->inmem+ANALYSIS_BUF_SIZE-240, 240);
     remaining = len - (ANALYSIS_BUF_SIZE-tonal->mem_fill);
-    downmix(x, &tonal->inmem[240], remaining, offset+ANALYSIS_BUF_SIZE-tonal->mem_fill, c1, c2, C);
+    tonal->hp_ener_accum = (float)downmix_and_resample(downmix, x,
+          &tonal->inmem[240], tonal->downmix_state, remaining,
+          offset+ANALYSIS_BUF_SIZE-tonal->mem_fill, c1, c2, C, tonal->Fs);
     tonal->mem_fill = 240 + remaining;
+    if (is_silence)
+    {
+       /* On silence, copy the previous analysis. */
+       int prev_pos = tonal->write_pos-2;
+       if (prev_pos < 0)
+          prev_pos += DETECT_SIZE;
+       OPUS_COPY(info, &tonal->info[prev_pos], 1);
+       RESTORE_STACK;
+       return;
+    }
     opus_fft(kfft, in, out, tonal->arch);
 #ifndef FIXED_POINT
     /* If there's any NaN on the input, the entire output will be NaN, so we only need to check one value. */
@@ -305,24 +585,31 @@ static void tonality_analysis(TonalityAnalysisState *tonal, const CELTMode *celt
        d_angle2 = angle2 - angle;
        d2_angle2 = d_angle2 - d_angle;
 
-       mod1 = d2_angle - (float)floor(.5+d2_angle);
+       mod1 = d2_angle - (float)float2int(d2_angle);
        noisiness[i] = ABS16(mod1);
        mod1 *= mod1;
        mod1 *= mod1;
 
-       mod2 = d2_angle2 - (float)floor(.5+d2_angle2);
+       mod2 = d2_angle2 - (float)float2int(d2_angle2);
        noisiness[i] += ABS16(mod2);
        mod2 *= mod2;
        mod2 *= mod2;
 
-       avg_mod = .25f*(d2A[i]+2.f*mod1+mod2);
+       avg_mod = .25f*(d2A[i]+mod1+2*mod2);
+       /* This introduces an extra delay of 2 frames in the detection. */
        tonality[i] = 1.f/(1.f+40.f*16.f*pi4*avg_mod)-.015f;
+       /* No delay on this detection, but it's less reliable. */
+       tonality2[i] = 1.f/(1.f+40.f*16.f*pi4*mod2)-.015f;
 
        A[i] = angle2;
        dA[i] = d_angle2;
        d2A[i] = mod2;
     }
-
+    for (i=2;i<N2-1;i++)
+    {
+       float tt = MIN32(tonality2[i], MAX32(tonality2[i-1], tonality2[i+1]));
+       tonality[i] = .9f*MAX32(tonality[i], tt-.1f);
+    }
     frame_tonality = 0;
     max_frame_tonality = 0;
     /*tw_sum = 0;*/
@@ -339,6 +626,22 @@ static void tonality_analysis(TonalityAnalysisState *tonal, const CELTMode *celt
     }
     relativeE = 0;
     frame_loudness = 0;
+    /* The energy of the very first band is special because of DC. */
+    {
+       float E = 0;
+       float X1r, X2r;
+       X1r = 2*(float)out[0].r;
+       X2r = 2*(float)out[0].i;
+       E = X1r*X1r + X2r*X2r;
+       for (i=1;i<4;i++)
+       {
+          float binE = out[i].r*(float)out[i].r + out[N-i].r*(float)out[N-i].r
+                     + out[i].i*(float)out[i].i + out[N-i].i*(float)out[N-i].i;
+          E += binE;
+       }
+       E = SCALE_ENER(E);
+       band_log2[0] = .5f*1.442695f*(float)log(E+1e-10f);
+    }
     for (b=0;b<NB_TBANDS;b++)
     {
        float E=0, tE=0, nE=0;
@@ -348,12 +651,9 @@ static void tonality_analysis(TonalityAnalysisState *tonal, const CELTMode *celt
        {
           float binE = out[i].r*(float)out[i].r + out[N-i].r*(float)out[N-i].r
                      + out[i].i*(float)out[i].i + out[N-i].i*(float)out[N-i].i;
-#ifdef FIXED_POINT
-          /* FIXME: It's probably best to change the BFCC filter initial state instead */
-          binE *= 5.55e-17f;
-#endif
+          binE = SCALE_ENER(binE);
           E += binE;
-          tE += binE*tonality[i];
+          tE += binE*MAX32(0, tonality[i]);
           nE += binE*2.f*(.5f-noisiness[i]);
        }
 #ifndef FIXED_POINT
@@ -371,14 +671,27 @@ static void tonality_analysis(TonalityAnalysisState *tonal, const CELTMode *celt
 
        frame_loudness += (float)sqrt(E+1e-10f);
        logE[b] = (float)log(E+1e-10f);
-       tonal->lowE[b] = MIN32(logE[b], tonal->lowE[b]+.01f);
-       tonal->highE[b] = MAX32(logE[b], tonal->highE[b]-.1f);
-       if (tonal->highE[b] < tonal->lowE[b]+1.f)
+       band_log2[b+1] = .5f*1.442695f*(float)log(E+1e-10f);
+       tonal->logE[tonal->E_count][b] = logE[b];
+       if (tonal->count==0)
+          tonal->highE[b] = tonal->lowE[b] = logE[b];
+       if (tonal->highE[b] > tonal->lowE[b] + 7.5)
        {
-          tonal->highE[b]+=.5f;
-          tonal->lowE[b]-=.5f;
+          if (tonal->highE[b] - logE[b] > logE[b] - tonal->lowE[b])
+             tonal->highE[b] -= .01f;
+          else
+             tonal->lowE[b] += .01f;
        }
-       relativeE += (logE[b]-tonal->lowE[b])/(1e-15f+tonal->highE[b]-tonal->lowE[b]);
+       if (logE[b] > tonal->highE[b])
+       {
+          tonal->highE[b] = logE[b];
+          tonal->lowE[b] = MAX32(tonal->highE[b]-15, tonal->lowE[b]);
+       } else if (logE[b] < tonal->lowE[b])
+       {
+          tonal->lowE[b] = logE[b];
+          tonal->highE[b] = MIN32(tonal->lowE[b]+15, tonal->highE[b]);
+       }
+       relativeE += (logE[b]-tonal->lowE[b])/(1e-5f + (tonal->highE[b]-tonal->lowE[b]));
 
        L1=L2=0;
        for (i=0;i<NB_FRAMES;i++)
@@ -410,45 +723,135 @@ static void tonality_analysis(TonalityAnalysisState *tonal, const CELTMode *celt
        tonal->prev_band_tonality[b] = band_tonality[b];
     }
 
+    leakage_from[0] = band_log2[0];
+    leakage_to[0] = band_log2[0] - LEAKAGE_OFFSET;
+    for (b=1;b<NB_TBANDS+1;b++)
+    {
+       float leak_slope = LEAKAGE_SLOPE*(tbands[b]-tbands[b-1])/4;
+       leakage_from[b] = MIN16(leakage_from[b-1]+leak_slope, band_log2[b]);
+       leakage_to[b] = MAX16(leakage_to[b-1]-leak_slope, band_log2[b]-LEAKAGE_OFFSET);
+    }
+    for (b=NB_TBANDS-2;b>=0;b--)
+    {
+       float leak_slope = LEAKAGE_SLOPE*(tbands[b+1]-tbands[b])/4;
+       leakage_from[b] = MIN16(leakage_from[b+1]+leak_slope, leakage_from[b]);
+       leakage_to[b] = MAX16(leakage_to[b+1]-leak_slope, leakage_to[b]);
+    }
+    celt_assert(NB_TBANDS+1 <= LEAK_BANDS);
+    for (b=0;b<NB_TBANDS+1;b++)
+    {
+       /* leak_boost[] is made up of two terms. The first, based on leakage_to[],
+          represents the boost needed to overcome the amount of analysis leakage
+          cause in a weaker band b by louder neighbouring bands.
+          The second, based on leakage_from[], applies to a loud band b for
+          which the quantization noise causes synthesis leakage to the weaker
+          neighbouring bands. */
+       float boost = MAX16(0, leakage_to[b] - band_log2[b]) +
+             MAX16(0, band_log2[b] - (leakage_from[b]+LEAKAGE_OFFSET));
+       info->leak_boost[b] = IMIN(255, (int)floor(.5 + 64.f*boost));
+    }
+    for (;b<LEAK_BANDS;b++) info->leak_boost[b] = 0;
+
+    for (i=0;i<NB_FRAMES;i++)
+    {
+       int j;
+       float mindist = 1e15f;
+       for (j=0;j<NB_FRAMES;j++)
+       {
+          int k;
+          float dist=0;
+          for (k=0;k<NB_TBANDS;k++)
+          {
+             float tmp;
+             tmp = tonal->logE[i][k] - tonal->logE[j][k];
+             dist += tmp*tmp;
+          }
+          if (j!=i)
+             mindist = MIN32(mindist, dist);
+       }
+       spec_variability += mindist;
+    }
+    spec_variability = (float)sqrt(spec_variability/NB_FRAMES/NB_TBANDS);
     bandwidth_mask = 0;
     bandwidth = 0;
     maxE = 0;
     noise_floor = 5.7e-4f/(1<<(IMAX(0,lsb_depth-8)));
-#ifdef FIXED_POINT
-    noise_floor *= 1<<(15+SIG_SHIFT);
-#endif
     noise_floor *= noise_floor;
-    for (b=0;b<NB_TOT_BANDS;b++)
+    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 = extra_bands[b];
-       band_end = extra_bands[b+1];
+       band_start = tbands[b];
+       band_end = tbands[b+1];
        for (i=band_start;i<band_end;i++)
        {
           float binE = out[i].r*(float)out[i].r + out[N-i].r*(float)out[N-i].r
                      + out[i].i*(float)out[i].i + out[N-i].i*(float)out[N-i].i;
           E += binE;
        }
+       E = SCALE_ENER(E);
        maxE = MAX32(maxE, E);
+       if (band_start < 64)
+       {
+          below_max_pitch += E;
+       } else {
+          above_max_pitch += E;
+       }
        tonal->meanE[b] = MAX32((1-alphaE2)*tonal->meanE[b], E);
-       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))
-          bandwidth = b;
+       if (E*1e9f > maxE && (Em > 3*noise_floor*(band_end-band_start) || E > noise_floor*(band_end-band_start)))
+          bandwidth = b+1;
+       /* Check if the band is masked (see below). */
+       is_masked[b] = E < (tonal->prev_bandwidth >= b+1  ? .01f : .05f)*bandwidth_mask;
+       /* Use a simple follower with 13 dB/Bark slope for spreading function. */
+       bandwidth_mask = MAX32(.05f*bandwidth_mask, E);
     }
+    /* Special case for the last two bands, for which we don't have spectrum but only
+       the energy above 12 kHz. The difficulty here is that the high-pass we use
+       leaks some LF energy, so we need to increase the threshold without accidentally cutting
+       off the band. */
+    if (tonal->Fs == 48000) {
+       float noise_ratio;
+       float Em;
+       float E = hp_ener*(1.f/(60*60));
+       noise_ratio = tonal->prev_bandwidth==20 ? 10.f : 30.f;
+
+#ifdef FIXED_POINT
+       /* silk_resampler_down2_hp() shifted right by an extra 8 bits. */
+       E *= 256.f*(1.f/Q15ONE)*(1.f/Q15ONE);
+#endif
+       above_max_pitch += E;
+       tonal->meanE[b] = MAX32((1-alphaE2)*tonal->meanE[b], E);
+       Em = MAX32(E, tonal->meanE[b]);
+       if (Em > 3*noise_ratio*noise_floor*160 || E > noise_ratio*noise_floor*160)
+          bandwidth = 20;
+       /* Check if the band is masked (see below). */
+       is_masked[b] = E < (tonal->prev_bandwidth == 20  ? .01f : .05f)*bandwidth_mask;
+    }
+    if (above_max_pitch > below_max_pitch)
+       info->max_pitch_ratio = below_max_pitch/above_max_pitch;
+    else
+       info->max_pitch_ratio = 1;
+    /* In some cases, resampling aliasing can create a small amount of energy in the first band
+       being cut. So if the last band is masked, we don't include it.  */
+    if (bandwidth == 20 && is_masked[NB_TBANDS])
+       bandwidth-=2;
+    else if (bandwidth > 0 && bandwidth <= NB_TBANDS && is_masked[bandwidth-1])
+       bandwidth--;
     if (tonal->count<=2)
        bandwidth = 20;
     frame_loudness = 20*(float)log10(frame_loudness);
-    tonal->Etracker = MAX32(tonal->Etracker-.03f, frame_loudness);
+    tonal->Etracker = MAX32(tonal->Etracker-.003f, frame_loudness);
     tonal->lowECount *= (1-alphaE);
     if (frame_loudness < tonal->Etracker-30)
        tonal->lowECount += alphaE;
@@ -460,11 +863,18 @@ static void tonality_analysis(TonalityAnalysisState *tonal, const CELTMode *celt
           sum += dct_table[i*16+b]*logE[b];
        BFCC[i] = sum;
     }
+    for (i=0;i<8;i++)
+    {
+       float sum=0;
+       for (b=0;b<16;b++)
+          sum += dct_table[i*16+b]*.5f*(tonal->highE[b]+tonal->lowE[b]);
+       midE[i] = sum;
+    }
 
     frame_stationarity /= NB_TBANDS;
     relativeE /= NB_TBANDS;
     if (tonal->count<10)
-       relativeE = .5;
+       relativeE = .5f;
     frame_noisiness /= NB_TBANDS;
 #if 1
     info->activity = frame_noisiness + (1-frame_noisiness)*relativeE;
@@ -479,7 +889,7 @@ static void tonality_analysis(TonalityAnalysisState *tonal, const CELTMode *celt
     info->tonality_slope = slope;
 
     tonal->E_count = (tonal->E_count+1)%NB_FRAMES;
-    tonal->count++;
+    tonal->count = IMIN(tonal->count+1, ANALYSIS_COUNT_MAX);
     info->tonality = frame_tonality;
 
     for (i=0;i<4;i++)
@@ -498,6 +908,8 @@ static void tonality_analysis(TonalityAnalysisState *tonal, const CELTMode *celt
        for (i=0;i<9;i++)
           tonal->std[i] = (1-alpha)*tonal->std[i] + alpha*features[i]*features[i];
     }
+    for (i=0;i<4;i++)
+       features[i] = BFCC[i]-midE[i];
 
     for (i=0;i<8;i++)
     {
@@ -507,136 +919,31 @@ static void tonality_analysis(TonalityAnalysisState *tonal, const CELTMode *celt
        tonal->mem[i] = BFCC[i];
     }
     for (i=0;i<9;i++)
-       features[11+i] = (float)sqrt(tonal->std[i]);
-    features[20] = info->tonality;
-    features[21] = info->activity;
-    features[22] = frame_stationarity;
-    features[23] = info->tonality_slope;
-    features[24] = tonal->lowECount;
-
-#ifndef DISABLE_FLOAT_API
-    mlp_process(&net, features, frame_probs);
-    frame_probs[0] = .5f*(frame_probs[0]+1);
-    /* Curve fitting between the MLP probability and the actual probability */
-    frame_probs[0] = .01f + 1.21f*frame_probs[0]*frame_probs[0] - .23f*(float)pow(frame_probs[0], 10);
-    /* Probability of active audio (as opposed to silence) */
-    frame_probs[1] = .5f*frame_probs[1]+.5f;
-    /* Consider that silence has a 50-50 probability. */
-    frame_probs[0] = frame_probs[1]*frame_probs[0] + (1-frame_probs[1])*.5f;
-
-    /*printf("%f %f ", frame_probs[0], frame_probs[1]);*/
-    {
-       /* Probability of state transition */
-       float tau;
-       /* Represents independence of the MLP probabilities, where
-          beta=1 means fully independent. */
-       float beta;
-       /* Denormalized probability of speech (p0) and music (p1) after update */
-       float p0, p1;
-       /* Probabilities for "all speech" and "all music" */
-       float s0, m0;
-       /* Probability sum for renormalisation */
-       float psum;
-       /* Instantaneous probability of speech and music, with beta pre-applied. */
-       float speech0;
-       float music0;
-       float p, q;
-
-       /* One transition every 3 minutes of active audio */
-       tau = .00005f*frame_probs[1];
-       /* Adapt beta based on how "unexpected" the new prob is */
-       p = MAX16(.05f,MIN16(.95f,frame_probs[0]));
-       q = MAX16(.05f,MIN16(.95f,tonal->music_prob));
-       beta = .01f+.05f*ABS16(p-q)/(p*(1-q)+q*(1-p));
-       /* p0 and p1 are the probabilities of speech and music at this frame
-          using only information from previous frame and applying the
-          state transition model */
-       p0 = (1-tonal->music_prob)*(1-tau) +    tonal->music_prob *tau;
-       p1 =    tonal->music_prob *(1-tau) + (1-tonal->music_prob)*tau;
-       /* We apply the current probability with exponent beta to work around
-          the fact that the probability estimates aren't independent. */
-       p0 *= (float)pow(1-frame_probs[0], beta);
-       p1 *= (float)pow(frame_probs[0], beta);
-       /* Normalise the probabilities to get the Marokv probability of music. */
-       tonal->music_prob = p1/(p0+p1);
-       info->music_prob = tonal->music_prob;
-
-       /* This chunk of code deals with delayed decision. */
-       psum=1e-20f;
-       /* Instantaneous probability of speech and music, with beta pre-applied. */
-       speech0 = (float)pow(1-frame_probs[0], beta);
-       music0  = (float)pow(frame_probs[0], beta);
-       if (tonal->count==1)
-       {
-          tonal->pspeech[0]=.5;
-          tonal->pmusic [0]=.5;
-       }
-       /* Updated probability of having only speech (s0) or only music (m0),
-          before considering the new observation. */
-       s0 = tonal->pspeech[0] + tonal->pspeech[1];
-       m0 = tonal->pmusic [0] + tonal->pmusic [1];
-       /* Updates s0 and m0 with instantaneous probability. */
-       tonal->pspeech[0] = s0*(1-tau)*speech0;
-       tonal->pmusic [0] = m0*(1-tau)*music0;
-       /* Propagate the transition probabilities */
-       for (i=1;i<DETECT_SIZE-1;i++)
-       {
-          tonal->pspeech[i] = tonal->pspeech[i+1]*speech0;
-          tonal->pmusic [i] = tonal->pmusic [i+1]*music0;
-       }
-       /* Probability that the latest frame is speech, when all the previous ones were music. */
-       tonal->pspeech[DETECT_SIZE-1] = m0*tau*speech0;
-       /* Probability that the latest frame is music, when all the previous ones were speech. */
-       tonal->pmusic [DETECT_SIZE-1] = s0*tau*music0;
-
-       /* Renormalise probabilities to 1 */
-       for (i=0;i<DETECT_SIZE;i++)
-          psum += tonal->pspeech[i] + tonal->pmusic[i];
-       psum = 1.f/psum;
-       for (i=0;i<DETECT_SIZE;i++)
-       {
-          tonal->pspeech[i] *= psum;
-          tonal->pmusic [i] *= psum;
-       }
-       psum = tonal->pmusic[0];
-       for (i=1;i<DETECT_SIZE;i++)
-          psum += tonal->pspeech[i];
-
-       /* Estimate our confidence in the speech/music decisions */
-       if (frame_probs[1]>.75)
-       {
-          if (tonal->music_prob>.9)
-          {
-             float adapt;
-             adapt = 1.f/(++tonal->music_confidence_count);
-             tonal->music_confidence_count = IMIN(tonal->music_confidence_count, 500);
-             tonal->music_confidence += adapt*MAX16(-.2f,frame_probs[0]-tonal->music_confidence);
-          }
-          if (tonal->music_prob<.1)
-          {
-             float adapt;
-             adapt = 1.f/(++tonal->speech_confidence_count);
-             tonal->speech_confidence_count = IMIN(tonal->speech_confidence_count, 500);
-             tonal->speech_confidence += adapt*MIN16(.2f,frame_probs[0]-tonal->speech_confidence);
-          }
-       } else {
-          if (tonal->music_confidence_count==0)
-             tonal->music_confidence = .9f;
-          if (tonal->speech_confidence_count==0)
-             tonal->speech_confidence = .1f;
-       }
-    }
-    if (tonal->last_music != (tonal->music_prob>.5f))
-       tonal->last_transition=0;
-    tonal->last_music = tonal->music_prob>.5f;
-#else
-    info->music_prob = 0;
-#endif
-    /*for (i=0;i<25;i++)
+       features[11+i] = (float)sqrt(tonal->std[i]) - std_feature_bias[i];
+    features[18] = spec_variability - 0.78f;
+    features[20] = info->tonality - 0.154723f;
+    features[21] = info->activity - 0.724643f;
+    features[22] = frame_stationarity - 0.743717f;
+    features[23] = info->tonality_slope + 0.069216f;
+    features[24] = tonal->lowECount - 0.067930f;
+
+    compute_dense(&layer0, layer_out, features);
+    compute_gru(&layer1, tonal->rnn_state, layer_out);
+    compute_dense(&layer2, frame_probs, tonal->rnn_state);
+
+    /* Probability of speech or music vs noise */
+    info->activity_probability = frame_probs[1];
+    info->music_prob = frame_probs[0];
+
+    /*printf("%f %f %f\n", frame_probs[0], frame_probs[1], info->music_prob);*/
+#ifdef MLP_TRAINING
+    for (i=0;i<25;i++)
        printf("%f ", features[i]);
-    printf("\n");*/
+    printf("\n");
+#endif
 
     info->bandwidth = bandwidth;
+    tonal->prev_bandwidth = bandwidth;
     /*printf("%d %d\n", info->bandwidth, info->opus_bandwidth);*/
     info->noisiness = frame_noisiness;
     info->valid = 1;
@@ -650,23 +957,25 @@ void run_analysis(TonalityAnalysisState *analysis, const CELTMode *celt_mode, co
    int offset;
    int pcm_len;
 
+   analysis_frame_size -= analysis_frame_size&1;
    if (analysis_pcm != NULL)
    {
       /* Avoid overflow/wrap-around of the analysis buffer */
-      analysis_frame_size = IMIN((DETECT_SIZE-5)*Fs/100, analysis_frame_size);
+      analysis_frame_size = IMIN((DETECT_SIZE-5)*Fs/50, analysis_frame_size);
 
       pcm_len = analysis_frame_size - analysis->analysis_offset;
       offset = analysis->analysis_offset;
-      do {
-         tonality_analysis(analysis, celt_mode, analysis_pcm, IMIN(480, pcm_len), offset, c1, c2, C, lsb_depth, downmix);
-         offset += 480;
-         pcm_len -= 480;
-      } while (pcm_len>0);
+      while (pcm_len>0) {
+         tonality_analysis(analysis, celt_mode, analysis_pcm, IMIN(Fs/50, pcm_len), offset, c1, c2, C, lsb_depth, downmix);
+         offset += Fs/50;
+         pcm_len -= Fs/50;
+      }
       analysis->analysis_offset = analysis_frame_size;
 
       analysis->analysis_offset -= frame_size;
    }
 
-   analysis_info->valid = 0;
    tonality_get_info(analysis, analysis_info, frame_size);
 }
+
+#endif /* DISABLE_FLOAT_API */

+ 19 - 19
thirdparty/opus/analysis.h

@@ -30,16 +30,24 @@
 
 #include "celt.h"
 #include "opus_private.h"
+#include "mlp.h"
 
 #define NB_FRAMES 8
 #define NB_TBANDS 18
-#define NB_TOT_BANDS 21
-#define ANALYSIS_BUF_SIZE 720 /* 15 ms at 48 kHz */
+#define ANALYSIS_BUF_SIZE 720 /* 30 ms at 24 kHz */
 
-#define DETECT_SIZE 200
+/* At that point we can stop counting frames because it no longer matters. */
+#define ANALYSIS_COUNT_MAX 10000
+
+#define DETECT_SIZE 100
+
+/* Uncomment this to print the MLP features on stdout. */
+/*#define MLP_TRAINING*/
 
 typedef struct {
    int arch;
+   int application;
+   opus_int32 Fs;
 #define TONALITY_ANALYSIS_RESET_START angle
    float angle[240];
    float d_angle[240];
@@ -48,35 +56,27 @@ typedef struct {
    int   mem_fill;                      /* number of usable samples in the buffer */
    float prev_band_tonality[NB_TBANDS];
    float prev_tonality;
+   int prev_bandwidth;
    float E[NB_FRAMES][NB_TBANDS];
+   float logE[NB_FRAMES][NB_TBANDS];
    float lowE[NB_TBANDS];
    float highE[NB_TBANDS];
-   float meanE[NB_TOT_BANDS];
+   float meanE[NB_TBANDS+1];
    float mem[32];
    float cmean[8];
    float std[9];
-   float music_prob;
    float Etracker;
    float lowECount;
    int E_count;
-   int last_music;
-   int last_transition;
    int count;
-   float subframe_mem[3];
    int analysis_offset;
-   /** Probability of having speech for time i to DETECT_SIZE-1 (and music before).
-       pspeech[0] is the probability that all frames in the window are speech. */
-   float pspeech[DETECT_SIZE];
-   /** Probability of having music for time i to DETECT_SIZE-1 (and speech before).
-       pmusic[0] is the probability that all frames in the window are music. */
-   float pmusic[DETECT_SIZE];
-   float speech_confidence;
-   float music_confidence;
-   int speech_confidence_count;
-   int music_confidence_count;
    int write_pos;
    int read_pos;
    int read_subframe;
+   float hp_ener_accum;
+   int initialized;
+   float rnn_state[MAX_NEURONS];
+   opus_val32 downmix_state[3];
    AnalysisInfo info[DETECT_SIZE];
 } TonalityAnalysisState;
 
@@ -86,7 +86,7 @@ typedef struct {
  * not be repeated every analysis step. No allocated memory is retained
  * by the state struct, so no cleanup call is required.
  */
-void tonality_analysis_init(TonalityAnalysisState *analysis);
+void tonality_analysis_init(TonalityAnalysisState *analysis, opus_int32 Fs);
 
 /** Reset a TonalityAnalysisState stuct.
  *

+ 8 - 8
thirdparty/opus/celt/_kiss_fft_guts.h

@@ -58,12 +58,12 @@
 #   define S_MUL(a,b) MULT16_32_Q15(b, a)
 
 #   define C_MUL(m,a,b) \
-      do{ (m).r = SUB32(S_MUL((a).r,(b).r) , S_MUL((a).i,(b).i)); \
-          (m).i = ADD32(S_MUL((a).r,(b).i) , S_MUL((a).i,(b).r)); }while(0)
+      do{ (m).r = SUB32_ovflw(S_MUL((a).r,(b).r) , S_MUL((a).i,(b).i)); \
+          (m).i = ADD32_ovflw(S_MUL((a).r,(b).i) , S_MUL((a).i,(b).r)); }while(0)
 
 #   define C_MULC(m,a,b) \
-      do{ (m).r = ADD32(S_MUL((a).r,(b).r) , S_MUL((a).i,(b).i)); \
-          (m).i = SUB32(S_MUL((a).i,(b).r) , S_MUL((a).r,(b).i)); }while(0)
+      do{ (m).r = ADD32_ovflw(S_MUL((a).r,(b).r) , S_MUL((a).i,(b).i)); \
+          (m).i = SUB32_ovflw(S_MUL((a).i,(b).r) , S_MUL((a).r,(b).i)); }while(0)
 
 #   define C_MULBYSCALAR( c, s ) \
       do{ (c).r =  S_MUL( (c).r , s ) ;\
@@ -77,17 +77,17 @@
                 DIVSCALAR( (c).i  , div); }while (0)
 
 #define  C_ADD( res, a,b)\
-    do {(res).r=ADD32((a).r,(b).r);  (res).i=ADD32((a).i,(b).i); \
+    do {(res).r=ADD32_ovflw((a).r,(b).r);  (res).i=ADD32_ovflw((a).i,(b).i); \
     }while(0)
 #define  C_SUB( res, a,b)\
-    do {(res).r=SUB32((a).r,(b).r);  (res).i=SUB32((a).i,(b).i); \
+    do {(res).r=SUB32_ovflw((a).r,(b).r);  (res).i=SUB32_ovflw((a).i,(b).i); \
     }while(0)
 #define C_ADDTO( res , a)\
-    do {(res).r = ADD32((res).r, (a).r);  (res).i = ADD32((res).i,(a).i);\
+    do {(res).r = ADD32_ovflw((res).r, (a).r);  (res).i = ADD32_ovflw((res).i,(a).i);\
     }while(0)
 
 #define C_SUBFROM( res , a)\
-    do {(res).r = ADD32((res).r,(a).r);  (res).i = SUB32((res).i,(a).i); \
+    do {(res).r = ADD32_ovflw((res).r,(a).r);  (res).i = SUB32_ovflw((res).i,(a).i); \
     }while(0)
 
 #if defined(OPUS_ARM_INLINE_ASM)

+ 44 - 8
thirdparty/opus/celt/arch.h

@@ -46,25 +46,50 @@
 #  endif
 # endif
 
+#if OPUS_GNUC_PREREQ(3, 0)
+#define opus_likely(x)       (__builtin_expect(!!(x), 1))
+#define opus_unlikely(x)     (__builtin_expect(!!(x), 0))
+#else
+#define opus_likely(x)       (!!(x))
+#define opus_unlikely(x)     (!!(x))
+#endif
+
 #define CELT_SIG_SCALE 32768.f
 
-#define celt_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))
@@ -93,14 +118,20 @@ static OPUS_INLINE void _celt_fatal(const char *str, const char *file, int line)
 
 typedef opus_int16 opus_val16;
 typedef opus_int32 opus_val32;
+typedef opus_int64 opus_val64;
 
 typedef opus_val32 celt_sig;
 typedef opus_val16 celt_norm;
 typedef opus_val32 celt_ener;
 
+#define celt_isnan(x) 0
+
 #define Q15ONE 32767
 
 #define SIG_SHIFT 12
+/* Safe saturation value for 32-bit signals. Should be less than
+   2^31*(1-0.85) to avoid blowing up on DC at deemphasis.*/
+#define SIG_SAT (300000000)
 
 #define NORM_SCALING 16384
 
@@ -129,7 +160,7 @@ static OPUS_INLINE opus_int16 SAT16(opus_int32 x) {
 
 #ifdef OPUS_ARM_PRESUME_AARCH64_NEON_INTR
 #include "arm/fixed_arm64.h"
-#elif OPUS_ARM_INLINE_EDSP
+#elif defined (OPUS_ARM_INLINE_EDSP)
 #include "arm/fixed_armv5e.h"
 #elif defined (OPUS_ARM_INLINE_ASM)
 #include "arm/fixed_armv4.h"
@@ -147,6 +178,7 @@ static OPUS_INLINE opus_int16 SAT16(opus_int32 x) {
 
 typedef float opus_val16;
 typedef float opus_val32;
+typedef float opus_val64;
 
 typedef float celt_sig;
 typedef float celt_norm;
@@ -186,6 +218,7 @@ static OPUS_INLINE int celt_isnan(float x)
 
 #define NEG16(x) (-(x))
 #define NEG32(x) (-(x))
+#define NEG32_ovflw(x) (-(x))
 #define EXTRACT16(x) (x)
 #define EXTEND32(x) (x)
 #define SHR16(a,shift) (a)
@@ -202,6 +235,7 @@ static OPUS_INLINE int celt_isnan(float x)
 #define SATURATE16(x)   (x)
 
 #define ROUND16(a,shift)  (a)
+#define SROUND16(a,shift) (a)
 #define HALF16(x)       (.5f*(x))
 #define HALF32(x)       (.5f*(x))
 
@@ -209,6 +243,8 @@ static OPUS_INLINE int celt_isnan(float x)
 #define SUB16(a,b) ((a)-(b))
 #define ADD32(a,b) ((a)+(b))
 #define SUB32(a,b) ((a)-(b))
+#define ADD32_ovflw(a,b) ((a)+(b))
+#define SUB32_ovflw(a,b) ((a)-(b))
 #define MULT16_16_16(a,b)     ((a)*(b))
 #define MULT16_16(a,b)     ((opus_val32)(a)*(opus_val32)(b))
 #define MAC16_16(c,a,b)     ((c)+(opus_val32)(a)*(opus_val32)(b))
@@ -243,9 +279,9 @@ static OPUS_INLINE int celt_isnan(float x)
 
 #ifndef GLOBAL_STACK_SIZE
 #ifdef FIXED_POINT
-#define GLOBAL_STACK_SIZE 100000
+#define GLOBAL_STACK_SIZE 120000
 #else
-#define GLOBAL_STACK_SIZE 100000
+#define GLOBAL_STACK_SIZE 120000
 #endif
 #endif
 

+ 2 - 2
thirdparty/opus/celt/arm/arm2gnu.pl

@@ -164,11 +164,11 @@ while (<>) {
         $prefix = "";
         if ($proc)
         {
-            $prefix = $prefix.sprintf("\t.type\t%s, %%function; ",$proc) unless ($apple);
+            $prefix = $prefix.sprintf("\t.type\t%s, %%function", $proc) unless ($apple);
             # Make sure we $prefix isn't empty here (for the $apple case).
             # We handle mangling the label here, make sure it doesn't match
             # the label handling below (if $prefix would be empty).
-            $prefix = "; ";
+            $prefix = $prefix."; ";
             push(@proc_stack, $proc);
             s/^[A-Za-z_\.]\w+/$symprefix$&:/;
         }

+ 19 - 2
thirdparty/opus/celt/arm/arm_celt_map.c

@@ -35,12 +35,29 @@
 
 #if defined(OPUS_HAVE_RTCD)
 
+# if defined(OPUS_ARM_MAY_HAVE_NEON_INTR) && !defined(OPUS_ARM_PRESUME_NEON_INTR)
+opus_val32 (*const CELT_INNER_PROD_IMPL[OPUS_ARCHMASK+1])(const opus_val16 *x, const opus_val16 *y, int N) = {
+  celt_inner_prod_c,   /* ARMv4 */
+  celt_inner_prod_c,   /* EDSP */
+  celt_inner_prod_c,   /* Media */
+  celt_inner_prod_neon /* NEON */
+};
+
+void (*const DUAL_INNER_PROD_IMPL[OPUS_ARCHMASK+1])(const opus_val16 *x, const opus_val16 *y01, const opus_val16 *y02,
+      int N, opus_val32 *xy1, opus_val32 *xy2) = {
+  dual_inner_prod_c,   /* ARMv4 */
+  dual_inner_prod_c,   /* EDSP */
+  dual_inner_prod_c,   /* Media */
+  dual_inner_prod_neon /* NEON */
+};
+# endif
+
 # if defined(FIXED_POINT)
 #  if ((defined(OPUS_ARM_MAY_HAVE_NEON) && !defined(OPUS_ARM_PRESUME_NEON)) || \
     (defined(OPUS_ARM_MAY_HAVE_MEDIA) && !defined(OPUS_ARM_PRESUME_MEDIA)) || \
     (defined(OPUS_ARM_MAY_HAVE_EDSP) && !defined(OPUS_ARM_PRESUME_EDSP)))
 opus_val32 (*const CELT_PITCH_XCORR_IMPL[OPUS_ARCHMASK+1])(const opus_val16 *,
-    const opus_val16 *, opus_val32 *, int , int) = {
+    const opus_val16 *, opus_val32 *, int, int, int) = {
   celt_pitch_xcorr_c,               /* ARMv4 */
   MAY_HAVE_EDSP(celt_pitch_xcorr),  /* EDSP */
   MAY_HAVE_MEDIA(celt_pitch_xcorr), /* Media */
@@ -51,7 +68,7 @@ opus_val32 (*const CELT_PITCH_XCORR_IMPL[OPUS_ARCHMASK+1])(const opus_val16 *,
 # else /* !FIXED_POINT */
 #  if defined(OPUS_ARM_MAY_HAVE_NEON_INTR) && !defined(OPUS_ARM_PRESUME_NEON_INTR)
 void (*const CELT_PITCH_XCORR_IMPL[OPUS_ARCHMASK+1])(const opus_val16 *,
-    const opus_val16 *, opus_val32 *, int, int) = {
+    const opus_val16 *, opus_val32 *, int, int, int) = {
   celt_pitch_xcorr_c,              /* ARMv4 */
   celt_pitch_xcorr_c,              /* EDSP */
   celt_pitch_xcorr_c,              /* Media */

+ 1 - 2
thirdparty/opus/celt/arm/celt_ne10_fft.c → thirdparty/opus/celt/arm/celt_fft_ne10.c

@@ -1,7 +1,7 @@
 /* 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
  */
 
@@ -36,7 +36,6 @@
 #endif
 #endif
 
-#include <NE10_init.h>
 #include <NE10_dsp.h>
 #include "os_support.h"
 #include "kiss_fft.h"

+ 1 - 1
thirdparty/opus/celt/arm/celt_ne10_mdct.c → thirdparty/opus/celt/arm/celt_mdct_ne10.c

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

+ 5 - 105
thirdparty/opus/celt/arm/celt_neon_intr.c

@@ -191,121 +191,21 @@ static void xcorr_kernel_neon_float(const float32_t *x, const float32_t *y,
    vst1q_f32(sum, SUMM);
 }
 
-/*
- * Function: xcorr_kernel_neon_float_process1
- * ---------------------------------
- * Computes single correlation values and stores in *sum
- */
-static void xcorr_kernel_neon_float_process1(const float32_t *x,
-      const float32_t *y, float32_t *sum, int len) {
-   float32x4_t XX[4];
-   float32x4_t YY[4];
-   float32x2_t XX_2;
-   float32x2_t YY_2;
-   float32x4_t SUMM;
-   float32x2_t SUMM_2[2];
-   const float32_t *xi = x;
-   const float32_t *yi = y;
-
-   SUMM = vdupq_n_f32(0);
-
-   /* Work on 16 values per iteration */
-   while (len >= 16) {
-      XX[0] = vld1q_f32(xi);
-      xi += 4;
-      XX[1] = vld1q_f32(xi);
-      xi += 4;
-      XX[2] = vld1q_f32(xi);
-      xi += 4;
-      XX[3] = vld1q_f32(xi);
-      xi += 4;
-
-      YY[0] = vld1q_f32(yi);
-      yi += 4;
-      YY[1] = vld1q_f32(yi);
-      yi += 4;
-      YY[2] = vld1q_f32(yi);
-      yi += 4;
-      YY[3] = vld1q_f32(yi);
-      yi += 4;
-
-      SUMM = vmlaq_f32(SUMM, YY[0], XX[0]);
-      SUMM = vmlaq_f32(SUMM, YY[1], XX[1]);
-      SUMM = vmlaq_f32(SUMM, YY[2], XX[2]);
-      SUMM = vmlaq_f32(SUMM, YY[3], XX[3]);
-      len -= 16;
-   }
-
-   /* Work on 8 values */
-   if (len >= 8) {
-      XX[0] = vld1q_f32(xi);
-      xi += 4;
-      XX[1] = vld1q_f32(xi);
-      xi += 4;
-
-      YY[0] = vld1q_f32(yi);
-      yi += 4;
-      YY[1] = vld1q_f32(yi);
-      yi += 4;
-
-      SUMM = vmlaq_f32(SUMM, YY[0], XX[0]);
-      SUMM = vmlaq_f32(SUMM, YY[1], XX[1]);
-      len -= 8;
-   }
-
-   /* Work on 4 values */
-   if (len >= 4) {
-      XX[0] = vld1q_f32(xi);
-      xi += 4;
-      YY[0] = vld1q_f32(yi);
-      yi += 4;
-      SUMM = vmlaq_f32(SUMM, YY[0], XX[0]);
-      len -= 4;
-   }
-
-   /* Start accumulating results */
-   SUMM_2[0] = vget_low_f32(SUMM);
-   if (len >= 2) {
-      /* While at it, consume 2 more values if available */
-      XX_2 = vld1_f32(xi);
-      xi += 2;
-      YY_2 = vld1_f32(yi);
-      yi += 2;
-      SUMM_2[0] = vmla_f32(SUMM_2[0], YY_2, XX_2);
-      len -= 2;
-   }
-   SUMM_2[1] = vget_high_f32(SUMM);
-   SUMM_2[0] = vadd_f32(SUMM_2[0], SUMM_2[1]);
-   SUMM_2[0] = vpadd_f32(SUMM_2[0], SUMM_2[0]);
-   /* Ok, now we have result accumulated in SUMM_2[0].0 */
-
-   if (len > 0) {
-      /* Case when you have one value left */
-      XX_2 = vld1_dup_f32(xi);
-      YY_2 = vld1_dup_f32(yi);
-      SUMM_2[0] = vmla_f32(SUMM_2[0], XX_2, YY_2);
-   }
-
-   vst1_lane_f32(sum, SUMM_2[0], 0);
-}
-
 void celt_pitch_xcorr_float_neon(const opus_val16 *_x, const opus_val16 *_y,
-                        opus_val32 *xcorr, int len, int max_pitch) {
+                        opus_val32 *xcorr, int len, int max_pitch, int arch) {
    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,
             (float32_t *)xcorr+i, len);
    }
 
-   /* In case max_pitch isn't multiple of 4
-    * compute single correlation value per iteration
-    */
+   /* In case max_pitch isn't a multiple of 4, do non-unrolled version. */
    for (; i < max_pitch; i++) {
-      xcorr_kernel_neon_float_process1((const float32_t *)_x,
-            (const float32_t *)_y+i, (float32_t *)xcorr+i, len);
+      xcorr[i] = celt_inner_prod_neon(_x, _y+i, len);
    }
 }
 #endif

+ 0 - 551
thirdparty/opus/celt/arm/celt_pitch_xcorr_arm-gnu.S

@@ -1,551 +0,0 @@
-    .syntax unified
-@ Copyright (c) 2007-2008 CSIRO
-@ Copyright (c) 2007-2009 Xiph.Org Foundation
-@ Copyright (c) 2013      Parrot
-@ Written by Aurélien Zanelli
-@
-@ Redistribution and use in source and binary forms, with or without
-@ modification, are permitted provided that the following conditions
-@ are met:
-@
-@ - Redistributions of source code must retain the above copyright
-@ notice, this list of conditions and the following disclaimer.
-@
-@ - Redistributions in binary form must reproduce the above copyright
-@ notice, this list of conditions and the following disclaimer in the
-@ documentation and/or other materials provided with the distribution.
-@
-@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-@ ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-@ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-@ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
-@ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-@ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-@ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-@ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-@ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-@ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-    .text;   .p2align 2;   .arch armv7-a
-   .fpu neon
-   .object_arch armv4t
-
-  .include "celt/arm/armopts-gnu.S"
-
- .if OPUS_ARM_MAY_HAVE_EDSP
-  .global celt_pitch_xcorr_edsp
- .endif
-
- .if OPUS_ARM_MAY_HAVE_NEON
-  .global celt_pitch_xcorr_neon
- .endif
-
- .if OPUS_ARM_MAY_HAVE_NEON
-
-@ Compute sum[k]=sum(x[j]*y[j+k],j=0...len-1), k=0...3
-; xcorr_kernel_neon: @ PROC
-xcorr_kernel_neon_start:
-  @ input:
-  @   r3     = int         len
-  @   r4     = opus_val16 *x
-  @   r5     = opus_val16 *y
-  @   q0     = opus_val32  sum[4]
-  @ output:
-  @   q0     = opus_val32  sum[4]
-  @ preserved: r0-r3, r6-r11, d2, q4-q7, q9-q15
-  @ internal usage:
-  @   r12 = int j
-  @   d3  = y_3|y_2|y_1|y_0
-  @   q2  = y_B|y_A|y_9|y_8|y_7|y_6|y_5|y_4
-  @   q3  = x_7|x_6|x_5|x_4|x_3|x_2|x_1|x_0
-  @   q8  = scratch
-  @
-  @ Load y[0...3]
-  @ This requires len>0 to always be valid (which we assert in the C code).
-  VLD1.16      {d5}, [r5]!
-  SUBS         r12, r3, #8
-  BLE xcorr_kernel_neon_process4
-@ Process 8 samples at a time.
-@ This loop loads one y value more than we actually need. Therefore we have to
-@ stop as soon as there are 8 or fewer samples left (instead of 7), to avoid
-@ reading past the end of the array.
-xcorr_kernel_neon_process8:
-  @ This loop has 19 total instructions (10 cycles to issue, minimum), with
-  @ - 2 cycles of ARM insrtuctions,
-  @ - 10 cycles of load/store/byte permute instructions, and
-  @ - 9 cycles of data processing instructions.
-  @ On a Cortex A8, we dual-issue the maximum amount (9 cycles) between the
-  @ latter two categories, meaning the whole loop should run in 10 cycles per
-  @ iteration, barring cache misses.
-  @
-  @ Load x[0...7]
-  VLD1.16      {d6, d7}, [r4]!
-  @ Unlike VMOV, VAND is a data processsing instruction (and doesn't get
-  @ assembled to VMOV, like VORR would), so it dual-issues with the prior VLD1.
-  VAND         d3, d5, d5
-  SUBS         r12, r12, #8
-  @ Load y[4...11]
-  VLD1.16      {d4, d5}, [r5]!
-  VMLAL.S16    q0, d3, d6[0]
-  VEXT.16      d16, d3, d4, #1
-  VMLAL.S16    q0, d4, d7[0]
-  VEXT.16      d17, d4, d5, #1
-  VMLAL.S16    q0, d16, d6[1]
-  VEXT.16      d16, d3, d4, #2
-  VMLAL.S16    q0, d17, d7[1]
-  VEXT.16      d17, d4, d5, #2
-  VMLAL.S16    q0, d16, d6[2]
-  VEXT.16      d16, d3, d4, #3
-  VMLAL.S16    q0, d17, d7[2]
-  VEXT.16      d17, d4, d5, #3
-  VMLAL.S16    q0, d16, d6[3]
-  VMLAL.S16    q0, d17, d7[3]
-  BGT xcorr_kernel_neon_process8
-@ Process 4 samples here if we have > 4 left (still reading one extra y value).
-xcorr_kernel_neon_process4:
-  ADDS         r12, r12, #4
-  BLE xcorr_kernel_neon_process2
-  @ Load x[0...3]
-  VLD1.16      d6, [r4]!
-  @ Use VAND since it's a data processing instruction again.
-  VAND         d4, d5, d5
-  SUB          r12, r12, #4
-  @ Load y[4...7]
-  VLD1.16      d5, [r5]!
-  VMLAL.S16    q0, d4, d6[0]
-  VEXT.16      d16, d4, d5, #1
-  VMLAL.S16    q0, d16, d6[1]
-  VEXT.16      d16, d4, d5, #2
-  VMLAL.S16    q0, d16, d6[2]
-  VEXT.16      d16, d4, d5, #3
-  VMLAL.S16    q0, d16, d6[3]
-@ Process 2 samples here if we have > 2 left (still reading one extra y value).
-xcorr_kernel_neon_process2:
-  ADDS         r12, r12, #2
-  BLE xcorr_kernel_neon_process1
-  @ Load x[0...1]
-  VLD2.16      {d6[],d7[]}, [r4]!
-  @ Use VAND since it's a data processing instruction again.
-  VAND         d4, d5, d5
-  SUB          r12, r12, #2
-  @ Load y[4...5]
-  VLD1.32      {d5[]}, [r5]!
-  VMLAL.S16    q0, d4, d6
-  VEXT.16      d16, d4, d5, #1
-  @ Replace bottom copy of {y5,y4} in d5 with {y3,y2} from d4, using VSRI
-  @ instead of VEXT, since it's a data-processing instruction.
-  VSRI.64      d5, d4, #32
-  VMLAL.S16    q0, d16, d7
-@ Process 1 sample using the extra y value we loaded above.
-xcorr_kernel_neon_process1:
-  @ Load next *x
-  VLD1.16      {d6[]}, [r4]!
-  ADDS         r12, r12, #1
-  @ y[0...3] are left in d5 from prior iteration(s) (if any)
-  VMLAL.S16    q0, d5, d6
-  MOVLE        pc, lr
-@ Now process 1 last sample, not reading ahead.
-  @ Load last *y
-  VLD1.16      {d4[]}, [r5]!
-  VSRI.64      d4, d5, #16
-  @ Load last *x
-  VLD1.16      {d6[]}, [r4]!
-  VMLAL.S16    q0, d4, d6
-  MOV          pc, lr
-	.size xcorr_kernel_neon, .-xcorr_kernel_neon  @ ENDP
-
-@ opus_val32 celt_pitch_xcorr_neon(opus_val16 *_x, opus_val16 *_y,
-@  opus_val32 *xcorr, int len, int max_pitch)
-; celt_pitch_xcorr_neon: @ PROC
-  @ input:
-  @   r0  = opus_val16 *_x
-  @   r1  = opus_val16 *_y
-  @   r2  = opus_val32 *xcorr
-  @   r3  = int         len
-  @ output:
-  @   r0  = int         maxcorr
-  @ internal usage:
-  @   r4  = opus_val16 *x (for xcorr_kernel_neon())
-  @   r5  = opus_val16 *y (for xcorr_kernel_neon())
-  @   r6  = int         max_pitch
-  @   r12 = int         j
-  @   q15 = int         maxcorr[4] (q15 is not used by xcorr_kernel_neon())
-  STMFD        sp!, {r4-r6, lr}
-  LDR          r6, [sp, #16]
-  VMOV.S32     q15, #1
-  @ if (max_pitch < 4) goto celt_pitch_xcorr_neon_process4_done
-  SUBS         r6, r6, #4
-  BLT celt_pitch_xcorr_neon_process4_done
-celt_pitch_xcorr_neon_process4:
-  @ xcorr_kernel_neon parameters:
-  @ r3 = len, r4 = _x, r5 = _y, q0 = {0, 0, 0, 0}
-  MOV          r4, r0
-  MOV          r5, r1
-  VEOR         q0, q0, q0
-  @ xcorr_kernel_neon only modifies r4, r5, r12, and q0...q3.
-  @ So we don't save/restore any other registers.
-  BL xcorr_kernel_neon_start
-  SUBS         r6, r6, #4
-  VST1.32      {q0}, [r2]!
-  @ _y += 4
-  ADD          r1, r1, #8
-  VMAX.S32     q15, q15, q0
-  @ if (max_pitch < 4) goto celt_pitch_xcorr_neon_process4_done
-  BGE celt_pitch_xcorr_neon_process4
-@ We have less than 4 sums left to compute.
-celt_pitch_xcorr_neon_process4_done:
-  ADDS         r6, r6, #4
-  @ Reduce maxcorr to a single value
-  VMAX.S32     d30, d30, d31
-  VPMAX.S32    d30, d30, d30
-  @ if (max_pitch <= 0) goto celt_pitch_xcorr_neon_done
-  BLE celt_pitch_xcorr_neon_done
-@ Now compute each remaining sum one at a time.
-celt_pitch_xcorr_neon_process_remaining:
-  MOV          r4, r0
-  MOV          r5, r1
-  VMOV.I32     q0, #0
-  SUBS         r12, r3, #8
-  BLT celt_pitch_xcorr_neon_process_remaining4
-@ Sum terms 8 at a time.
-celt_pitch_xcorr_neon_process_remaining_loop8:
-  @ Load x[0...7]
-  VLD1.16      {q1}, [r4]!
-  @ Load y[0...7]
-  VLD1.16      {q2}, [r5]!
-  SUBS         r12, r12, #8
-  VMLAL.S16    q0, d4, d2
-  VMLAL.S16    q0, d5, d3
-  BGE celt_pitch_xcorr_neon_process_remaining_loop8
-@ Sum terms 4 at a time.
-celt_pitch_xcorr_neon_process_remaining4:
-  ADDS         r12, r12, #4
-  BLT celt_pitch_xcorr_neon_process_remaining4_done
-  @ Load x[0...3]
-  VLD1.16      {d2}, [r4]!
-  @ Load y[0...3]
-  VLD1.16      {d3}, [r5]!
-  SUB          r12, r12, #4
-  VMLAL.S16    q0, d3, d2
-celt_pitch_xcorr_neon_process_remaining4_done:
-  @ Reduce the sum to a single value.
-  VADD.S32     d0, d0, d1
-  VPADDL.S32   d0, d0
-  ADDS         r12, r12, #4
-  BLE celt_pitch_xcorr_neon_process_remaining_loop_done
-@ Sum terms 1 at a time.
-celt_pitch_xcorr_neon_process_remaining_loop1:
-  VLD1.16      {d2[]}, [r4]!
-  VLD1.16      {d3[]}, [r5]!
-  SUBS         r12, r12, #1
-  VMLAL.S16    q0, d2, d3
-  BGT celt_pitch_xcorr_neon_process_remaining_loop1
-celt_pitch_xcorr_neon_process_remaining_loop_done:
-  VST1.32      {d0[0]}, [r2]!
-  VMAX.S32     d30, d30, d0
-  SUBS         r6, r6, #1
-  @ _y++
-  ADD          r1, r1, #2
-  @ if (--max_pitch > 0) goto celt_pitch_xcorr_neon_process_remaining
-  BGT celt_pitch_xcorr_neon_process_remaining
-celt_pitch_xcorr_neon_done:
-  VMOV.32      r0, d30[0]
-  LDMFD        sp!, {r4-r6, pc}
-	.size celt_pitch_xcorr_neon, .-celt_pitch_xcorr_neon  @ ENDP
-
- .endif
-
- .if OPUS_ARM_MAY_HAVE_EDSP
-
-@ This will get used on ARMv7 devices without NEON, so it has been optimized
-@ to take advantage of dual-issuing where possible.
-; xcorr_kernel_edsp: @ PROC
-xcorr_kernel_edsp_start:
-  @ input:
-  @   r3      = int         len
-  @   r4      = opus_val16 *_x (must be 32-bit aligned)
-  @   r5      = opus_val16 *_y (must be 32-bit aligned)
-  @   r6...r9 = opus_val32  sum[4]
-  @ output:
-  @   r6...r9 = opus_val32  sum[4]
-  @ preserved: r0-r5
-  @ internal usage
-  @   r2      = int         j
-  @   r12,r14 = opus_val16  x[4]
-  @   r10,r11 = opus_val16  y[4]
-  STMFD        sp!, {r2,r4,r5,lr}
-  LDR          r10, [r5], #4      @ Load y[0...1]
-  SUBS         r2, r3, #4         @ j = len-4
-  LDR          r11, [r5], #4      @ Load y[2...3]
-  BLE xcorr_kernel_edsp_process4_done
-  LDR          r12, [r4], #4      @ Load x[0...1]
-  @ Stall
-xcorr_kernel_edsp_process4:
-  @ The multiplies must issue from pipeline 0, and can't dual-issue with each
-  @ other. Every other instruction here dual-issues with a multiply, and is
-  @ thus "free". There should be no stalls in the body of the loop.
-  SMLABB       r6, r12, r10, r6   @ sum[0] = MAC16_16(sum[0],x_0,y_0)
-  LDR          r14, [r4], #4      @ Load x[2...3]
-  SMLABT       r7, r12, r10, r7   @ sum[1] = MAC16_16(sum[1],x_0,y_1)
-  SUBS         r2, r2, #4         @ j-=4
-  SMLABB       r8, r12, r11, r8   @ sum[2] = MAC16_16(sum[2],x_0,y_2)
-  SMLABT       r9, r12, r11, r9   @ sum[3] = MAC16_16(sum[3],x_0,y_3)
-  SMLATT       r6, r12, r10, r6   @ sum[0] = MAC16_16(sum[0],x_1,y_1)
-  LDR          r10, [r5], #4      @ Load y[4...5]
-  SMLATB       r7, r12, r11, r7   @ sum[1] = MAC16_16(sum[1],x_1,y_2)
-  SMLATT       r8, r12, r11, r8   @ sum[2] = MAC16_16(sum[2],x_1,y_3)
-  SMLATB       r9, r12, r10, r9   @ sum[3] = MAC16_16(sum[3],x_1,y_4)
-  LDRGT        r12, [r4], #4      @ Load x[0...1]
-  SMLABB       r6, r14, r11, r6   @ sum[0] = MAC16_16(sum[0],x_2,y_2)
-  SMLABT       r7, r14, r11, r7   @ sum[1] = MAC16_16(sum[1],x_2,y_3)
-  SMLABB       r8, r14, r10, r8   @ sum[2] = MAC16_16(sum[2],x_2,y_4)
-  SMLABT       r9, r14, r10, r9   @ sum[3] = MAC16_16(sum[3],x_2,y_5)
-  SMLATT       r6, r14, r11, r6   @ sum[0] = MAC16_16(sum[0],x_3,y_3)
-  LDR          r11, [r5], #4      @ Load y[6...7]
-  SMLATB       r7, r14, r10, r7   @ sum[1] = MAC16_16(sum[1],x_3,y_4)
-  SMLATT       r8, r14, r10, r8   @ sum[2] = MAC16_16(sum[2],x_3,y_5)
-  SMLATB       r9, r14, r11, r9   @ sum[3] = MAC16_16(sum[3],x_3,y_6)
-  BGT xcorr_kernel_edsp_process4
-xcorr_kernel_edsp_process4_done:
-  ADDS         r2, r2, #4
-  BLE xcorr_kernel_edsp_done
-  LDRH         r12, [r4], #2      @ r12 = *x++
-  SUBS         r2, r2, #1         @ j--
-  @ Stall
-  SMLABB       r6, r12, r10, r6   @ sum[0] = MAC16_16(sum[0],x,y_0)
-  LDRHGT       r14, [r4], #2      @ r14 = *x++
-  SMLABT       r7, r12, r10, r7   @ sum[1] = MAC16_16(sum[1],x,y_1)
-  SMLABB       r8, r12, r11, r8   @ sum[2] = MAC16_16(sum[2],x,y_2)
-  SMLABT       r9, r12, r11, r9   @ sum[3] = MAC16_16(sum[3],x,y_3)
-  BLE xcorr_kernel_edsp_done
-  SMLABT       r6, r14, r10, r6   @ sum[0] = MAC16_16(sum[0],x,y_1)
-  SUBS         r2, r2, #1         @ j--
-  SMLABB       r7, r14, r11, r7   @ sum[1] = MAC16_16(sum[1],x,y_2)
-  LDRH         r10, [r5], #2      @ r10 = y_4 = *y++
-  SMLABT       r8, r14, r11, r8   @ sum[2] = MAC16_16(sum[2],x,y_3)
-  LDRHGT       r12, [r4], #2      @ r12 = *x++
-  SMLABB       r9, r14, r10, r9   @ sum[3] = MAC16_16(sum[3],x,y_4)
-  BLE xcorr_kernel_edsp_done
-  SMLABB       r6, r12, r11, r6   @ sum[0] = MAC16_16(sum[0],tmp,y_2)
-  CMP          r2, #1             @ j--
-  SMLABT       r7, r12, r11, r7   @ sum[1] = MAC16_16(sum[1],tmp,y_3)
-  LDRH         r2, [r5], #2       @ r2 = y_5 = *y++
-  SMLABB       r8, r12, r10, r8   @ sum[2] = MAC16_16(sum[2],tmp,y_4)
-  LDRHGT       r14, [r4]          @ r14 = *x
-  SMLABB       r9, r12, r2, r9    @ sum[3] = MAC16_16(sum[3],tmp,y_5)
-  BLE xcorr_kernel_edsp_done
-  SMLABT       r6, r14, r11, r6   @ sum[0] = MAC16_16(sum[0],tmp,y_3)
-  LDRH         r11, [r5]          @ r11 = y_6 = *y
-  SMLABB       r7, r14, r10, r7   @ sum[1] = MAC16_16(sum[1],tmp,y_4)
-  SMLABB       r8, r14, r2, r8    @ sum[2] = MAC16_16(sum[2],tmp,y_5)
-  SMLABB       r9, r14, r11, r9   @ sum[3] = MAC16_16(sum[3],tmp,y_6)
-xcorr_kernel_edsp_done:
-  LDMFD        sp!, {r2,r4,r5,pc}
-	.size xcorr_kernel_edsp, .-xcorr_kernel_edsp  @ ENDP
-
-; celt_pitch_xcorr_edsp: @ PROC
-  @ input:
-  @   r0  = opus_val16 *_x (must be 32-bit aligned)
-  @   r1  = opus_val16 *_y (only needs to be 16-bit aligned)
-  @   r2  = opus_val32 *xcorr
-  @   r3  = int         len
-  @ output:
-  @   r0  = maxcorr
-  @ internal usage
-  @   r4  = opus_val16 *x
-  @   r5  = opus_val16 *y
-  @   r6  = opus_val32  sum0
-  @   r7  = opus_val32  sum1
-  @   r8  = opus_val32  sum2
-  @   r9  = opus_val32  sum3
-  @   r1  = int         max_pitch
-  @   r12 = int         j
-  STMFD        sp!, {r4-r11, lr}
-  MOV          r5, r1
-  LDR          r1, [sp, #36]
-  MOV          r4, r0
-  TST          r5, #3
-  @ maxcorr = 1
-  MOV          r0, #1
-  BEQ          celt_pitch_xcorr_edsp_process1u_done
-@ Compute one sum at the start to make y 32-bit aligned.
-  SUBS         r12, r3, #4
-  @ r14 = sum = 0
-  MOV          r14, #0
-  LDRH         r8, [r5], #2
-  BLE celt_pitch_xcorr_edsp_process1u_loop4_done
-  LDR          r6, [r4], #4
-  MOV          r8, r8, LSL #16
-celt_pitch_xcorr_edsp_process1u_loop4:
-  LDR          r9, [r5], #4
-  SMLABT       r14, r6, r8, r14     @ sum = MAC16_16(sum, x_0, y_0)
-  LDR          r7, [r4], #4
-  SMLATB       r14, r6, r9, r14     @ sum = MAC16_16(sum, x_1, y_1)
-  LDR          r8, [r5], #4
-  SMLABT       r14, r7, r9, r14     @ sum = MAC16_16(sum, x_2, y_2)
-  SUBS         r12, r12, #4         @ j-=4
-  SMLATB       r14, r7, r8, r14     @ sum = MAC16_16(sum, x_3, y_3)
-  LDRGT        r6, [r4], #4
-  BGT celt_pitch_xcorr_edsp_process1u_loop4
-  MOV          r8, r8, LSR #16
-celt_pitch_xcorr_edsp_process1u_loop4_done:
-  ADDS         r12, r12, #4
-celt_pitch_xcorr_edsp_process1u_loop1:
-  LDRHGE       r6, [r4], #2
-  @ Stall
-  SMLABBGE     r14, r6, r8, r14    @ sum = MAC16_16(sum, *x, *y)
-  SUBSGE       r12, r12, #1
-  LDRHGT       r8, [r5], #2
-  BGT celt_pitch_xcorr_edsp_process1u_loop1
-  @ Restore _x
-  SUB          r4, r4, r3, LSL #1
-  @ Restore and advance _y
-  SUB          r5, r5, r3, LSL #1
-  @ maxcorr = max(maxcorr, sum)
-  CMP          r0, r14
-  ADD          r5, r5, #2
-  MOVLT        r0, r14
-  SUBS         r1, r1, #1
-  @ xcorr[i] = sum
-  STR          r14, [r2], #4
-  BLE celt_pitch_xcorr_edsp_done
-celt_pitch_xcorr_edsp_process1u_done:
-  @ if (max_pitch < 4) goto celt_pitch_xcorr_edsp_process2
-  SUBS         r1, r1, #4
-  BLT celt_pitch_xcorr_edsp_process2
-celt_pitch_xcorr_edsp_process4:
-  @ xcorr_kernel_edsp parameters:
-  @ r3 = len, r4 = _x, r5 = _y, r6...r9 = sum[4] = {0, 0, 0, 0}
-  MOV          r6, #0
-  MOV          r7, #0
-  MOV          r8, #0
-  MOV          r9, #0
-  BL xcorr_kernel_edsp_start  @ xcorr_kernel_edsp(_x, _y+i, xcorr+i, len)
-  @ maxcorr = max(maxcorr, sum0, sum1, sum2, sum3)
-  CMP          r0, r6
-  @ _y+=4
-  ADD          r5, r5, #8
-  MOVLT        r0, r6
-  CMP          r0, r7
-  MOVLT        r0, r7
-  CMP          r0, r8
-  MOVLT        r0, r8
-  CMP          r0, r9
-  MOVLT        r0, r9
-  STMIA        r2!, {r6-r9}
-  SUBS         r1, r1, #4
-  BGE celt_pitch_xcorr_edsp_process4
-celt_pitch_xcorr_edsp_process2:
-  ADDS         r1, r1, #2
-  BLT celt_pitch_xcorr_edsp_process1a
-  SUBS         r12, r3, #4
-  @ {r10, r11} = {sum0, sum1} = {0, 0}
-  MOV          r10, #0
-  MOV          r11, #0
-  LDR          r8, [r5], #4
-  BLE celt_pitch_xcorr_edsp_process2_loop_done
-  LDR          r6, [r4], #4
-  LDR          r9, [r5], #4
-celt_pitch_xcorr_edsp_process2_loop4:
-  SMLABB       r10, r6, r8, r10     @ sum0 = MAC16_16(sum0, x_0, y_0)
-  LDR          r7, [r4], #4
-  SMLABT       r11, r6, r8, r11     @ sum1 = MAC16_16(sum1, x_0, y_1)
-  SUBS         r12, r12, #4         @ j-=4
-  SMLATT       r10, r6, r8, r10     @ sum0 = MAC16_16(sum0, x_1, y_1)
-  LDR          r8, [r5], #4
-  SMLATB       r11, r6, r9, r11     @ sum1 = MAC16_16(sum1, x_1, y_2)
-  LDRGT        r6, [r4], #4
-  SMLABB       r10, r7, r9, r10     @ sum0 = MAC16_16(sum0, x_2, y_2)
-  SMLABT       r11, r7, r9, r11     @ sum1 = MAC16_16(sum1, x_2, y_3)
-  SMLATT       r10, r7, r9, r10     @ sum0 = MAC16_16(sum0, x_3, y_3)
-  LDRGT        r9, [r5], #4
-  SMLATB       r11, r7, r8, r11     @ sum1 = MAC16_16(sum1, x_3, y_4)
-  BGT celt_pitch_xcorr_edsp_process2_loop4
-celt_pitch_xcorr_edsp_process2_loop_done:
-  ADDS         r12, r12, #2
-  BLE  celt_pitch_xcorr_edsp_process2_1
-  LDR          r6, [r4], #4
-  @ Stall
-  SMLABB       r10, r6, r8, r10     @ sum0 = MAC16_16(sum0, x_0, y_0)
-  LDR          r9, [r5], #4
-  SMLABT       r11, r6, r8, r11     @ sum1 = MAC16_16(sum1, x_0, y_1)
-  SUB          r12, r12, #2
-  SMLATT       r10, r6, r8, r10     @ sum0 = MAC16_16(sum0, x_1, y_1)
-  MOV          r8, r9
-  SMLATB       r11, r6, r9, r11     @ sum1 = MAC16_16(sum1, x_1, y_2)
-celt_pitch_xcorr_edsp_process2_1:
-  LDRH         r6, [r4], #2
-  ADDS         r12, r12, #1
-  @ Stall
-  SMLABB       r10, r6, r8, r10     @ sum0 = MAC16_16(sum0, x_0, y_0)
-  LDRHGT       r7, [r4], #2
-  SMLABT       r11, r6, r8, r11     @ sum1 = MAC16_16(sum1, x_0, y_1)
-  BLE celt_pitch_xcorr_edsp_process2_done
-  LDRH         r9, [r5], #2
-  SMLABT       r10, r7, r8, r10     @ sum0 = MAC16_16(sum0, x_0, y_1)
-  SMLABB       r11, r7, r9, r11     @ sum1 = MAC16_16(sum1, x_0, y_2)
-celt_pitch_xcorr_edsp_process2_done:
-  @ Restore _x
-  SUB          r4, r4, r3, LSL #1
-  @ Restore and advance _y
-  SUB          r5, r5, r3, LSL #1
-  @ maxcorr = max(maxcorr, sum0)
-  CMP          r0, r10
-  ADD          r5, r5, #2
-  MOVLT        r0, r10
-  SUB          r1, r1, #2
-  @ maxcorr = max(maxcorr, sum1)
-  CMP          r0, r11
-  @ xcorr[i] = sum
-  STR          r10, [r2], #4
-  MOVLT        r0, r11
-  STR          r11, [r2], #4
-celt_pitch_xcorr_edsp_process1a:
-  ADDS         r1, r1, #1
-  BLT celt_pitch_xcorr_edsp_done
-  SUBS         r12, r3, #4
-  @ r14 = sum = 0
-  MOV          r14, #0
-  BLT celt_pitch_xcorr_edsp_process1a_loop_done
-  LDR          r6, [r4], #4
-  LDR          r8, [r5], #4
-  LDR          r7, [r4], #4
-  LDR          r9, [r5], #4
-celt_pitch_xcorr_edsp_process1a_loop4:
-  SMLABB       r14, r6, r8, r14     @ sum = MAC16_16(sum, x_0, y_0)
-  SUBS         r12, r12, #4         @ j-=4
-  SMLATT       r14, r6, r8, r14     @ sum = MAC16_16(sum, x_1, y_1)
-  LDRGE        r6, [r4], #4
-  SMLABB       r14, r7, r9, r14     @ sum = MAC16_16(sum, x_2, y_2)
-  LDRGE        r8, [r5], #4
-  SMLATT       r14, r7, r9, r14     @ sum = MAC16_16(sum, x_3, y_3)
-  LDRGE        r7, [r4], #4
-  LDRGE        r9, [r5], #4
-  BGE celt_pitch_xcorr_edsp_process1a_loop4
-celt_pitch_xcorr_edsp_process1a_loop_done:
-  ADDS         r12, r12, #2
-  LDRGE        r6, [r4], #4
-  LDRGE        r8, [r5], #4
-  @ Stall
-  SMLABBGE     r14, r6, r8, r14     @ sum = MAC16_16(sum, x_0, y_0)
-  SUBGE        r12, r12, #2
-  SMLATTGE     r14, r6, r8, r14     @ sum = MAC16_16(sum, x_1, y_1)
-  ADDS         r12, r12, #1
-  LDRHGE       r6, [r4], #2
-  LDRHGE       r8, [r5], #2
-  @ Stall
-  SMLABBGE     r14, r6, r8, r14     @ sum = MAC16_16(sum, *x, *y)
-  @ maxcorr = max(maxcorr, sum)
-  CMP          r0, r14
-  @ xcorr[i] = sum
-  STR          r14, [r2], #4
-  MOVLT        r0, r14
-celt_pitch_xcorr_edsp_done:
-  LDMFD        sp!, {r4-r11, pc}
-	.size celt_pitch_xcorr_edsp, .-celt_pitch_xcorr_edsp  @ ENDP
-
- .endif
-
-@ END:
-    .section	.note.GNU-stack,"",%progbits

+ 5 - 1
thirdparty/opus/celt/arm/celt_pitch_xcorr_arm.s

@@ -153,7 +153,7 @@ xcorr_kernel_neon_process1
   ENDP
 
 ; opus_val32 celt_pitch_xcorr_neon(opus_val16 *_x, opus_val16 *_y,
-;  opus_val32 *xcorr, int len, int max_pitch)
+;  opus_val32 *xcorr, int len, int max_pitch, int arch)
 celt_pitch_xcorr_neon PROC
   ; input:
   ;   r0  = opus_val16 *_x
@@ -168,6 +168,8 @@ celt_pitch_xcorr_neon PROC
   ;   r6  = int         max_pitch
   ;   r12 = int         j
   ;   q15 = int         maxcorr[4] (q15 is not used by xcorr_kernel_neon())
+  ; ignored:
+  ;         int         arch
   STMFD        sp!, {r4-r6, lr}
   LDR          r6, [sp, #16]
   VMOV.S32     q15, #1
@@ -358,6 +360,8 @@ celt_pitch_xcorr_edsp PROC
   ;   r9  = opus_val32  sum3
   ;   r1  = int         max_pitch
   ;   r12 = int         j
+  ; ignored:
+  ;         int         arch
   STMFD        sp!, {r4-r11, lr}
   MOV          r5, r1
   LDR          r1, [sp, #36]

+ 0 - 1
thirdparty/opus/celt/arm/fft_arm.h

@@ -34,7 +34,6 @@
 #if !defined(FFT_ARM_H)
 #define FFT_ARM_H
 
-#include "config.h"
 #include "kiss_fft.h"
 
 #if defined(HAVE_ARM_NE10)

+ 3 - 3
thirdparty/opus/celt/arm/fixed_armv4.h

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

+ 2 - 2
thirdparty/opus/celt/arm/fixed_armv5e.h

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

+ 0 - 1
thirdparty/opus/celt/arm/mdct_arm.h

@@ -33,7 +33,6 @@
 #if !defined(MDCT_ARM_H)
 #define MDCT_ARM_H
 
-#include "config.h"
 #include "mdct.h"
 
 #if defined(HAVE_ARM_NE10)

+ 45 - 11
thirdparty/opus/celt/arm/pitch_arm.h

@@ -30,11 +30,47 @@
 
 # include "armcpu.h"
 
+# if defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
+opus_val32 celt_inner_prod_neon(const opus_val16 *x, const opus_val16 *y, int N);
+void dual_inner_prod_neon(const opus_val16 *x, const opus_val16 *y01,
+        const opus_val16 *y02, int N, opus_val32 *xy1, opus_val32 *xy2);
+
+#  if !defined(OPUS_HAVE_RTCD) && defined(OPUS_ARM_PRESUME_NEON)
+#   define OVERRIDE_CELT_INNER_PROD (1)
+#   define OVERRIDE_DUAL_INNER_PROD (1)
+#   define celt_inner_prod(x, y, N, arch) ((void)(arch), PRESUME_NEON(celt_inner_prod)(x, y, N))
+#   define dual_inner_prod(x, y01, y02, N, xy1, xy2, arch) ((void)(arch), PRESUME_NEON(dual_inner_prod)(x, y01, y02, N, xy1, xy2))
+#  endif
+# endif
+
+# if !defined(OVERRIDE_CELT_INNER_PROD)
+#  if defined(OPUS_HAVE_RTCD) && (defined(OPUS_ARM_MAY_HAVE_NEON_INTR) && !defined(OPUS_ARM_PRESUME_NEON_INTR))
+extern opus_val32 (*const CELT_INNER_PROD_IMPL[OPUS_ARCHMASK+1])(const opus_val16 *x, const opus_val16 *y, int N);
+#   define OVERRIDE_CELT_INNER_PROD (1)
+#   define celt_inner_prod(x, y, N, arch) ((*CELT_INNER_PROD_IMPL[(arch)&OPUS_ARCHMASK])(x, y, N))
+#  elif defined(OPUS_ARM_PRESUME_NEON_INTR)
+#   define OVERRIDE_CELT_INNER_PROD (1)
+#   define celt_inner_prod(x, y, N, arch) ((void)(arch), celt_inner_prod_neon(x, y, N))
+#  endif
+# endif
+
+# if !defined(OVERRIDE_DUAL_INNER_PROD)
+#  if defined(OPUS_HAVE_RTCD) && (defined(OPUS_ARM_MAY_HAVE_NEON_INTR) && !defined(OPUS_ARM_PRESUME_NEON_INTR))
+extern void (*const DUAL_INNER_PROD_IMPL[OPUS_ARCHMASK+1])(const opus_val16 *x,
+        const opus_val16 *y01, const opus_val16 *y02, int N, opus_val32 *xy1, opus_val32 *xy2);
+#   define OVERRIDE_DUAL_INNER_PROD (1)
+#   define dual_inner_prod(x, y01, y02, N, xy1, xy2, arch) ((*DUAL_INNER_PROD_IMPL[(arch)&OPUS_ARCHMASK])(x, y01, y02, N, xy1, xy2))
+#  elif defined(OPUS_ARM_PRESUME_NEON_INTR)
+#   define OVERRIDE_DUAL_INNER_PROD (1)
+#   define dual_inner_prod(x, y01, y02, N, xy1, xy2, arch) ((void)(arch), dual_inner_prod_neon(x, y01, y02, N, xy1, xy2))
+#  endif
+# endif
+
 # if defined(FIXED_POINT)
 
 #  if defined(OPUS_ARM_MAY_HAVE_NEON)
 opus_val32 celt_pitch_xcorr_neon(const opus_val16 *_x, const opus_val16 *_y,
-    opus_val32 *xcorr, int len, int max_pitch);
+    opus_val32 *xcorr, int len, int max_pitch, int arch);
 #  endif
 
 #  if defined(OPUS_ARM_MAY_HAVE_MEDIA)
@@ -43,7 +79,7 @@ opus_val32 celt_pitch_xcorr_neon(const opus_val16 *_x, const opus_val16 *_y,
 
 #  if defined(OPUS_ARM_MAY_HAVE_EDSP)
 opus_val32 celt_pitch_xcorr_edsp(const opus_val16 *_x, const opus_val16 *_y,
-    opus_val32 *xcorr, int len, int max_pitch);
+    opus_val32 *xcorr, int len, int max_pitch, int arch);
 #  endif
 
 #  if defined(OPUS_HAVE_RTCD) && \
@@ -52,18 +88,17 @@ opus_val32 celt_pitch_xcorr_edsp(const opus_val16 *_x, const opus_val16 *_y,
      (defined(OPUS_ARM_MAY_HAVE_EDSP) && !defined(OPUS_ARM_PRESUME_EDSP)))
 extern opus_val32
 (*const CELT_PITCH_XCORR_IMPL[OPUS_ARCHMASK+1])(const opus_val16 *,
-      const opus_val16 *, opus_val32 *, int, int);
+      const opus_val16 *, opus_val32 *, int, int, int);
 #   define OVERRIDE_PITCH_XCORR (1)
 #   define celt_pitch_xcorr(_x, _y, xcorr, len, max_pitch, arch) \
   ((*CELT_PITCH_XCORR_IMPL[(arch)&OPUS_ARCHMASK])(_x, _y, \
-        xcorr, len, max_pitch))
+        xcorr, len, max_pitch, arch))
 
 #  elif defined(OPUS_ARM_PRESUME_EDSP) || \
     defined(OPUS_ARM_PRESUME_MEDIA) || \
     defined(OPUS_ARM_PRESUME_NEON)
 #   define OVERRIDE_PITCH_XCORR (1)
-#   define celt_pitch_xcorr(_x, _y, xcorr, len, max_pitch, arch) \
-  ((void)(arch),PRESUME_NEON(celt_pitch_xcorr)(_x, _y, xcorr, len, max_pitch))
+#   define celt_pitch_xcorr (PRESUME_NEON(celt_pitch_xcorr))
 
 #  endif
 
@@ -99,25 +134,24 @@ extern void (*const XCORR_KERNEL_IMPL[OPUS_ARCHMASK + 1])(
 /* Float case */
 #if defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
 void celt_pitch_xcorr_float_neon(const opus_val16 *_x, const opus_val16 *_y,
-                                 opus_val32 *xcorr, int len, int max_pitch);
+                                 opus_val32 *xcorr, int len, int max_pitch, int arch);
 #endif
 
 #  if defined(OPUS_HAVE_RTCD) && \
     (defined(OPUS_ARM_MAY_HAVE_NEON_INTR) && !defined(OPUS_ARM_PRESUME_NEON_INTR))
 extern void
 (*const CELT_PITCH_XCORR_IMPL[OPUS_ARCHMASK+1])(const opus_val16 *,
-      const opus_val16 *, opus_val32 *, int, int);
+      const opus_val16 *, opus_val32 *, int, int, int);
 
 #  define OVERRIDE_PITCH_XCORR (1)
 #  define celt_pitch_xcorr(_x, _y, xcorr, len, max_pitch, arch) \
   ((*CELT_PITCH_XCORR_IMPL[(arch)&OPUS_ARCHMASK])(_x, _y, \
-        xcorr, len, max_pitch))
+        xcorr, len, max_pitch, arch))
 
 #  elif defined(OPUS_ARM_PRESUME_NEON_INTR)
 
 #   define OVERRIDE_PITCH_XCORR (1)
-#   define celt_pitch_xcorr(_x, _y, xcorr, len, max_pitch, arch) \
-   ((void)(arch),celt_pitch_xcorr_float_neon(_x, _y, xcorr, len, max_pitch))
+#   define celt_pitch_xcorr celt_pitch_xcorr_float_neon
 
 #  endif
 

+ 290 - 0
thirdparty/opus/celt/arm/pitch_neon_intr.c

@@ -0,0 +1,290 @@
+/***********************************************************************
+Copyright (c) 2017 Google Inc.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <arm_neon.h>
+#include "pitch.h"
+
+#ifdef FIXED_POINT
+
+opus_val32 celt_inner_prod_neon(const opus_val16 *x, const opus_val16 *y, int N)
+{
+    int i;
+    opus_val32 xy;
+    int16x8_t x_s16x8, y_s16x8;
+    int32x4_t xy_s32x4 = vdupq_n_s32(0);
+    int64x2_t xy_s64x2;
+    int64x1_t xy_s64x1;
+
+    for (i = 0; i < N - 7; i += 8) {
+        x_s16x8  = vld1q_s16(&x[i]);
+        y_s16x8  = vld1q_s16(&y[i]);
+        xy_s32x4 = vmlal_s16(xy_s32x4, vget_low_s16 (x_s16x8), vget_low_s16 (y_s16x8));
+        xy_s32x4 = vmlal_s16(xy_s32x4, vget_high_s16(x_s16x8), vget_high_s16(y_s16x8));
+    }
+
+    if (N - i >= 4) {
+        const int16x4_t x_s16x4 = vld1_s16(&x[i]);
+        const int16x4_t y_s16x4 = vld1_s16(&y[i]);
+        xy_s32x4 = vmlal_s16(xy_s32x4, x_s16x4, y_s16x4);
+        i += 4;
+    }
+
+    xy_s64x2 = vpaddlq_s32(xy_s32x4);
+    xy_s64x1 = vadd_s64(vget_low_s64(xy_s64x2), vget_high_s64(xy_s64x2));
+    xy       = vget_lane_s32(vreinterpret_s32_s64(xy_s64x1), 0);
+
+    for (; i < N; i++) {
+        xy = MAC16_16(xy, x[i], y[i]);
+    }
+
+#ifdef OPUS_CHECK_ASM
+    celt_assert(celt_inner_prod_c(x, y, N) == xy);
+#endif
+
+    return xy;
+}
+
+void dual_inner_prod_neon(const opus_val16 *x, const opus_val16 *y01, const opus_val16 *y02,
+        int N, opus_val32 *xy1, opus_val32 *xy2)
+{
+    int i;
+    opus_val32 xy01, xy02;
+    int16x8_t x_s16x8, y01_s16x8, y02_s16x8;
+    int32x4_t xy01_s32x4 = vdupq_n_s32(0);
+    int32x4_t xy02_s32x4 = vdupq_n_s32(0);
+    int64x2_t xy01_s64x2, xy02_s64x2;
+    int64x1_t xy01_s64x1, xy02_s64x1;
+
+    for (i = 0; i < N - 7; i += 8) {
+        x_s16x8    = vld1q_s16(&x[i]);
+        y01_s16x8  = vld1q_s16(&y01[i]);
+        y02_s16x8  = vld1q_s16(&y02[i]);
+        xy01_s32x4 = vmlal_s16(xy01_s32x4, vget_low_s16 (x_s16x8), vget_low_s16 (y01_s16x8));
+        xy02_s32x4 = vmlal_s16(xy02_s32x4, vget_low_s16 (x_s16x8), vget_low_s16 (y02_s16x8));
+        xy01_s32x4 = vmlal_s16(xy01_s32x4, vget_high_s16(x_s16x8), vget_high_s16(y01_s16x8));
+        xy02_s32x4 = vmlal_s16(xy02_s32x4, vget_high_s16(x_s16x8), vget_high_s16(y02_s16x8));
+    }
+
+    if (N - i >= 4) {
+        const int16x4_t x_s16x4   = vld1_s16(&x[i]);
+        const int16x4_t y01_s16x4 = vld1_s16(&y01[i]);
+        const int16x4_t y02_s16x4 = vld1_s16(&y02[i]);
+        xy01_s32x4 = vmlal_s16(xy01_s32x4, x_s16x4, y01_s16x4);
+        xy02_s32x4 = vmlal_s16(xy02_s32x4, x_s16x4, y02_s16x4);
+        i += 4;
+    }
+
+    xy01_s64x2 = vpaddlq_s32(xy01_s32x4);
+    xy02_s64x2 = vpaddlq_s32(xy02_s32x4);
+    xy01_s64x1 = vadd_s64(vget_low_s64(xy01_s64x2), vget_high_s64(xy01_s64x2));
+    xy02_s64x1 = vadd_s64(vget_low_s64(xy02_s64x2), vget_high_s64(xy02_s64x2));
+    xy01       = vget_lane_s32(vreinterpret_s32_s64(xy01_s64x1), 0);
+    xy02       = vget_lane_s32(vreinterpret_s32_s64(xy02_s64x1), 0);
+
+    for (; i < N; i++) {
+        xy01 = MAC16_16(xy01, x[i], y01[i]);
+        xy02 = MAC16_16(xy02, x[i], y02[i]);
+    }
+    *xy1 = xy01;
+    *xy2 = xy02;
+
+#ifdef OPUS_CHECK_ASM
+    {
+        opus_val32 xy1_c, xy2_c;
+        dual_inner_prod_c(x, y01, y02, N, &xy1_c, &xy2_c);
+        celt_assert(xy1_c == *xy1);
+        celt_assert(xy2_c == *xy2);
+    }
+#endif
+}
+
+#else /* !FIXED_POINT */
+
+/* ========================================================================== */
+
+#ifdef OPUS_CHECK_ASM
+
+/* This part of code simulates floating-point NEON operations. */
+
+/* celt_inner_prod_neon_float_c_simulation() simulates the floating-point   */
+/* operations of celt_inner_prod_neon(), and both functions should have bit */
+/* exact output.                                                            */
+static opus_val32 celt_inner_prod_neon_float_c_simulation(const opus_val16 *x, const opus_val16 *y, int N)
+{
+   int i;
+   opus_val32 xy, xy0 = 0, xy1 = 0, xy2 = 0, xy3 = 0;
+   for (i = 0; i < N - 3; i += 4) {
+      xy0 = MAC16_16(xy0, x[i + 0], y[i + 0]);
+      xy1 = MAC16_16(xy1, x[i + 1], y[i + 1]);
+      xy2 = MAC16_16(xy2, x[i + 2], y[i + 2]);
+      xy3 = MAC16_16(xy3, x[i + 3], y[i + 3]);
+   }
+   xy0 += xy2;
+   xy1 += xy3;
+   xy = xy0 + xy1;
+   for (; i < N; i++) {
+      xy = MAC16_16(xy, x[i], y[i]);
+   }
+   return xy;
+}
+
+/* dual_inner_prod_neon_float_c_simulation() simulates the floating-point   */
+/* operations of dual_inner_prod_neon(), and both functions should have bit */
+/* exact output.                                                            */
+static void dual_inner_prod_neon_float_c_simulation(const opus_val16 *x, const opus_val16 *y01, const opus_val16 *y02,
+      int N, opus_val32 *xy1, opus_val32 *xy2)
+{
+   int i;
+   opus_val32 xy01, xy02, xy01_0 = 0, xy01_1 = 0, xy01_2 = 0, xy01_3 = 0, xy02_0 = 0, xy02_1 = 0, xy02_2 = 0, xy02_3 = 0;
+   for (i = 0; i < N - 3; i += 4) {
+      xy01_0 = MAC16_16(xy01_0, x[i + 0], y01[i + 0]);
+      xy01_1 = MAC16_16(xy01_1, x[i + 1], y01[i + 1]);
+      xy01_2 = MAC16_16(xy01_2, x[i + 2], y01[i + 2]);
+      xy01_3 = MAC16_16(xy01_3, x[i + 3], y01[i + 3]);
+      xy02_0 = MAC16_16(xy02_0, x[i + 0], y02[i + 0]);
+      xy02_1 = MAC16_16(xy02_1, x[i + 1], y02[i + 1]);
+      xy02_2 = MAC16_16(xy02_2, x[i + 2], y02[i + 2]);
+      xy02_3 = MAC16_16(xy02_3, x[i + 3], y02[i + 3]);
+   }
+   xy01_0 += xy01_2;
+   xy02_0 += xy02_2;
+   xy01_1 += xy01_3;
+   xy02_1 += xy02_3;
+   xy01 = xy01_0 + xy01_1;
+   xy02 = xy02_0 + xy02_1;
+   for (; i < N; i++) {
+      xy01 = MAC16_16(xy01, x[i], y01[i]);
+      xy02 = MAC16_16(xy02, x[i], y02[i]);
+   }
+   *xy1 = xy01;
+   *xy2 = xy02;
+}
+
+#endif /* OPUS_CHECK_ASM */
+
+/* ========================================================================== */
+
+opus_val32 celt_inner_prod_neon(const opus_val16 *x, const opus_val16 *y, int N)
+{
+    int i;
+    opus_val32 xy;
+    float32x4_t xy_f32x4 = vdupq_n_f32(0);
+    float32x2_t xy_f32x2;
+
+    for (i = 0; i < N - 7; i += 8) {
+        float32x4_t x_f32x4, y_f32x4;
+        x_f32x4  = vld1q_f32(&x[i]);
+        y_f32x4  = vld1q_f32(&y[i]);
+        xy_f32x4 = vmlaq_f32(xy_f32x4, x_f32x4, y_f32x4);
+        x_f32x4  = vld1q_f32(&x[i + 4]);
+        y_f32x4  = vld1q_f32(&y[i + 4]);
+        xy_f32x4 = vmlaq_f32(xy_f32x4, x_f32x4, y_f32x4);
+    }
+
+    if (N - i >= 4) {
+        const float32x4_t x_f32x4 = vld1q_f32(&x[i]);
+        const float32x4_t y_f32x4 = vld1q_f32(&y[i]);
+        xy_f32x4 = vmlaq_f32(xy_f32x4, x_f32x4, y_f32x4);
+        i += 4;
+    }
+
+    xy_f32x2 = vadd_f32(vget_low_f32(xy_f32x4), vget_high_f32(xy_f32x4));
+    xy_f32x2 = vpadd_f32(xy_f32x2, xy_f32x2);
+    xy       = vget_lane_f32(xy_f32x2, 0);
+
+    for (; i < N; i++) {
+        xy = MAC16_16(xy, x[i], y[i]);
+    }
+
+#ifdef OPUS_CHECK_ASM
+    celt_assert(ABS32(celt_inner_prod_neon_float_c_simulation(x, y, N) - xy) <= VERY_SMALL);
+#endif
+
+    return xy;
+}
+
+void dual_inner_prod_neon(const opus_val16 *x, const opus_val16 *y01, const opus_val16 *y02,
+        int N, opus_val32 *xy1, opus_val32 *xy2)
+{
+    int i;
+    opus_val32 xy01, xy02;
+    float32x4_t xy01_f32x4 = vdupq_n_f32(0);
+    float32x4_t xy02_f32x4 = vdupq_n_f32(0);
+    float32x2_t xy01_f32x2, xy02_f32x2;
+
+    for (i = 0; i < N - 7; i += 8) {
+        float32x4_t x_f32x4, y01_f32x4, y02_f32x4;
+        x_f32x4    = vld1q_f32(&x[i]);
+        y01_f32x4  = vld1q_f32(&y01[i]);
+        y02_f32x4  = vld1q_f32(&y02[i]);
+        xy01_f32x4 = vmlaq_f32(xy01_f32x4, x_f32x4, y01_f32x4);
+        xy02_f32x4 = vmlaq_f32(xy02_f32x4, x_f32x4, y02_f32x4);
+        x_f32x4    = vld1q_f32(&x[i + 4]);
+        y01_f32x4  = vld1q_f32(&y01[i + 4]);
+        y02_f32x4  = vld1q_f32(&y02[i + 4]);
+        xy01_f32x4 = vmlaq_f32(xy01_f32x4, x_f32x4, y01_f32x4);
+        xy02_f32x4 = vmlaq_f32(xy02_f32x4, x_f32x4, y02_f32x4);
+    }
+
+    if (N - i >= 4) {
+        const float32x4_t x_f32x4   = vld1q_f32(&x[i]);
+        const float32x4_t y01_f32x4 = vld1q_f32(&y01[i]);
+        const float32x4_t y02_f32x4 = vld1q_f32(&y02[i]);
+        xy01_f32x4 = vmlaq_f32(xy01_f32x4, x_f32x4, y01_f32x4);
+        xy02_f32x4 = vmlaq_f32(xy02_f32x4, x_f32x4, y02_f32x4);
+        i += 4;
+    }
+
+    xy01_f32x2 = vadd_f32(vget_low_f32(xy01_f32x4), vget_high_f32(xy01_f32x4));
+    xy02_f32x2 = vadd_f32(vget_low_f32(xy02_f32x4), vget_high_f32(xy02_f32x4));
+    xy01_f32x2 = vpadd_f32(xy01_f32x2, xy01_f32x2);
+    xy02_f32x2 = vpadd_f32(xy02_f32x2, xy02_f32x2);
+    xy01       = vget_lane_f32(xy01_f32x2, 0);
+    xy02       = vget_lane_f32(xy02_f32x2, 0);
+
+    for (; i < N; i++) {
+        xy01 = MAC16_16(xy01, x[i], y01[i]);
+        xy02 = MAC16_16(xy02, x[i], y02[i]);
+    }
+    *xy1 = xy01;
+    *xy2 = xy02;
+
+#ifdef OPUS_CHECK_ASM
+    {
+        opus_val32 xy1_c, xy2_c;
+        dual_inner_prod_neon_float_c_simulation(x, y01, y02, N, &xy1_c, &xy2_c);
+        celt_assert(ABS32(xy1_c - *xy1) <= VERY_SMALL);
+        celt_assert(ABS32(xy2_c - *xy2) <= VERY_SMALL);
+    }
+#endif
+}
+
+#endif /* FIXED_POINT */

+ 233 - 90
thirdparty/opus/celt/bands.c

@@ -65,19 +65,19 @@ opus_uint32 celt_lcg_rand(opus_uint32 seed)
 
 /* This is a cos() approximation designed to be bit-exact on any platform. Bit exactness
    with this approximation is important because it has an impact on the bit allocation */
-static opus_int16 bitexact_cos(opus_int16 x)
+opus_int16 bitexact_cos(opus_int16 x)
 {
    opus_int32 tmp;
    opus_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;
 }
 
-static int bitexact_log2tan(int isin,int icos)
+int bitexact_log2tan(int isin,int icos)
 {
    int lc;
    int ls;
@@ -92,10 +92,11 @@ static int bitexact_log2tan(int isin,int icos)
 
 #ifdef FIXED_POINT
 /* Compute the amplitude (sqrt energy) in each of the bands */
-void compute_band_energies(const CELTMode *m, const celt_sig *X, celt_ener *bandE, int end, int C, int LM)
+void compute_band_energies(const CELTMode *m, const celt_sig *X, celt_ener *bandE, int end, int C, int LM, int arch)
 {
    int i, c, N;
    const opus_int16 *eBands = m->eBands;
+   (void)arch;
    N = m->shortMdctSize<<LM;
    c=0; do {
       for (i=0;i<end;i++)
@@ -155,7 +156,7 @@ void normalise_bands(const CELTMode *m, const celt_sig * OPUS_RESTRICT freq, cel
 
 #else /* FIXED_POINT */
 /* Compute the amplitude (sqrt energy) in each of the bands */
-void compute_band_energies(const CELTMode *m, const celt_sig *X, celt_ener *bandE, int end, int C, int LM)
+void compute_band_energies(const CELTMode *m, const celt_sig *X, celt_ener *bandE, int end, int C, int LM, int arch)
 {
    int i, c, N;
    const opus_int16 *eBands = m->eBands;
@@ -164,7 +165,7 @@ void compute_band_energies(const CELTMode *m, const celt_sig *X, celt_ener *band
       for (i=0;i<end;i++)
       {
          opus_val32 sum;
-         sum = 1e-27f + celt_inner_prod_c(&X[c*N+(eBands[i]<<LM)], &X[c*N+(eBands[i]<<LM)], (eBands[i+1]-eBands[i])<<LM);
+         sum = 1e-27f + celt_inner_prod(&X[c*N+(eBands[i]<<LM)], &X[c*N+(eBands[i]<<LM)], (eBands[i+1]-eBands[i])<<LM, arch);
          bandE[i+c*m->nbEBands] = celt_sqrt(sum);
          /*printf ("%f ", bandE[i+c*m->nbEBands]);*/
       }
@@ -224,9 +225,9 @@ void denormalise_bands(const CELTMode *m, const celt_norm * OPUS_RESTRICT X,
 #endif
       j=M*eBands[i];
       band_end = M*eBands[i+1];
-      lg = ADD16(bandLogE[i], SHL16((opus_val16)eMeans[i],6));
+      lg = SATURATE16(ADD32(bandLogE[i], SHL32((opus_val32)eMeans[i],6)));
 #ifndef FIXED_POINT
-      g = celt_exp2(lg);
+      g = celt_exp2(MIN32(32.f, lg));
 #else
       /* Handle the integer part of the log energy */
       shift = 16-(lg>>DB_SHIFT);
@@ -241,12 +242,12 @@ void denormalise_bands(const CELTMode *m, const celt_norm * OPUS_RESTRICT X,
       /* Handle extreme gains with negative shift. */
       if (shift<0)
       {
-         /* For shift < -2 we'd be likely to overflow, so we're capping
-               the gain here. This shouldn't happen unless the bitstream is
-               already corrupted. */
-         if (shift < -2)
+         /* For shift <= -2 and g > 16384 we'd be likely to overflow, so we're
+            capping the gain here, which is equivalent to a cap of 18 on lg.
+            This shouldn't trigger unless the bitstream is already corrupted. */
+         if (shift <= -2)
          {
-            g = 32767;
+            g = 16384;
             shift = -2;
          }
          do {
@@ -281,7 +282,7 @@ void anti_collapse(const CELTMode *m, celt_norm *X_, unsigned char *collapse_mas
 
       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
@@ -360,6 +361,30 @@ void anti_collapse(const CELTMode *m, celt_norm *X_, unsigned char *collapse_mas
    }
 }
 
+/* Compute the weights to use for optimizing normalized distortion across
+   channels. We use the amplitude to weight square distortion, which means
+   that we use the square root of the value we would have been using if we
+   wanted to minimize the MSE in the non-normalized domain. This roughly
+   corresponds to some quick-and-dirty perceptual experiments I ran to
+   measure inter-aural masking (there doesn't seem to be any published data
+   on the topic). */
+static void compute_channel_weights(celt_ener Ex, celt_ener Ey, opus_val16 w[2])
+{
+   celt_ener minE;
+#ifdef FIXED_POINT
+   int shift;
+#endif
+   minE = MIN32(Ex, Ey);
+   /* Adjustment to make the weights a bit more conservative. */
+   Ex = ADD32(Ex, minE/3);
+   Ey = ADD32(Ey, minE/3);
+#ifdef FIXED_POINT
+   shift = celt_ilog2(EPSILON+MAX32(Ex, Ey))-14;
+#endif
+   w[0] = VSHR32(Ex, shift);
+   w[1] = VSHR32(Ey, shift);
+}
+
 static void intensity_stereo(const CELTMode *m, celt_norm * OPUS_RESTRICT X, const celt_norm * OPUS_RESTRICT Y, const celt_ener *bandE, int bandID, int N)
 {
    int i = bandID;
@@ -453,7 +478,7 @@ static void stereo_merge(celt_norm * OPUS_RESTRICT X, celt_norm * OPUS_RESTRICT
 /* 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;
@@ -494,8 +519,8 @@ int spreading_decision(const CELTMode *m, const celt_norm *X, int *average,
          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);
 
@@ -519,7 +544,7 @@ int spreading_decision(const CELTMode *m, const celt_norm *X, int *average,
    /*printf("%d %d %d\n", hf_sum, *hf_average, *tapset_decision);*/
    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;
@@ -647,6 +672,7 @@ static int compute_qn(int N, int b, int offset, int pulse_cap, int stereo)
 
 struct band_ctx {
    int encode;
+   int resynth;
    const CELTMode *m;
    int i;
    int intensity;
@@ -657,6 +683,9 @@ struct band_ctx {
    const celt_ener *bandE;
    opus_uint32 seed;
    int arch;
+   int theta_round;
+   int disable_inv;
+   int avoid_split_noise;
 };
 
 struct split_ctx {
@@ -714,8 +743,35 @@ static void compute_theta(struct band_ctx *ctx, struct split_ctx *sctx,
    if (qn!=1)
    {
       if (encode)
-         itheta = (itheta*(opus_int32)qn+8192)>>14;
-
+      {
+         if (!stereo || ctx->theta_round == 0)
+         {
+            itheta = (itheta*(opus_int32)qn+8192)>>14;
+            if (!stereo && ctx->avoid_split_noise && itheta > 0 && itheta < qn)
+            {
+               /* Check if the selected value of theta will cause the bit allocation
+                  to inject noise on one side. If so, make sure the energy of that side
+                  is zero. */
+               int unquantized = celt_udiv((opus_int32)itheta*16384, qn);
+               imid = bitexact_cos((opus_int16)unquantized);
+               iside = bitexact_cos((opus_int16)(16384-unquantized));
+               delta = FRAC_MUL16((N-1)<<7,bitexact_log2tan(iside,imid));
+               if (delta > *b)
+                  itheta = qn;
+               else if (delta < -*b)
+                  itheta = 0;
+            }
+         } else {
+            int down;
+            /* Bias quantization towards itheta=0 and itheta=16384. */
+            int bias = itheta > 8192 ? 32767/qn : -32767/qn;
+            down = IMIN(qn-1, IMAX(0, (itheta*(opus_int32)qn + bias)>>14));
+            if (ctx->theta_round < 0)
+               itheta = down;
+            else
+               itheta = down+1;
+         }
+      }
       /* Entropy coding of the angle. We use a uniform pdf for the
          time split, a step for stereo, and a triangular one for the rest. */
       if (stereo && N>2)
@@ -793,7 +849,7 @@ static void compute_theta(struct band_ctx *ctx, struct split_ctx *sctx,
    } else if (stereo) {
       if (encode)
       {
-         inv = itheta > 8192;
+         inv = itheta > 8192 && !ctx->disable_inv;
          if (inv)
          {
             int j;
@@ -810,6 +866,9 @@ static void compute_theta(struct band_ctx *ctx, struct split_ctx *sctx,
             inv = ec_dec_bit_logp(ec, 2);
       } else
          inv = 0;
+      /* inv flag override to avoid problems with downmixing. */
+      if (ctx->disable_inv)
+         inv = 0;
       itheta = 0;
    }
    qalloc = ec_tell_frac(ec) - tell;
@@ -845,11 +904,6 @@ static void compute_theta(struct band_ctx *ctx, struct split_ctx *sctx,
 static unsigned quant_band_n1(struct band_ctx *ctx, celt_norm *X, celt_norm *Y, int b,
       celt_norm *lowband_out)
 {
-#ifdef RESYNTH
-   int resynth = 1;
-#else
-   int resynth = !ctx->encode;
-#endif
    int c;
    int stereo;
    celt_norm *x = X;
@@ -874,7 +928,7 @@ static unsigned quant_band_n1(struct band_ctx *ctx, celt_norm *X, celt_norm *Y,
          ctx->remaining_bits -= 1<<BITRES;
          b-=1<<BITRES;
       }
-      if (resynth)
+      if (ctx->resynth)
          x[0] = sign ? -NORM_SCALING : NORM_SCALING;
       x = Y;
    } while (++c<1+stereo);
@@ -899,11 +953,6 @@ static unsigned quant_partition(struct band_ctx *ctx, celt_norm *X,
    int B0=B;
    opus_val16 mid=0, side=0;
    unsigned cm=0;
-#ifdef RESYNTH
-   int resynth = 1;
-#else
-   int resynth = !ctx->encode;
-#endif
    celt_norm *Y=NULL;
    int encode;
    const CELTMode *m;
@@ -935,8 +984,7 @@ static unsigned quant_partition(struct band_ctx *ctx, celt_norm *X,
          fill = (fill&1)|(fill<<1);
       B = (B+1)>>1;
 
-      compute_theta(ctx, &sctx, X, Y, N, &b, B, B0,
-            LM, 0, &fill);
+      compute_theta(ctx, &sctx, X, Y, N, &b, B, B0, LM, 0, &fill);
       imid = sctx.imid;
       iside = sctx.iside;
       delta = sctx.delta;
@@ -970,24 +1018,20 @@ static unsigned quant_partition(struct band_ctx *ctx, celt_norm *X,
       rebalance = ctx->remaining_bits;
       if (mbits >= sbits)
       {
-         cm = quant_partition(ctx, X, N, mbits, B,
-               lowband, LM,
+         cm = quant_partition(ctx, X, N, mbits, B, lowband, LM,
                MULT16_16_P15(gain,mid), fill);
          rebalance = mbits - (rebalance-ctx->remaining_bits);
          if (rebalance > 3<<BITRES && itheta!=0)
             sbits += rebalance - (3<<BITRES);
-         cm |= quant_partition(ctx, Y, N, sbits, B,
-               next_lowband2, LM,
+         cm |= quant_partition(ctx, Y, N, sbits, B, next_lowband2, LM,
                MULT16_16_P15(gain,side), fill>>B)<<(B0>>1);
       } else {
-         cm = quant_partition(ctx, Y, N, sbits, B,
-               next_lowband2, LM,
+         cm = quant_partition(ctx, Y, N, sbits, B, next_lowband2, LM,
                MULT16_16_P15(gain,side), fill>>B)<<(B0>>1);
          rebalance = sbits - (rebalance-ctx->remaining_bits);
          if (rebalance > 3<<BITRES && itheta!=16384)
             mbits += rebalance - (3<<BITRES);
-         cm |= quant_partition(ctx, X, N, mbits, B,
-               lowband, LM,
+         cm |= quant_partition(ctx, X, N, mbits, B, lowband, LM,
                MULT16_16_P15(gain,mid), fill);
       }
    } else {
@@ -1012,18 +1056,14 @@ static unsigned quant_partition(struct band_ctx *ctx, celt_norm *X,
          /* Finally do the actual quantization */
          if (encode)
          {
-            cm = alg_quant(X, N, K, spread, B, ec
-#ifdef RESYNTH
-                 , gain
-#endif
-                 );
+            cm = alg_quant(X, N, K, spread, B, ec, gain, ctx->resynth, ctx->arch);
          } else {
             cm = alg_unquant(X, N, K, spread, B, ec, gain);
          }
       } else {
          /* If there's no pulse, fill the band anyway */
          int j;
-         if (resynth)
+         if (ctx->resynth)
          {
             unsigned cm_mask;
             /* B can be as large as 16, so this shift might overflow an int on a
@@ -1080,11 +1120,6 @@ static unsigned quant_band(struct band_ctx *ctx, celt_norm *X,
    int recombine=0;
    int longBlocks;
    unsigned cm=0;
-#ifdef RESYNTH
-   int resynth = 1;
-#else
-   int resynth = !ctx->encode;
-#endif
    int k;
    int encode;
    int tf_change;
@@ -1151,11 +1186,10 @@ static unsigned quant_band(struct band_ctx *ctx, celt_norm *X,
          deinterleave_hadamard(lowband, N_B>>recombine, B0<<recombine, longBlocks);
    }
 
-   cm = quant_partition(ctx, X, N, b, B, lowband,
-         LM, gain, fill);
+   cm = quant_partition(ctx, X, N, b, B, lowband, LM, gain, fill);
 
    /* This code is used by the decoder and by the resynthesis-enabled encoder */
-   if (resynth)
+   if (ctx->resynth)
    {
       /* Undo the sample reorganization going from time order to frequency order */
       if (B0>1)
@@ -1208,11 +1242,6 @@ static unsigned quant_band_stereo(struct band_ctx *ctx, celt_norm *X, celt_norm
    int inv = 0;
    opus_val16 mid=0, side=0;
    unsigned cm=0;
-#ifdef RESYNTH
-   int resynth = 1;
-#else
-   int resynth = !ctx->encode;
-#endif
    int mbits, sbits, delta;
    int itheta;
    int qalloc;
@@ -1232,8 +1261,7 @@ static unsigned quant_band_stereo(struct band_ctx *ctx, celt_norm *X, celt_norm
 
    orig_fill = fill;
 
-   compute_theta(ctx, &sctx, X, Y, N, &b, B, B,
-         LM, 1, &fill);
+   compute_theta(ctx, &sctx, X, Y, N, &b, B, B, LM, 1, &fill);
    inv = sctx.inv;
    imid = sctx.imid;
    iside = sctx.iside;
@@ -1281,13 +1309,13 @@ static unsigned quant_band_stereo(struct band_ctx *ctx, celt_norm *X, celt_norm
       sign = 1-2*sign;
       /* We use orig_fill here because we want to fold the side, but if
          itheta==16384, we'll have cleared the low bits of fill. */
-      cm = quant_band(ctx, x2, N, mbits, B, lowband,
-            LM, lowband_out, Q15ONE, lowband_scratch, orig_fill);
+      cm = quant_band(ctx, x2, N, mbits, B, lowband, LM, lowband_out, Q15ONE,
+            lowband_scratch, orig_fill);
       /* We don't split N=2 bands, so cm is either 1 or 0 (for a fold-collapse),
          and there's no need to worry about mixing with the other channel. */
       y2[0] = -sign*x2[1];
       y2[1] = sign*x2[0];
-      if (resynth)
+      if (ctx->resynth)
       {
          celt_norm tmp;
          X[0] = MULT16_16_Q15(mid, X[0]);
@@ -1314,38 +1342,32 @@ static unsigned quant_band_stereo(struct band_ctx *ctx, celt_norm *X, celt_norm
       {
          /* In stereo mode, we do not apply a scaling to the mid because we need the normalized
             mid for folding later. */
-         cm = quant_band(ctx, X, N, mbits, B,
-               lowband, LM, lowband_out,
-               Q15ONE, lowband_scratch, fill);
+         cm = quant_band(ctx, X, N, mbits, B, lowband, LM, lowband_out, Q15ONE,
+               lowband_scratch, fill);
          rebalance = mbits - (rebalance-ctx->remaining_bits);
          if (rebalance > 3<<BITRES && itheta!=0)
             sbits += rebalance - (3<<BITRES);
 
          /* For a stereo split, the high bits of fill are always zero, so no
             folding will be done to the side. */
-         cm |= quant_band(ctx, Y, N, sbits, B,
-               NULL, LM, NULL,
-               side, NULL, fill>>B);
+         cm |= quant_band(ctx, Y, N, sbits, B, NULL, LM, NULL, side, NULL, fill>>B);
       } else {
          /* For a stereo split, the high bits of fill are always zero, so no
             folding will be done to the side. */
-         cm = quant_band(ctx, Y, N, sbits, B,
-               NULL, LM, NULL,
-               side, NULL, fill>>B);
+         cm = quant_band(ctx, Y, N, sbits, B, NULL, LM, NULL, side, NULL, fill>>B);
          rebalance = sbits - (rebalance-ctx->remaining_bits);
          if (rebalance > 3<<BITRES && itheta!=16384)
             mbits += rebalance - (3<<BITRES);
          /* In stereo mode, we do not apply a scaling to the mid because we need the normalized
             mid for folding later. */
-         cm |= quant_band(ctx, X, N, mbits, B,
-               lowband, LM, lowband_out,
-               Q15ONE, lowband_scratch, fill);
+         cm |= quant_band(ctx, X, N, mbits, B, lowband, LM, lowband_out, Q15ONE,
+               lowband_scratch, fill);
       }
    }
 
 
    /* This code is used by the decoder and by the resynthesis-enabled encoder */
-   if (resynth)
+   if (ctx->resynth)
    {
       if (N!=2)
          stereo_merge(X, Y, mid, N, ctx->arch);
@@ -1359,19 +1381,38 @@ static unsigned quant_band_stereo(struct band_ctx *ctx, celt_norm *X, celt_norm
    return cm;
 }
 
+static void special_hybrid_folding(const CELTMode *m, celt_norm *norm, celt_norm *norm2, int start, int M, int dual_stereo)
+{
+   int n1, n2;
+   const opus_int16 * OPUS_RESTRICT eBands = m->eBands;
+   n1 = M*(eBands[start+1]-eBands[start]);
+   n2 = M*(eBands[start+2]-eBands[start+1]);
+   /* Duplicate enough of the first band folding data to be able to fold the second band.
+      Copies no data for CELT-only mode. */
+   OPUS_COPY(&norm[n1], &norm[2*n1 - n2], n2-n1);
+   if (dual_stereo)
+      OPUS_COPY(&norm2[n1], &norm2[2*n1 - n2], n2-n1);
+}
 
 void quant_all_bands(int encode, const CELTMode *m, int start, int end,
       celt_norm *X_, celt_norm *Y_, unsigned char *collapse_masks,
       const celt_ener *bandE, int *pulses, int shortBlocks, int spread,
       int dual_stereo, int intensity, int *tf_res, opus_int32 total_bits,
       opus_int32 balance, ec_ctx *ec, int LM, int codedBands,
-      opus_uint32 *seed, int arch)
+      opus_uint32 *seed, int complexity, int arch, int disable_inv)
 {
    int i;
    opus_int32 remaining_bits;
    const opus_int16 * OPUS_RESTRICT eBands = m->eBands;
    celt_norm * OPUS_RESTRICT norm, * OPUS_RESTRICT norm2;
    VARDECL(celt_norm, _norm);
+   VARDECL(celt_norm, _lowband_scratch);
+   VARDECL(celt_norm, X_save);
+   VARDECL(celt_norm, Y_save);
+   VARDECL(celt_norm, X_save2);
+   VARDECL(celt_norm, Y_save2);
+   VARDECL(celt_norm, norm_save2);
+   int resynth_alloc;
    celt_norm *lowband_scratch;
    int B;
    int M;
@@ -1379,10 +1420,11 @@ void quant_all_bands(int encode, const CELTMode *m, int start, int end,
    int update_lowband = 1;
    int C = Y_ != NULL ? 2 : 1;
    int norm_offset;
+   int theta_rdo = encode && Y_!=NULL && !dual_stereo && complexity>=8;
 #ifdef RESYNTH
    int resynth = 1;
 #else
-   int resynth = !encode;
+   int resynth = !encode || theta_rdo;
 #endif
    struct band_ctx ctx;
    SAVE_STACK;
@@ -1395,9 +1437,24 @@ void quant_all_bands(int encode, const CELTMode *m, int start, int end,
    ALLOC(_norm, C*(M*eBands[m->nbEBands-1]-norm_offset), celt_norm);
    norm = _norm;
    norm2 = norm + M*eBands[m->nbEBands-1]-norm_offset;
-   /* We can use the last band as scratch space because we don't need that
-      scratch space for the last band. */
-   lowband_scratch = X_+M*eBands[m->nbEBands-1];
+
+   /* For decoding, we can use the last band as scratch space because we don't need that
+      scratch space for the last band and we don't care about the data there until we're
+      decoding the last band. */
+   if (encode && resynth)
+      resynth_alloc = M*(eBands[m->nbEBands]-eBands[m->nbEBands-1]);
+   else
+      resynth_alloc = ALLOC_NONE;
+   ALLOC(_lowband_scratch, resynth_alloc, celt_norm);
+   if (encode && resynth)
+      lowband_scratch = _lowband_scratch;
+   else
+      lowband_scratch = X_+M*eBands[m->nbEBands-1];
+   ALLOC(X_save, resynth_alloc, celt_norm);
+   ALLOC(Y_save, resynth_alloc, celt_norm);
+   ALLOC(X_save2, resynth_alloc, celt_norm);
+   ALLOC(Y_save2, resynth_alloc, celt_norm);
+   ALLOC(norm_save2, resynth_alloc, celt_norm);
 
    lowband_offset = 0;
    ctx.bandE = bandE;
@@ -1408,6 +1465,11 @@ void quant_all_bands(int encode, const CELTMode *m, int start, int end,
    ctx.seed = *seed;
    ctx.spread = spread;
    ctx.arch = arch;
+   ctx.disable_inv = disable_inv;
+   ctx.resynth = resynth;
+   ctx.theta_round = 0;
+   /* Avoid injecting noise in the first band on transients. */
+   ctx.avoid_split_noise = B > 1;
    for (i=start;i<end;i++)
    {
       opus_int32 tell;
@@ -1430,6 +1492,7 @@ void quant_all_bands(int encode, const CELTMode *m, int start, int end,
       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 */
@@ -1445,8 +1508,15 @@ void quant_all_bands(int encode, const CELTMode *m, int start, int end,
          b = 0;
       }
 
+#ifndef DISABLE_UPDATE_DRAFT
+      if (resynth && (M*eBands[i]-N >= M*eBands[start] || i==start+1) && (update_lowband || lowband_offset==0))
+            lowband_offset = i;
+      if (i == start+1)
+         special_hybrid_folding(m, norm, norm2, start, M, dual_stereo);
+#else
       if (resynth && M*eBands[i]-N >= M*eBands[start] && (update_lowband || lowband_offset==0))
             lowband_offset = i;
+#endif
 
       tf_change = tf_res[i];
       ctx.tf_change = tf_change;
@@ -1457,7 +1527,7 @@ void quant_all_bands(int encode, const CELTMode *m, int start, int end,
             Y = norm;
          lowband_scratch = NULL;
       }
-      if (i==end-1)
+      if (last && !theta_rdo)
          lowband_scratch = NULL;
 
       /* Get a conservative estimate of the collapse_mask's for the bands we're
@@ -1472,7 +1542,11 @@ void quant_all_bands(int encode, const CELTMode *m, int start, int end,
          fold_start = lowband_offset;
          while(M*eBands[--fold_start] > effective_lowband+norm_offset);
          fold_end = lowband_offset-1;
+#ifndef DISABLE_UPDATE_DRAFT
+         while(++fold_end < i && M*eBands[fold_end] < effective_lowband+norm_offset+N);
+#else
          while(M*eBands[++fold_end] < effective_lowband+norm_offset+N);
+#endif
          x_cm = y_cm = 0;
          fold_i = fold_start; do {
            x_cm |= collapse_masks[fold_i*C+0];
@@ -1505,13 +1579,79 @@ void quant_all_bands(int encode, const CELTMode *m, int start, int end,
       } else {
          if (Y!=NULL)
          {
-            x_cm = quant_band_stereo(&ctx, X, Y, N, b, B,
-                  effective_lowband != -1 ? norm+effective_lowband : NULL, LM,
-                        last?NULL:norm+M*eBands[i]-norm_offset, lowband_scratch, x_cm|y_cm);
+            if (theta_rdo && i < intensity)
+            {
+               ec_ctx ec_save, ec_save2;
+               struct band_ctx ctx_save, ctx_save2;
+               opus_val32 dist0, dist1;
+               unsigned cm, cm2;
+               int nstart_bytes, nend_bytes, save_bytes;
+               unsigned char *bytes_buf;
+               unsigned char bytes_save[1275];
+               opus_val16 w[2];
+               compute_channel_weights(bandE[i], bandE[i+m->nbEBands], w);
+               /* Make a copy. */
+               cm = x_cm|y_cm;
+               ec_save = *ec;
+               ctx_save = ctx;
+               OPUS_COPY(X_save, X, N);
+               OPUS_COPY(Y_save, Y, N);
+               /* Encode and round down. */
+               ctx.theta_round = -1;
+               x_cm = quant_band_stereo(&ctx, X, Y, N, b, B,
+                     effective_lowband != -1 ? norm+effective_lowband : NULL, LM,
+                     last?NULL:norm+M*eBands[i]-norm_offset, lowband_scratch, cm);
+               dist0 = MULT16_32_Q15(w[0], celt_inner_prod(X_save, X, N, arch)) + MULT16_32_Q15(w[1], celt_inner_prod(Y_save, Y, N, arch));
+
+               /* Save first result. */
+               cm2 = x_cm;
+               ec_save2 = *ec;
+               ctx_save2 = ctx;
+               OPUS_COPY(X_save2, X, N);
+               OPUS_COPY(Y_save2, Y, N);
+               if (!last)
+                  OPUS_COPY(norm_save2, norm+M*eBands[i]-norm_offset, N);
+               nstart_bytes = ec_save.offs;
+               nend_bytes = ec_save.storage;
+               bytes_buf = ec_save.buf+nstart_bytes;
+               save_bytes = nend_bytes-nstart_bytes;
+               OPUS_COPY(bytes_save, bytes_buf, save_bytes);
+
+               /* Restore */
+               *ec = ec_save;
+               ctx = ctx_save;
+               OPUS_COPY(X, X_save, N);
+               OPUS_COPY(Y, Y_save, N);
+#ifndef DISABLE_UPDATE_DRAFT
+               if (i == start+1)
+                  special_hybrid_folding(m, norm, norm2, start, M, dual_stereo);
+#endif
+               /* Encode and round up. */
+               ctx.theta_round = 1;
+               x_cm = quant_band_stereo(&ctx, X, Y, N, b, B,
+                     effective_lowband != -1 ? norm+effective_lowband : NULL, LM,
+                     last?NULL:norm+M*eBands[i]-norm_offset, lowband_scratch, cm);
+               dist1 = MULT16_32_Q15(w[0], celt_inner_prod(X_save, X, N, arch)) + MULT16_32_Q15(w[1], celt_inner_prod(Y_save, Y, N, arch));
+               if (dist0 >= dist1) {
+                  x_cm = cm2;
+                  *ec = ec_save2;
+                  ctx = ctx_save2;
+                  OPUS_COPY(X, X_save2, N);
+                  OPUS_COPY(Y, Y_save2, N);
+                  if (!last)
+                     OPUS_COPY(norm+M*eBands[i]-norm_offset, norm_save2, N);
+                  OPUS_COPY(bytes_buf, bytes_save, save_bytes);
+               }
+            } else {
+               ctx.theta_round = 0;
+               x_cm = quant_band_stereo(&ctx, X, Y, N, b, B,
+                     effective_lowband != -1 ? norm+effective_lowband : NULL, LM,
+                     last?NULL:norm+M*eBands[i]-norm_offset, lowband_scratch, x_cm|y_cm);
+            }
          } else {
             x_cm = quant_band(&ctx, X, N, b, B,
                   effective_lowband != -1 ? norm+effective_lowband : NULL, LM,
-                        last?NULL:norm+M*eBands[i]-norm_offset, Q15ONE, lowband_scratch, x_cm|y_cm);
+                  last?NULL:norm+M*eBands[i]-norm_offset, Q15ONE, lowband_scratch, x_cm|y_cm);
          }
          y_cm = x_cm;
       }
@@ -1521,6 +1661,9 @@ void quant_all_bands(int encode, const CELTMode *m, int start, int end,
 
       /* Update the folding position only as long as we have 1 bit/sample depth. */
       update_lowband = b>(N<<BITRES);
+      /* We only need to avoid noise on a split for the first band. After that, we
+         have folding. */
+      ctx.avoid_split_noise = 0;
    }
    *seed = ctx.seed;
 

+ 6 - 3
thirdparty/opus/celt/bands.h

@@ -36,12 +36,15 @@
 #include "entdec.h"
 #include "rate.h"
 
+opus_int16 bitexact_cos(opus_int16 x);
+int bitexact_log2tan(int isin,int icos);
+
 /** Compute the amplitude (sqrt energy) in each of the bands
  * @param m Mode data
  * @param X Spectrum
  * @param bandE Square root of the energy for each band (returned)
  */
-void compute_band_energies(const CELTMode *m, const celt_sig *X, celt_ener *bandE, int end, int C, int LM);
+void compute_band_energies(const CELTMode *m, const celt_sig *X, celt_ener *bandE, int end, int C, int LM, int arch);
 
 /*void compute_noise_energies(const CELTMode *m, const celt_sig *X, const opus_val16 *tonality, celt_ener *bandE);*/
 
@@ -69,7 +72,7 @@ void denormalise_bands(const CELTMode *m, const celt_norm * OPUS_RESTRICT X,
 
 int spreading_decision(const CELTMode *m, const celt_norm *X, int *average,
       int 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);
@@ -105,7 +108,7 @@ void quant_all_bands(int encode, const CELTMode *m, int start, int end,
       const celt_ener *bandE, int *pulses, int shortBlocks, int spread,
       int dual_stereo, int intensity, int *tf_res, opus_int32 total_bits,
       opus_int32 balance, ec_ctx *ec, int M, int codedBands, opus_uint32 *seed,
-      int arch);
+      int complexity, int arch, int disable_inv);
 
 void anti_collapse(const CELTMode *m, celt_norm *X_,
       unsigned char *collapse_masks, int LM, int C, int size, int start,

+ 21 - 4
thirdparty/opus/celt/celt.c

@@ -111,26 +111,31 @@ void comb_filter_const_c(opus_val32 *y, opus_val32 *x, int T, int N,
       t = MAC16_32_Q16(x[i], g10, x2);
       t = MAC16_32_Q16(t, g11, ADD32(x1,x3));
       t = MAC16_32_Q16(t, g12, ADD32(x0,x4));
+      t = SATURATE(t, SIG_SAT);
       y[i] = t;
       x4=SHL32(x[i-T+3],1);
       t = MAC16_32_Q16(x[i+1], g10, x1);
       t = MAC16_32_Q16(t, g11, ADD32(x0,x2));
       t = MAC16_32_Q16(t, g12, ADD32(x4,x3));
+      t = SATURATE(t, SIG_SAT);
       y[i+1] = t;
       x3=SHL32(x[i-T+4],1);
       t = MAC16_32_Q16(x[i+2], g10, x0);
       t = MAC16_32_Q16(t, g11, ADD32(x4,x1));
       t = MAC16_32_Q16(t, g12, ADD32(x3,x2));
+      t = SATURATE(t, SIG_SAT);
       y[i+2] = t;
       x2=SHL32(x[i-T+5],1);
       t = MAC16_32_Q16(x[i+3], g10, x4);
       t = MAC16_32_Q16(t, g11, ADD32(x3,x0));
       t = MAC16_32_Q16(t, g12, ADD32(x2,x1));
+      t = SATURATE(t, SIG_SAT);
       y[i+3] = t;
       x1=SHL32(x[i-T+6],1);
       t = MAC16_32_Q16(x[i+4], g10, x3);
       t = MAC16_32_Q16(t, g11, ADD32(x2,x4));
       t = MAC16_32_Q16(t, g12, ADD32(x1,x0));
+      t = SATURATE(t, SIG_SAT);
       y[i+4] = t;
    }
 #ifdef CUSTOM_MODES
@@ -141,6 +146,7 @@ void comb_filter_const_c(opus_val32 *y, opus_val32 *x, int T, int N,
       t = MAC16_32_Q16(x[i], g10, x2);
       t = MAC16_32_Q16(t, g11, ADD32(x1,x3));
       t = MAC16_32_Q16(t, g12, ADD32(x0,x4));
+      t = SATURATE(t, SIG_SAT);
       y[i] = t;
       x4=x3;
       x3=x2;
@@ -169,6 +175,7 @@ void comb_filter_const_c(opus_val32 *y, opus_val32 *x, int T, int N,
                + MULT16_32_Q15(g10,x2)
                + MULT16_32_Q15(g11,ADD32(x1,x3))
                + MULT16_32_Q15(g12,ADD32(x0,x4));
+      y[i] = SATURATE(y[i], SIG_SAT);
       x4=x3;
       x3=x2;
       x2=x1;
@@ -200,6 +207,10 @@ void comb_filter(opus_val32 *y, opus_val32 *x, int T0, int T1, int N,
          OPUS_MOVE(y, x, N);
       return;
    }
+   /* When the gain is zero, T0 and/or T1 is set to zero. We need
+      to have then be at least 2 to avoid processing garbage data. */
+   T0 = IMAX(T0, COMBFILTER_MINPERIOD);
+   T1 = IMAX(T1, COMBFILTER_MINPERIOD);
    g00 = MULT16_16_P15(g0, gains[tapset0][0]);
    g01 = MULT16_16_P15(g0, gains[tapset0][1]);
    g02 = MULT16_16_P15(g0, gains[tapset0][2]);
@@ -225,6 +236,7 @@ void comb_filter(opus_val32 *y, opus_val32 *x, int T0, int T1, int N,
                + MULT16_32_Q15(MULT16_16_Q15(f,g10),x2)
                + MULT16_32_Q15(MULT16_16_Q15(f,g11),ADD32(x1,x3))
                + MULT16_32_Q15(MULT16_16_Q15(f,g12),ADD32(x0,x4));
+      y[i] = SATURATE(y[i], SIG_SAT);
       x4=x3;
       x3=x2;
       x2=x1;
@@ -244,11 +256,16 @@ void comb_filter(opus_val32 *y, opus_val32 *x, int T0, int T1, int N,
 }
 #endif /* OVERRIDE_comb_filter */
 
+/* TF change table. Positive values mean better frequency resolution (longer
+   effective window), whereas negative values mean better time resolution
+   (shorter effective window). The second index is computed as:
+   4*isTransient + 2*tf_select + per_band_flag */
 const signed char tf_select_table[4][8] = {
-      {0, -1, 0, -1,    0,-1, 0,-1},
-      {0, -1, 0, -2,    1, 0, 1,-1},
-      {0, -2, 0, -3,    2, 0, 1,-1},
-      {0, -2, 0, -3,    3, 0, 1,-1},
+    /*isTransient=0     isTransient=1 */
+      {0, -1, 0, -1,    0,-1, 0,-1}, /* 2.5 ms */
+      {0, -1, 0, -2,    1, 0, 1,-1}, /* 5 ms */
+      {0, -2, 0, -3,    2, 0, 1,-1}, /* 10 ms */
+      {0, -2, 0, -3,    3, 0, 1,-1}, /* 20 ms */
 };
 
 

+ 27 - 5
thirdparty/opus/celt/celt.h

@@ -50,6 +50,8 @@ extern "C" {
 #define CELTDecoder OpusCustomDecoder
 #define CELTMode OpusCustomMode
 
+#define LEAK_BANDS 19
+
 typedef struct {
    int valid;
    float tonality;
@@ -57,17 +59,27 @@ typedef struct {
    float noisiness;
    float activity;
    float music_prob;
-   int        bandwidth;
-}AnalysisInfo;
+   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;
+
+typedef struct {
+   int signalType;
+   int offset;
+} SILKInfo;
 
 #define __celt_check_mode_ptr_ptr(ptr) ((ptr) + ((ptr) - (const CELTMode**)(ptr)))
 
 #define __celt_check_analysis_ptr(ptr) ((ptr) + ((ptr) - (const AnalysisInfo*)(ptr)))
 
-/* Encoder/decoder Requests */
+#define __celt_check_silkinfo_ptr(ptr) ((ptr) + ((ptr) - (const SILKInfo*)(ptr)))
 
-/* Expose this option again when variable framesize actually works */
-#define OPUS_FRAMESIZE_VARIABLE              5010 /**< Optimize the frame size dynamically */
+/* Encoder/decoder Requests */
 
 
 #define CELT_SET_PREDICTION_REQUEST    10002
@@ -116,6 +128,9 @@ typedef struct {
 #define OPUS_SET_ENERGY_MASK_REQUEST    10026
 #define OPUS_SET_ENERGY_MASK(x) OPUS_SET_ENERGY_MASK_REQUEST, __opus_check_val16_ptr(x)
 
+#define CELT_SET_SILK_INFO_REQUEST    10028
+#define CELT_SET_SILK_INFO(x) CELT_SET_SILK_INFO_REQUEST, __celt_check_silkinfo_ptr(x)
+
 /* Encoder stuff */
 
 int celt_encoder_get_size(int channels);
@@ -194,6 +209,13 @@ static OPUS_INLINE int fromOpus(unsigned char c)
 
 extern const signed char tf_select_table[4][8];
 
+#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,

+ 157 - 33
thirdparty/opus/celt/celt_decoder.c

@@ -51,6 +51,14 @@
 #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
@@ -73,6 +81,7 @@ struct OpusCustomDecoder {
    int downsample;
    int start, end;
    int signalling;
+   int disable_inv;
    int arch;
 
    /* Everything beyond this point gets cleared on a reset */
@@ -100,6 +109,38 @@ struct OpusCustomDecoder {
    /* 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);
@@ -163,6 +204,11 @@ OPUS_CUSTOM_NOSTATIC int opus_custom_decoder_init(CELTDecoder *st, const CELTMod
    st->start = 0;
    st->end = st->mode->effEBands;
    st->signalling = 1;
+#ifndef DISABLE_UPDATE_DRAFT
+   st->disable_inv = channels == 1;
+#else
+   st->disable_inv = 0;
+#endif
    st->arch = opus_select_arch();
 
    opus_custom_decoder_ctl(st, OPUS_RESET_STATE);
@@ -177,6 +223,36 @@ void opus_custom_decoder_destroy(CELTDecoder *st)
 }
 #endif /* CUSTOM_MODES */
 
+#ifndef CUSTOM_MODES
+/* Special case for stereo with no downsampling and no accumulation. This is
+   quite common and we can make it faster by processing both channels in the
+   same loop, reducing overhead due to the dependency loop in the IIR filter. */
+static void deemphasis_stereo_simple(celt_sig *in[], opus_val16 *pcm, int N, const opus_val16 coef0,
+      celt_sig *mem)
+{
+   celt_sig * OPUS_RESTRICT x0;
+   celt_sig * OPUS_RESTRICT x1;
+   celt_sig m0, m1;
+   int j;
+   x0=in[0];
+   x1=in[1];
+   m0 = mem[0];
+   m1 = mem[1];
+   for (j=0;j<N;j++)
+   {
+      celt_sig tmp0, tmp1;
+      /* Add VERY_SMALL to x[] first to reduce dependency chain. */
+      tmp0 = x0[j] + VERY_SMALL + m0;
+      tmp1 = x1[j] + VERY_SMALL + m1;
+      m0 = MULT16_32_Q15(coef0, tmp0);
+      m1 = MULT16_32_Q15(coef0, tmp1);
+      pcm[2*j  ] = SCALEOUT(SIG2WORD16(tmp0));
+      pcm[2*j+1] = SCALEOUT(SIG2WORD16(tmp1));
+   }
+   mem[0] = m0;
+   mem[1] = m1;
+}
+#endif
 
 #ifndef RESYNTH
 static
@@ -190,6 +266,14 @@ void deemphasis(celt_sig *in[], opus_val16 *pcm, int N, int C, int downsample, c
    opus_val16 coef0;
    VARDECL(celt_sig, scratch);
    SAVE_STACK;
+#ifndef CUSTOM_MODES
+   /* Short version for common case. */
+   if (downsample == 1 && C == 2 && !accum)
+   {
+      deemphasis_stereo_simple(in, pcm, N, coef[0], mem);
+      return;
+   }
+#endif
 #ifndef FIXED_POINT
    (void)accum;
    celt_assert(accum==0);
@@ -225,7 +309,7 @@ void deemphasis(celt_sig *in[], opus_val16 *pcm, int N, int C, int downsample, c
          /* Shortcut for the standard (non-custom modes) case */
          for (j=0;j<N;j++)
          {
-            celt_sig tmp = x[j] + m + VERY_SMALL;
+            celt_sig tmp = x[j] + VERY_SMALL + m;
             m = MULT16_32_Q15(coef0, tmp);
             scratch[j] = tmp;
          }
@@ -246,7 +330,7 @@ void deemphasis(celt_sig *in[], opus_val16 *pcm, int N, int C, int downsample, c
          {
             for (j=0;j<N;j++)
             {
-               celt_sig tmp = x[j] + m + VERY_SMALL;
+               celt_sig tmp = x[j] + VERY_SMALL + m;
                m = MULT16_32_Q15(coef0, tmp);
                y[j*C] = SCALEOUT(SIG2WORD16(tmp));
             }
@@ -333,7 +417,7 @@ void celt_synthesis(const CELTMode *mode, celt_norm *X, celt_sig * out_syn[],
       denormalise_bands(mode, X+N, freq2, oldBandE+nbEBands, start, effEnd, M,
             downsample, silence);
       for (i=0;i<N;i++)
-         freq[i] = HALF32(ADD32(freq[i],freq2[i]));
+         freq[i] = ADD32(HALF32(freq[i]), HALF32(freq2[i]));
       for (b=0;b<B;b++)
          clt_mdct_backward(&mode->mdct, &freq[b], out_syn[0]+NB*b, mode->window, overlap, shift, B, arch);
    } else {
@@ -345,6 +429,12 @@ void celt_synthesis(const CELTMode *mode, celt_norm *X, celt_sig * out_syn[],
             clt_mdct_backward(&mode->mdct, &freq[b], out_syn[c]+NB*b, mode->window, overlap, shift, B, arch);
       } while (++c<CC);
    }
+   /* Saturate IMDCT output so that we can't overflow in the pitch postfilter
+      or in the */
+   c=0; do {
+      for (i=0;i<N;i++)
+         out_syn[c][i] = SATURATE(out_syn[c][i], SIG_SAT);
+   } while (++c<CC);
    RESTORE_STACK;
 }
 
@@ -387,14 +477,6 @@ static void tf_decode(int start, int end, int isTransient, int *tf_res, int LM,
    }
 }
 
-/* The maximum pitch lag to allow in the pitch-based PLC. It's possible to save
-   CPU time in the PLC pitch search by making this smaller than MAX_PERIOD. The
-   current value corresponds to a pitch of 66.67 Hz. */
-#define PLC_PITCH_LAG_MAX (720)
-/* The minimum pitch lag to allow in the pitch-based PLC. This corresponds to a
-   pitch of 480 Hz. */
-#define PLC_PITCH_LAG_MIN (100)
-
 static int celt_plc_pitch_search(celt_sig *decode_mem[2], int C, int arch)
 {
    int pitch_index;
@@ -504,12 +586,15 @@ static void celt_decode_lost(CELTDecoder * OPUS_RESTRICT st, int N, int LM)
 
       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;
       opus_val16 fade = Q15ONE;
       int pitch_index;
       VARDECL(opus_val32, etmp);
-      VARDECL(opus_val16, exc);
+      VARDECL(opus_val16, _exc);
+      VARDECL(opus_val16, fir_tmp);
 
       if (loss_count == 0)
       {
@@ -519,8 +604,14 @@ static void celt_decode_lost(CELTDecoder * OPUS_RESTRICT st, int N, int LM)
          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, opus_val16);
+      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 {
          opus_val16 decay;
@@ -529,13 +620,11 @@ static void celt_decode_lost(CELTDecoder * OPUS_RESTRICT st, int N, int LM)
          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)
          {
@@ -561,22 +650,32 @@ static void celt_decode_lost(CELTDecoder * OPUS_RESTRICT st, int N, int LM)
 #endif
             }
             _celt_lpc(lpc+c*LPC_ORDER, ac, LPC_ORDER);
+#ifdef FIXED_POINT
+         /* For fixed-point, apply bandwidth expansion until we can guarantee that
+            no overflow can happen in the IIR filter. This means:
+            32768*sum(abs(filter)) < 2^31 */
+         while (1) {
+            opus_val16 tmp=Q15ONE;
+            opus_val32 sum=QCONST16(1., SIG_SHIFT);
+            for (i=0;i<LPC_ORDER;i++)
+               sum += ABS16(lpc[c*LPC_ORDER+i]);
+            if (sum < 65535) break;
+            for (i=0;i<LPC_ORDER;i++)
+            {
+               tmp = MULT16_16_Q15(QCONST16(.99f,15), tmp);
+               lpc[c*LPC_ORDER+i] = MULT16_16_Q15(lpc[c*LPC_ORDER+i], tmp);
+            }
+         }
+#endif
          }
-         /* We want the excitation for 2 pitch periods in order to look for a
-            decaying signal, but we can't get more than MAX_PERIOD. */
-         exc_length = IMIN(2*pitch_index, MAX_PERIOD);
          /* Initialize the LPC history with the samples just before the start
             of the region for which we're computing the excitation. */
          {
-            opus_val16 lpc_mem[LPC_ORDER];
-            for (i=0;i<LPC_ORDER;i++)
-            {
-               lpc_mem[i] =
-                     ROUND16(buf[DECODE_BUFFER_SIZE-exc_length-1-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, lpc_mem, 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.
@@ -630,9 +729,8 @@ static void celt_decode_lost(CELTDecoder * OPUS_RESTRICT st, int N, int LM)
             tmp = ROUND16(
                   buf[DECODE_BUFFER_SIZE-MAX_PERIOD-N+extrapolation_offset+j],
                   SIG_SHIFT);
-            S1 += SHR32(MULT16_16(tmp, tmp), 8);
+            S1 += SHR32(MULT16_16(tmp, tmp), 10);
          }
-
          {
             opus_val16 lpc_mem[LPC_ORDER];
             /* Copy the last decoded samples (prior to the overlap region) to
@@ -644,6 +742,10 @@ static void celt_decode_lost(CELTDecoder * OPUS_RESTRICT st, int N, int LM)
             celt_iir(buf+DECODE_BUFFER_SIZE-N, lpc+c*LPC_ORDER,
                   buf+DECODE_BUFFER_SIZE-N, extrapolation_len, LPC_ORDER,
                   lpc_mem, st->arch);
+#ifdef FIXED_POINT
+            for (i=0; i < extrapolation_len; i++)
+               buf[DECODE_BUFFER_SIZE-N+i] = SATURATE(buf[DECODE_BUFFER_SIZE-N+i], SIG_SAT);
+#endif
          }
 
          /* Check if the synthesis energy is higher than expected, which can
@@ -654,7 +756,7 @@ static void celt_decode_lost(CELTDecoder * OPUS_RESTRICT st, int N, int LM)
             for (i=0;i<extrapolation_len;i++)
             {
                opus_val16 tmp = ROUND16(buf[DECODE_BUFFER_SIZE-N+i], SIG_SHIFT);
-               S2 += SHR32(MULT16_16(tmp, tmp), 8);
+               S2 += SHR32(MULT16_16(tmp, tmp), 10);
             }
             /* This checks for an "explosion" in the synthesis. */
 #ifdef FIXED_POINT
@@ -762,6 +864,7 @@ int celt_decode_with_ec(CELTDecoder * OPUS_RESTRICT st, const unsigned char *dat
    const opus_int16 *eBands;
    ALLOC_STACK;
 
+   VALIDATE_CELT_DECODER(st);
    mode = st->mode;
    nbEBands = mode->nbEBands;
    overlap = mode->overlap;
@@ -956,7 +1059,7 @@ int celt_decode_with_ec(CELTDecoder * OPUS_RESTRICT st, const unsigned char *dat
    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);
 
@@ -979,7 +1082,8 @@ int celt_decode_with_ec(CELTDecoder * OPUS_RESTRICT st, const unsigned char *dat
 
    quant_all_bands(0, mode, start, end, X, C==2 ? X+N : NULL, collapse_masks,
          NULL, pulses, shortBlocks, spread_decision, dual_stereo, intensity, tf_res,
-         len*(8<<BITRES)-anti_collapse_rsv, balance, dec, LM, codedBands, &st->rng, st->arch);
+         len*(8<<BITRES)-anti_collapse_rsv, balance, dec, LM, codedBands, &st->rng, 0,
+         st->arch, st->disable_inv);
 
    if (anti_collapse_rsv > 0)
    {
@@ -1234,6 +1338,26 @@ int opus_custom_decoder_ctl(CELTDecoder * OPUS_RESTRICT st, int request, ...)
          *value=st->rng;
       }
       break;
+      case OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST:
+      {
+          opus_int32 value = va_arg(ap, opus_int32);
+          if(value<0 || value>1)
+          {
+             goto bad_arg;
+          }
+          st->disable_inv = value;
+      }
+      break;
+      case OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST:
+      {
+          opus_int32 *value = va_arg(ap, opus_int32*);
+          if (!value)
+          {
+             goto bad_arg;
+          }
+          *value = st->disable_inv;
+      }
+      break;
       default:
          goto bad_request;
    }

+ 298 - 101
thirdparty/opus/celt/celt_encoder.c

@@ -73,8 +73,8 @@ struct OpusCustomEncoder {
    int constrained_vbr;      /* If zero, VBR can do whatever it likes with the rate */
    int loss_rate;
    int lsb_depth;
-   int variable_duration;
    int lfe;
+   int disable_inv;
    int arch;
 
    /* Everything beyond this point gets cleared on a reset */
@@ -98,6 +98,7 @@ struct OpusCustomEncoder {
 #endif
    int consec_transient;
    AnalysisInfo analysis;
+   SILKInfo silk_info;
 
    opus_val32 preemph_memE[2];
    opus_val32 preemph_memD[2];
@@ -123,6 +124,7 @@ struct OpusCustomEncoder {
    /* opus_val16 oldBandE[],     Size = channels*mode->nbEBands */
    /* opus_val16 oldLogE[],      Size = channels*mode->nbEBands */
    /* opus_val16 oldLogE2[],     Size = channels*mode->nbEBands */
+   /* opus_val16 energyError[],  Size = channels*mode->nbEBands */
 };
 
 int celt_encoder_get_size(int channels)
@@ -136,9 +138,10 @@ OPUS_CUSTOM_NOSTATIC int opus_custom_encoder_get_size(const CELTMode *mode, int
    int size = sizeof(struct CELTEncoder)
          + (channels*mode->overlap-1)*sizeof(celt_sig)    /* celt_sig in_mem[channels*mode->overlap]; */
          + channels*COMBFILTER_MAXPERIOD*sizeof(celt_sig) /* celt_sig prefilter_mem[channels*COMBFILTER_MAXPERIOD]; */
-         + 3*channels*mode->nbEBands*sizeof(opus_val16);  /* opus_val16 oldBandE[channels*mode->nbEBands]; */
+         + 4*channels*mode->nbEBands*sizeof(opus_val16);  /* opus_val16 oldBandE[channels*mode->nbEBands]; */
                                                           /* opus_val16 oldLogE[channels*mode->nbEBands]; */
                                                           /* opus_val16 oldLogE2[channels*mode->nbEBands]; */
+                                                          /* opus_val16 energyError[channels*mode->nbEBands]; */
    return size;
 }
 
@@ -178,7 +181,6 @@ static int opus_custom_encoder_init_arch(CELTEncoder *st, const CELTMode *mode,
    st->start = 0;
    st->end = st->mode->effEBands;
    st->signalling = 1;
-
    st->arch = arch;
 
    st->constrained_vbr = 1;
@@ -223,7 +225,8 @@ void opus_custom_encoder_destroy(CELTEncoder *st)
 
 
 static int transient_analysis(const opus_val32 * OPUS_RESTRICT in, int len, int C,
-                              opus_val16 *tf_estimate, int *tf_chan)
+                              opus_val16 *tf_estimate, int *tf_chan, int allow_weak_transients,
+                              int *weak_transient)
 {
    int i;
    VARDECL(opus_val16, tmp);
@@ -233,6 +236,12 @@ static int transient_analysis(const opus_val32 * OPUS_RESTRICT in, int len, int
    int c;
    opus_val16 tf_max;
    int len2;
+   /* Forward masking: 6.7 dB/ms. */
+#ifdef FIXED_POINT
+   int forward_shift = 4;
+#else
+   opus_val16 forward_decay = QCONST16(.0625f,15);
+#endif
    /* Table of 6*64/x, trained on real data to minimize the average error */
    static const unsigned char inv_table[128] = {
          255,255,156,110, 86, 70, 59, 51, 45, 40, 37, 33, 31, 28, 26, 25,
@@ -247,6 +256,19 @@ static int transient_analysis(const opus_val32 * OPUS_RESTRICT in, int len, int
    SAVE_STACK;
    ALLOC(tmp, len, opus_val16);
 
+   *weak_transient = 0;
+   /* For lower bitrates, let's be more conservative and have a forward masking
+      decay of 3.3 dB/ms. This avoids having to code transients at very low
+      bitrate (mostly for hybrid), which can result in unstable energy and/or
+      partial collapse. */
+   if (allow_weak_transients)
+   {
+#ifdef FIXED_POINT
+      forward_shift = 5;
+#else
+      forward_decay = QCONST16(.03125f,15);
+#endif
+   }
    len2=len/2;
    for (c=0;c<C;c++)
    {
@@ -269,7 +291,7 @@ static int transient_analysis(const opus_val32 * OPUS_RESTRICT in, int len, int
          mem0 = mem1 + y - 2*x;
          mem1 = x - .5f*y;
 #endif
-         tmp[i] = EXTRACT16(SHR32(y,2));
+         tmp[i] = SROUND16(y, 2);
          /*printf("%f ", tmp[i]);*/
       }
       /*printf("\n");*/
@@ -280,7 +302,7 @@ static int transient_analysis(const opus_val32 * OPUS_RESTRICT in, int len, int
       /* Normalize tmp to max range */
       {
          int shift=0;
-         shift = 14-celt_ilog2(1+celt_maxabs16(tmp, len));
+         shift = 14-celt_ilog2(MAX16(1, celt_maxabs16(tmp, len)));
          if (shift!=0)
          {
             for (i=0;i<len;i++)
@@ -299,9 +321,9 @@ static int transient_analysis(const opus_val32 * OPUS_RESTRICT in, int len, int
          mean += x2;
 #ifdef FIXED_POINT
          /* FIXME: Use PSHR16() instead */
-         tmp[i] = mem0 + PSHR32(x2-mem0,4);
+         tmp[i] = mem0 + PSHR32(x2-mem0,forward_shift);
 #else
-         tmp[i] = mem0 + MULT16_16_P15(QCONST16(.0625f,15),x2-mem0);
+         tmp[i] = mem0 + MULT16_16_P15(forward_decay,x2-mem0);
 #endif
          mem0 = tmp[i];
       }
@@ -311,6 +333,7 @@ static int transient_analysis(const opus_val32 * OPUS_RESTRICT in, int len, int
       /* Backward pass to compute the pre-echo threshold */
       for (i=len2-1;i>=0;i--)
       {
+         /* Backward masking: 13.9 dB/ms. */
 #ifdef FIXED_POINT
          /* FIXME: Use PSHR16() instead */
          tmp[i] = mem0 + PSHR32(tmp[i]-mem0,3);
@@ -339,6 +362,12 @@ static int transient_analysis(const opus_val32 * OPUS_RESTRICT in, int len, int
       /* 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;
@@ -359,7 +388,12 @@ static int transient_analysis(const opus_val32 * OPUS_RESTRICT in, int len, int
       }
    }
    is_transient = mask_metric>200;
-
+   /* For low bitrates, define "weak transients" that need to be
+      handled differently to avoid partial collapse. */
+   if (allow_weak_transients && is_transient && mask_metric<600) {
+      is_transient = 0;
+      *weak_transient = 1;
+   }
    /* Arbitrary metric for VBR boost */
    tf_max = MAX16(0,celt_sqrt(27*mask_metric)-42);
    /* *tf_estimate = 1 + MIN16(1, sqrt(MAX16(0, tf_max-30))/20); */
@@ -549,7 +583,7 @@ static opus_val32 l1_metric(const celt_norm *tmp, int N, int LM, opus_val16 bias
 
 static int tf_analysis(const CELTMode *m, int len, int isTransient,
       int *tf_res, int lambda, celt_norm *X, int N0, int LM,
-      int *tf_sum, opus_val16 tf_estimate, int tf_chan)
+      opus_val16 tf_estimate, int tf_chan, int *importance)
 {
    int i;
    VARDECL(int, metric);
@@ -574,7 +608,6 @@ static int tf_analysis(const CELTMode *m, int len, int isTransient,
    ALLOC(path0, len, int);
    ALLOC(path1, len, int);
 
-   *tf_sum = 0;
    for (i=0;i<len;i++)
    {
       int k, N;
@@ -629,27 +662,26 @@ static int tf_analysis(const CELTMode *m, int len, int isTransient,
          metric[i] = 2*best_level;
       else
          metric[i] = -2*best_level;
-      *tf_sum += (isTransient ? LM : 0) - metric[i]/2;
       /* For bands that can't be split to -1, set the metric to the half-way point to avoid
          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;
@@ -658,8 +690,8 @@ static int tf_analysis(const CELTMode *m, int len, int isTransient,
     * 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++)
    {
@@ -687,8 +719,8 @@ static int tf_analysis(const CELTMode *m, int len, int isTransient,
          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 */
@@ -754,7 +786,7 @@ static void tf_encode(int start, int end, int isTransient, int *tf_res, int LM,
 static int alloc_trim_analysis(const CELTMode *m, const celt_norm *X,
       const opus_val16 *bandLogE, int end, int LM, int C, int N0,
       AnalysisInfo *analysis, opus_val16 *stereo_saving, opus_val16 tf_estimate,
-      int intensity, opus_val16 surround_trim, int arch)
+      int intensity, opus_val16 surround_trim, opus_int32 equiv_rate, int arch)
 {
    int i;
    opus_val32 diff=0;
@@ -762,6 +794,14 @@ static int alloc_trim_analysis(const CELTMode *m, const celt_norm *X,
    int trim_index;
    opus_val16 trim = QCONST16(5.f, 8);
    opus_val16 logXC, logXC2;
+   /* At low bitrate, reducing the trim seems to help. At higher bitrates, it's less
+      clear what's best, so we're keeping it as it was before, at least for now. */
+   if (equiv_rate < 64000) {
+      trim = QCONST16(4.f, 8);
+   } else if (equiv_rate < 80000) {
+      opus_int32 frac = (equiv_rate-64000) >> 10;
+      trim = QCONST16(4.f, 8) + QCONST16(1.f/16.f, 8)*frac;
+   }
    if (C==2)
    {
       opus_val16 sum = 0; /* Q10 */
@@ -809,7 +849,7 @@ static int alloc_trim_analysis(const CELTMode *m, const celt_norm *X,
    } while (++c<C);
    diff /= C*(end-1);
    /*printf("%f\n", diff);*/
-   trim -= MAX16(-QCONST16(2.f, 8), MIN16(QCONST16(2.f, 8), SHR16(diff+QCONST16(1.f, DB_SHIFT),DB_SHIFT-8)/6 ));
+   trim -= MAX32(-QCONST16(2.f, 8), MIN32(QCONST16(2.f, 8), SHR32(diff+QCONST16(1.f, DB_SHIFT),DB_SHIFT-8)/6 ));
    trim -= SHR16(surround_trim, DB_SHIFT-8);
    trim -= 2*SHR16(tf_estimate, 14-8);
 #ifndef DISABLE_FLOAT_API
@@ -930,7 +970,8 @@ static opus_val16 median_of_3(const opus_val16 *x)
 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)
+      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;
@@ -956,6 +997,42 @@ static opus_val16 dynalloc_analysis(const opus_val16 *bandLogE, const opus_val16
       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)
    {
@@ -1012,6 +1089,14 @@ static opus_val16 dynalloc_analysis(const opus_val16 *bandLogE, const opus_val16
       }
       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)
       {
@@ -1020,14 +1105,26 @@ static opus_val16 dynalloc_analysis(const opus_val16 *bandLogE, const opus_val16
       }
       for (i=start;i<end;i++)
       {
-         int width;
-         int boost;
-         int boost_bits;
-
          if (i<8)
             follower[i] *= 2;
          if (i>=12)
             follower[i] = HALF16(follower[i]);
+      }
+#ifdef DISABLE_FLOAT_API
+      (void)analysis;
+#else
+      if (analysis->valid)
+      {
+         for (i=start;i<IMIN(LEAK_BANDS, end);i++)
+            follower[i] = follower[i] +  QCONST16(1.f/64.f, DB_SHIFT)*analysis->leak_boost[i];
+      }
+#endif
+      for (i=start;i<end;i++)
+      {
+         int width;
+         int boost;
+         int boost_bits;
+
          follower[i] = MIN16(follower[i], QCONST16(4, DB_SHIFT));
 
          width = C*(eBands[i+1]-eBands[i])<<LM;
@@ -1042,11 +1139,11 @@ static opus_val16 dynalloc_analysis(const opus_val16 *bandLogE, const opus_val16
             boost = (int)SHR32(EXTEND32(follower[i])*width/6,DB_SHIFT);
             boost_bits = boost*6<<BITRES;
          }
-         /* For CBR and non-transient CVBR frames, limit dynalloc to 1/4 of the bits */
+         /* For CBR and non-transient CVBR frames, limit dynalloc to 2/3 of the bits */
          if ((!vbr || (constrained_vbr&&!isTransient))
-               && (tot_boost+boost_bits)>>BITRES>>3 > effectiveBytes/4)
+               && (tot_boost+boost_bits)>>BITRES>>3 > 2*effectiveBytes/3)
          {
-            opus_int32 cap = ((effectiveBytes/4)<<BITRES<<3);
+            opus_int32 cap = ((2*effectiveBytes/3)<<BITRES<<3);
             offsets[i] = cap-tot_boost;
             tot_boost = cap;
             break;
@@ -1055,6 +1152,9 @@ static opus_val16 dynalloc_analysis(const opus_val16 *bandLogE, const opus_val16
             tot_boost += boost_bits;
          }
       }
+   } else {
+      for (i=start;i<end;i++)
+         importance[i] = 13;
    }
    *tot_boost_ = tot_boost;
    RESTORE_STACK;
@@ -1063,7 +1163,7 @@ static opus_val16 dynalloc_analysis(const opus_val16 *bandLogE, const opus_val16
 
 
 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);
@@ -1119,7 +1219,12 @@ static int run_prefilter(CELTEncoder *st, celt_sig *in, celt_sig *prefilter_mem,
       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);
 
@@ -1193,7 +1298,7 @@ static int compute_vbr(const CELTMode *mode, AnalysisInfo *analysis, opus_int32
       int LM, opus_int32 bitrate, int lastCodedBands, int C, int intensity,
       int constrained_vbr, opus_val16 stereo_saving, int tot_boost,
       opus_val16 tf_estimate, int pitch_change, opus_val16 maxDepth,
-      int variable_duration, int lfe, int has_surround_mask, opus_val16 surround_masking,
+      int lfe, int has_surround_mask, opus_val16 surround_masking,
       opus_val16 temporal_vbr)
 {
    /* The target rate in 8th bits per frame */
@@ -1235,10 +1340,9 @@ static int compute_vbr(const CELTMode *mode, AnalysisInfo *analysis, opus_int32
                       SHR32(MULT16_16(stereo_saving-QCONST16(0.1f,8),(coded_stereo_dof<<BITRES)),8));
    }
    /* Boost the rate according to dynalloc (minus the dynalloc average for calibration). */
-   target += tot_boost-(16<<LM);
+   target += tot_boost-(19<<LM);
    /* Apply transient boost, compensating for average boost. */
-   tf_calibration = variable_duration==OPUS_FRAMESIZE_VARIABLE ?
-                    QCONST16(0.02f,14) : QCONST16(0.04f,14);
+   tf_calibration = QCONST16(0.044f,14);
    target += (opus_int32)SHL32(MULT16_32_Q15(tf_estimate-tf_calibration, target),1);
 
 #ifndef DISABLE_FLOAT_API
@@ -1249,7 +1353,7 @@ static int compute_vbr(const CELTMode *mode, AnalysisInfo *analysis, opus_int32
       float tonal;
 
       /* Tonality boost (compensating for the average). */
-      tonal = MAX16(0.f,analysis->tonality-.15f)-0.09f;
+      tonal = MAX16(0.f,analysis->tonality-.15f)-0.12f;
       tonal_target = target + (opus_int32)((coded_bins<<BITRES)*1.2f*tonal);
       if (pitch_change)
          tonal_target +=  (opus_int32)((coded_bins<<BITRES)*.8f);
@@ -1279,21 +1383,11 @@ static int compute_vbr(const CELTMode *mode, AnalysisInfo *analysis, opus_int32
       /*printf("%f %d\n", maxDepth, floor_depth);*/
    }
 
-   if ((!has_surround_mask||lfe) && (constrained_vbr || bitrate<64000))
+   /* Make VBR less aggressive for constrained VBR because we can't keep a higher bitrate
+      for long. Needs tuning. */
+   if ((!has_surround_mask||lfe) && constrained_vbr)
    {
-      opus_val16 rate_factor = Q15ONE;
-      if (bitrate < 64000)
-      {
-#ifdef FIXED_POINT
-         rate_factor = MAX16(0,(bitrate-32000));
-#else
-         rate_factor = MAX16(0,(1.f/32768)*(bitrate-32000));
-#endif
-      }
-      if (constrained_vbr)
-         rate_factor = MIN16(rate_factor, QCONST16(0.67f, 15));
-      target = base_target + (opus_int32)MULT16_32_Q15(rate_factor, target-base_target);
-
+      target = base_target + (opus_int32)MULT16_32_Q15(QCONST16(0.67f, 15), target-base_target);
    }
 
    if (!has_surround_mask && tf_estimate < QCONST16(.2f, 14))
@@ -1327,11 +1421,13 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm,
    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);
    celt_sig *prefilter_mem;
-   opus_val16 *oldBandE, *oldLogE, *oldLogE2;
+   opus_val16 *oldBandE, *oldLogE, *oldLogE2, *energyError;
    int shortBlocks=0;
    int isTransient=0;
    const int CC = st->channels;
@@ -1343,7 +1439,6 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm,
    int end;
    int effEnd;
    int codedBands;
-   int tf_sum;
    int alloc_trim;
    int pitch_index=COMBFILTER_MINPERIOD;
    opus_val16 gain1 = 0;
@@ -1355,6 +1450,7 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm,
    opus_int32 total_boost;
    opus_int32 balance;
    opus_int32 tell;
+   opus_int32 tell0_frac;
    int prefilter_tapset=0;
    int pf_on;
    int anti_collapse_rsv;
@@ -1376,7 +1472,10 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm,
    opus_val16 surround_masking=0;
    opus_val16 temporal_vbr=0;
    opus_val16 surround_trim = 0;
-   opus_int32 equiv_rate = 510000;
+   opus_int32 equiv_rate;
+   int hybrid;
+   int weak_transient = 0;
+   int enable_tf_analysis;
    VARDECL(opus_val16, surround_dynalloc);
    ALLOC_STACK;
 
@@ -1386,6 +1485,7 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm,
    eBands = mode->eBands;
    start = st->start;
    end = st->end;
+   hybrid = start != 0;
    tf_estimate = 0;
    if (nbCompressedBytes<2 || pcm==NULL)
    {
@@ -1409,12 +1509,14 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm,
    oldBandE = (opus_val16*)(st->in_mem+CC*(overlap+COMBFILTER_MAXPERIOD));
    oldLogE = oldBandE + CC*nbEBands;
    oldLogE2 = oldLogE + CC*nbEBands;
+   energyError = oldLogE2 + CC*nbEBands;
 
    if (enc==NULL)
    {
-      tell=1;
+      tell0_frac=tell=1;
       nbFilledBytes=0;
    } else {
+      tell0_frac=ec_tell_frac(enc);
       tell=ec_tell(enc);
       nbFilledBytes=(tell+4)>>3;
    }
@@ -1467,10 +1569,11 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm,
       if (st->bitrate!=OPUS_BITRATE_MAX)
          nbCompressedBytes = IMAX(2, IMIN(nbCompressedBytes,
                (tmp+4*mode->Fs)/(8*mode->Fs)-!!st->signalling));
-      effectiveBytes = nbCompressedBytes;
+      effectiveBytes = nbCompressedBytes - nbFilledBytes;
    }
+   equiv_rate = ((opus_int32)nbCompressedBytes*8*50 >> (3-LM)) - (40*C+20)*((400>>LM) - 50);
    if (st->bitrate != OPUS_BITRATE_MAX)
-      equiv_rate = st->bitrate - (40*C+20)*((400>>LM) - 50);
+      equiv_rate = IMIN(equiv_rate, st->bitrate - (40*C+20)*((400>>LM) - 50));
 
    if (enc==NULL)
    {
@@ -1558,17 +1661,17 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm,
    {
       int enabled;
       int qg;
-      enabled = ((st->lfe&&nbAvailableBytes>3) || nbAvailableBytes>12*C) && start==0 && !silence && !st->disable_pf
-            && st->complexity >= 5 && !(st->consec_transient && LM!=3 && st->variable_duration==OPUS_FRAMESIZE_VARIABLE);
+      enabled = ((st->lfe&&nbAvailableBytes>3) || nbAvailableBytes>12*C) && !hybrid && !silence && !st->disable_pf
+            && 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;
       if (pf_on==0)
       {
-         if(start==0 && tell+16<=total_bits)
+         if(!hybrid && tell+16<=total_bits)
             ec_enc_bit_logp(enc, 0, 1);
       } else {
          /*This block is not gated by a total bits check only because
@@ -1589,8 +1692,12 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm,
    shortBlocks = 0;
    if (st->complexity >= 1 && !st->lfe)
    {
+      /* 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.signalType != 2;
       isTransient = transient_analysis(in, N+overlap, CC,
-            &tf_estimate, &tf_chan);
+            &tf_estimate, &tf_chan, allow_weak_transients, &weak_transient);
    }
    if (LM>0 && ec_tell(enc)+3<=total_bits)
    {
@@ -1610,16 +1717,19 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm,
    if (secondMdct)
    {
       compute_mdcts(mode, 0, in, freq, C, CC, LM, st->upsample, st->arch);
-      compute_band_energies(mode, freq, bandE, effEnd, C, LM);
+      compute_band_energies(mode, freq, bandE, effEnd, C, LM, st->arch);
       amp2Log2(mode, effEnd, end, bandE, bandLogE2, C);
       for (i=0;i<C*nbEBands;i++)
          bandLogE2[i] += HALF16(SHL16(LM, DB_SHIFT));
    }
 
    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);
+   compute_band_energies(mode, freq, bandE, effEnd, C, LM, st->arch);
 
    if (st->lfe)
    {
@@ -1634,7 +1744,7 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm,
    ALLOC(surround_dynalloc, C*nbEBands, opus_val16);
    OPUS_CLEAR(surround_dynalloc, end);
    /* This computes how much masking takes place between surround channels */
-   if (start==0&&st->energy_mask&&!st->lfe)
+   if (!hybrid&&st->energy_mask&&!st->lfe)
    {
       int mask_end;
       int midband;
@@ -1736,14 +1846,14 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm,
 
    /* Last chance to catch any transient we might have missed in the
       time-domain analysis */
-   if (LM>0 && ec_tell(enc)+3<=total_bits && !isTransient && st->complexity>=5 && !st->lfe)
+   if (LM>0 && ec_tell(enc)+3<=total_bits && !isTransient && st->complexity>=5 && !st->lfe && !hybrid)
    {
       if (patch_transient_decision(bandLogE, oldBandE, nbEBands, start, end, C))
       {
          isTransient = 1;
          shortBlocks = M;
          compute_mdcts(mode, shortBlocks, in, freq, C, CC, LM, st->upsample, st->arch);
-         compute_band_energies(mode, freq, bandE, effEnd, C, LM);
+         compute_band_energies(mode, freq, bandE, effEnd, C, LM, st->arch);
          amp2Log2(mode, effEnd, end, bandE, bandLogE, C);
          /* Compensate for the scaling of short vs long mdcts */
          for (i=0;i<C*nbEBands;i++)
@@ -1760,31 +1870,59 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm,
    /* 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 && start==0 && st->complexity>=2 && !st->lfe)
+   if (enable_tf_analysis)
    {
       int lambda;
-      if (effectiveBytes<40)
-         lambda = 12;
-      else if (effectiveBytes<60)
-         lambda = 6;
-      else if (effectiveBytes<100)
-         lambda = 4;
-      else
-         lambda = 3;
-      lambda*=2;
-      tf_select = tf_analysis(mode, effEnd, isTransient, tf_res, lambda, X, N, LM, &tf_sum, 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 weak transients, we rely on the fact that improving time resolution using
+         TF on a long window is imperfect and will not result in an energy collapse at
+         low bitrate. */
+      for (i=0;i<end;i++)
+         tf_res[i] = 1;
+      tf_select=0;
+   } 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++)
+         tf_res[i] = 0;
+      tf_select=isTransient;
    } else {
-      tf_sum = 0;
       for (i=0;i<end;i++)
          tf_res[i] = isTransient;
       tf_select=0;
    }
 
    ALLOC(error, C*nbEBands, opus_val16);
+   c=0;
+   do {
+      for (i=start;i<end;i++)
+      {
+         /* When the energy is stable, slightly bias energy quantization towards
+            the previous error to make the gain more stable (a constant offset is
+            better than fluctuations). */
+         if (ABS32(SUB32(bandLogE[i+c*nbEBands], oldBandE[i+c*nbEBands])) < QCONST16(2.f, DB_SHIFT))
+         {
+            bandLogE[i+c*nbEBands] -= MULT16_16_Q15(energyError[i+c*nbEBands], QCONST16(0.25f, 15));
+         }
+      }
+   } while (++c < C);
    quant_coarse_energy(mode, start, end, effEnd, bandLogE,
          oldBandE, total_bits, error, enc,
          C, LM, nbAvailableBytes, st->force_intra,
@@ -1798,7 +1936,15 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm,
       {
          st->tapset_decision = 0;
          st->spread_decision = SPREAD_NORMAL;
-      } else if (shortBlocks || st->complexity < 3 || nbAvailableBytes < 10*C || start != 0)
+      } else if (hybrid)
+      {
+         if (st->complexity == 0)
+            st->spread_decision = SPREAD_NONE;
+         else if (isTransient)
+            st->spread_decision = SPREAD_NORMAL;
+         else
+            st->spread_decision = SPREAD_AGGRESSIVE;
+      } else if (shortBlocks || st->complexity < 3 || nbAvailableBytes < 10*C)
       {
          if (st->complexity == 0)
             st->spread_decision = SPREAD_NONE;
@@ -1822,7 +1968,7 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm,
          {
             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);*/
@@ -1830,11 +1976,6 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm,
       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);
    /* For LFE, everything interesting is in the first band */
    if (st->lfe)
       offsets[0] = IMIN(8, effectiveBytes/3);
@@ -1896,12 +2037,15 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm,
    alloc_trim = 5;
    if (tell+(6<<BITRES) <= total_bits - total_boost)
    {
-      if (st->lfe)
+      if (start > 0 || st->lfe)
+      {
+         st->stereo_saving = 0;
          alloc_trim = 5;
-      else
+      } else {
          alloc_trim = alloc_trim_analysis(mode, X, bandLogE,
             end, LM, C, N, &st->analysis, &st->stereo_saving, tf_estimate,
-            st->intensity, surround_trim, st->arch);
+            st->intensity, surround_trim, equiv_rate, st->arch);
+      }
       ec_enc_icdf(enc, alloc_trim, trim_icdf, 7);
       tell = ec_tell_frac(enc);
    }
@@ -1919,17 +2063,36 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm,
      /* Don't attempt to use more than 510 kb/s, even for frames smaller than 20 ms.
         The CELT allocator will just not be able to use more than that anyway. */
      nbCompressedBytes = IMIN(nbCompressedBytes,1275>>(3-LM));
-     base_target = vbr_rate - ((40*C+20)<<BITRES);
+     if (!hybrid)
+     {
+        base_target = vbr_rate - ((40*C+20)<<BITRES);
+     } else {
+        base_target = IMAX(0, vbr_rate - ((9*C+4)<<BITRES));
+     }
 
      if (st->constrained_vbr)
         base_target += (st->vbr_offset>>lm_diff);
 
-     target = compute_vbr(mode, &st->analysis, base_target, LM, equiv_rate,
+     if (!hybrid)
+     {
+        target = compute_vbr(mode, &st->analysis, base_target, LM, equiv_rate,
            st->lastCodedBands, C, st->intensity, st->constrained_vbr,
            st->stereo_saving, tot_boost, tf_estimate, pitch_change, maxDepth,
-           st->variable_duration, st->lfe, st->energy_mask!=NULL, surround_masking,
+           st->lfe, st->energy_mask!=NULL, surround_masking,
            temporal_vbr);
-
+     } else {
+        target = base_target;
+        /* Tonal frames (offset<100) need more bits than noisy (offset>100) ones. */
+        if (st->silk_info.offset < 100) target += 12 << BITRES >> (3-LM);
+        if (st->silk_info.offset > 100) target -= 18 << BITRES >> (3-LM);
+        /* Boosting bitrate on transients and vowels with significant temporal
+           spikes. */
+        target += (opus_int32)MULT16_16_Q14(tf_estimate-QCONST16(.25f,14), (50<<BITRES));
+        /* If we have a strong transient, let's make sure it has enough bits to code
+           the first two bands, so that it can use folding rather than noise. */
+        if (tf_estimate > QCONST16(.7f,14))
+           target = IMAX(target, 50<<BITRES);
+     }
      /* The current offset is removed from the target and the space used
         so far is added*/
      target=target+tell;
@@ -1937,11 +2100,16 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm,
          result in the encoder running out of bits.
         The margin of 2 bytes ensures that none of the bust-prevention logic
          in the decoder will have triggered so far. */
-     min_allowed = ((tell+total_boost+(1<<(BITRES+3))-1)>>(BITRES+3)) + 2 - nbFilledBytes;
+     min_allowed = ((tell+total_boost+(1<<(BITRES+3))-1)>>(BITRES+3)) + 2;
+     /* Take into account the 37 bits we need to have left in the packet to
+        signal a redundant frame in hybrid mode. Creating a shorter packet would
+        create an entropy coder desync. */
+     if (hybrid)
+        min_allowed = IMAX(min_allowed, (tell0_frac+(37<<BITRES)+total_boost+(1<<(BITRES+3))-1)>>(BITRES+3));
 
      nbAvailableBytes = (target+(1<<(BITRES+2)))>>(BITRES+3);
      nbAvailableBytes = IMAX(min_allowed,nbAvailableBytes);
-     nbAvailableBytes = IMIN(nbCompressedBytes,nbAvailableBytes+nbFilledBytes) - nbFilledBytes;
+     nbAvailableBytes = IMIN(nbCompressedBytes,nbAvailableBytes);
 
      /* By how much did we "miss" the target on that frame */
      delta = target - vbr_rate;
@@ -1988,7 +2156,7 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm,
         st->vbr_reservoir = 0;
         /*printf ("+%d\n", adjust);*/
      }
-     nbCompressedBytes = IMIN(nbCompressedBytes,nbAvailableBytes+nbFilledBytes);
+     nbCompressedBytes = IMIN(nbCompressedBytes,nbAvailableBytes);
      /*printf("%d\n", nbCompressedBytes*50*8);*/
      /* This moves the raw bits to take into account the new compressed size */
      ec_enc_shrink(enc, nbCompressedBytes);
@@ -2023,7 +2191,7 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm,
 #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)
@@ -2038,7 +2206,7 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm,
    quant_all_bands(1, mode, start, end, X, C==2 ? X+N : NULL, collapse_masks,
          bandE, pulses, shortBlocks, st->spread_decision,
          dual_stereo, st->intensity, tf_res, nbCompressedBytes*(8<<BITRES)-anti_collapse_rsv,
-         balance, enc, LM, codedBands, &st->rng, st->arch);
+         balance, enc, LM, codedBands, &st->rng, st->complexity, st->arch, st->disable_inv);
 
    if (anti_collapse_rsv > 0)
    {
@@ -2049,6 +2217,14 @@ int celt_encode_with_ec(CELTEncoder * OPUS_RESTRICT st, const opus_val16 * pcm,
       ec_enc_bits(enc, anti_collapse_on, 1);
    }
    quant_energy_finalise(mode, start, end, oldBandE, error, fine_quant, fine_priority, nbCompressedBytes*8-ec_tell(enc), enc, C);
+   OPUS_CLEAR(energyError, nbEBands*CC);
+   c=0;
+   do {
+      for (i=start;i<end;i++)
+      {
+         energyError[i+c*nbEBands] = MAX16(-QCONST16(0.5f, 15), MIN16(QCONST16(0.5f, 15), error[i+c*nbEBands]));
+      }
+   } while (++c < C);
 
    if (silence)
    {
@@ -2321,10 +2497,24 @@ int opus_custom_encoder_ctl(CELTEncoder * OPUS_RESTRICT st, int request, ...)
           *value=st->lsb_depth;
       }
       break;
-      case OPUS_SET_EXPERT_FRAME_DURATION_REQUEST:
+      case OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST:
       {
           opus_int32 value = va_arg(ap, opus_int32);
-          st->variable_duration = value;
+          if(value<0 || value>1)
+          {
+             goto bad_arg;
+          }
+          st->disable_inv = value;
+      }
+      break;
+      case OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST:
+      {
+          opus_int32 *value = va_arg(ap, opus_int32*);
+          if (!value)
+          {
+             goto bad_arg;
+          }
+          *value = st->disable_inv;
       }
       break;
       case OPUS_RESET_STATE:
@@ -2368,6 +2558,13 @@ int opus_custom_encoder_ctl(CELTEncoder * OPUS_RESTRICT st, int request, ...)
             OPUS_COPY(&st->analysis, info, 1);
       }
       break;
+      case CELT_SET_SILK_INFO_REQUEST:
+      {
+         SILKInfo *info = va_arg(ap, SILKInfo *);
+         if (info)
+            OPUS_COPY(&st->silk_info, info, 1);
+      }
+      break;
       case CELT_GET_MODE_REQUEST:
       {
          const CELTMode ** value = va_arg(ap, const CELTMode**);

+ 22 - 40
thirdparty/opus/celt/celt_lpc.c

@@ -89,58 +89,40 @@ int          p
 
 
 void celt_fir_c(
-         const opus_val16 *_x,
+         const opus_val16 *x,
          const opus_val16 *num,
-         opus_val16 *_y,
+         opus_val16 *y,
          int N,
          int ord,
-         opus_val16 *mem,
          int arch)
 {
    int i,j;
    VARDECL(opus_val16, rnum);
-   VARDECL(opus_val16, x);
    SAVE_STACK;
-
+   celt_assert(x != y);
    ALLOC(rnum, ord, opus_val16);
-   ALLOC(x, N+ord, opus_val16);
    for(i=0;i<ord;i++)
       rnum[i] = num[ord-i-1];
-   for(i=0;i<ord;i++)
-      x[i] = mem[ord-i-1];
-   for (i=0;i<N;i++)
-      x[i+ord]=_x[i];
-   for(i=0;i<ord;i++)
-      mem[i] = _x[N-i-1];
-#ifdef SMALL_FOOTPRINT
-   (void)arch;
-   for (i=0;i<N;i++)
-   {
-      opus_val32 sum = SHL32(EXTEND32(_x[i]), SIG_SHIFT);
-      for (j=0;j<ord;j++)
-      {
-         sum = MAC16_16(sum,rnum[j],x[i+j]);
-      }
-      _y[i] = SATURATE16(PSHR32(sum, SIG_SHIFT));
-   }
-#else
    for (i=0;i<N-3;i+=4)
    {
-      opus_val32 sum[4]={0,0,0,0};
-      xcorr_kernel(rnum, x+i, sum, ord, arch);
-      _y[i  ] = SATURATE16(ADD32(EXTEND32(_x[i  ]), PSHR32(sum[0], SIG_SHIFT)));
-      _y[i+1] = SATURATE16(ADD32(EXTEND32(_x[i+1]), PSHR32(sum[1], SIG_SHIFT)));
-      _y[i+2] = SATURATE16(ADD32(EXTEND32(_x[i+2]), PSHR32(sum[2], SIG_SHIFT)));
-      _y[i+3] = SATURATE16(ADD32(EXTEND32(_x[i+3]), PSHR32(sum[3], SIG_SHIFT)));
+      opus_val32 sum[4];
+      sum[0] = SHL32(EXTEND32(x[i  ]), 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);
+      y[i  ] = ROUND16(sum[0], SIG_SHIFT);
+      y[i+1] = ROUND16(sum[1], SIG_SHIFT);
+      y[i+2] = ROUND16(sum[2], SIG_SHIFT);
+      y[i+3] = ROUND16(sum[3], SIG_SHIFT);
    }
    for (;i<N;i++)
    {
-      opus_val32 sum = 0;
+      opus_val32 sum = SHL32(EXTEND32(x[i]), SIG_SHIFT);
       for (j=0;j<ord;j++)
-         sum = MAC16_16(sum,rnum[j],x[i+j]);
-      _y[i] = SATURATE16(ADD32(EXTEND32(_x[i]), PSHR32(sum, SIG_SHIFT)));
+         sum = MAC16_16(sum,rnum[j],x[i+j-ord]);
+      y[i] = ROUND16(sum, SIG_SHIFT);
    }
-#endif
    RESTORE_STACK;
 }
 
@@ -166,7 +148,7 @@ void celt_iir(const opus_val32 *_x,
       {
          mem[j]=mem[j-1];
       }
-      mem[0] = ROUND16(sum,SIG_SHIFT);
+      mem[0] = SROUND16(sum, SIG_SHIFT);
       _y[i] = sum;
    }
 #else
@@ -195,20 +177,20 @@ void celt_iir(const opus_val32 *_x,
       xcorr_kernel(rden, y+i, sum, ord, arch);
 
       /* Patch up the result to compensate for the fact that this is an IIR */
-      y[i+ord  ] = -ROUND16(sum[0],SIG_SHIFT);
+      y[i+ord  ] = -SROUND16(sum[0],SIG_SHIFT);
       _y[i  ] = sum[0];
       sum[1] = MAC16_16(sum[1], y[i+ord  ], den[0]);
-      y[i+ord+1] = -ROUND16(sum[1],SIG_SHIFT);
+      y[i+ord+1] = -SROUND16(sum[1],SIG_SHIFT);
       _y[i+1] = sum[1];
       sum[2] = MAC16_16(sum[2], y[i+ord+1], den[0]);
       sum[2] = MAC16_16(sum[2], y[i+ord  ], den[1]);
-      y[i+ord+2] = -ROUND16(sum[2],SIG_SHIFT);
+      y[i+ord+2] = -SROUND16(sum[2],SIG_SHIFT);
       _y[i+2] = sum[2];
 
       sum[3] = MAC16_16(sum[3], y[i+ord+2], den[0]);
       sum[3] = MAC16_16(sum[3], y[i+ord+1], den[1]);
       sum[3] = MAC16_16(sum[3], y[i+ord  ], den[2]);
-      y[i+ord+3] = -ROUND16(sum[3],SIG_SHIFT);
+      y[i+ord+3] = -SROUND16(sum[3],SIG_SHIFT);
       _y[i+3] = sum[3];
    }
    for (;i<N;i++)
@@ -216,7 +198,7 @@ void celt_iir(const opus_val32 *_x,
       opus_val32 sum = _x[i];
       for (j=0;j<ord;j++)
          sum -= MULT16_16(rden[j],y[i+j]);
-      y[i+ord] = ROUND16(sum,SIG_SHIFT);
+      y[i+ord] = SROUND16(sum,SIG_SHIFT);
       _y[i] = sum;
    }
    for(i=0;i<ord;i++)

+ 2 - 3
thirdparty/opus/celt/celt_lpc.h

@@ -45,12 +45,11 @@ void celt_fir_c(
          opus_val16 *y,
          int N,
          int ord,
-         opus_val16 *mem,
          int arch);
 
 #if !defined(OVERRIDE_CELT_FIR)
-#define celt_fir(x, num, y, N, ord, mem, arch) \
-    (celt_fir_c(x, num, y, N, ord, mem, arch))
+#define celt_fir(x, num, y, N, ord, arch) \
+    (celt_fir_c(x, num, y, N, ord, arch))
 #endif
 
 void celt_iir(const opus_val32 *x,

+ 1 - 1
thirdparty/opus/celt/cwrs.c

@@ -482,7 +482,7 @@ static opus_val32 cwrsi(int _n,int _k,opus_uint32 _i,int *_y){
       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);

+ 2 - 2
thirdparty/opus/celt/entcode.h

@@ -122,7 +122,7 @@ opus_uint32 ec_tell_frac(ec_ctx *_this);
 
 /* 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;
@@ -138,7 +138,7 @@ static OPUS_INLINE opus_uint32 celt_udiv(opus_uint32 n, opus_uint32 d) {
 }
 
 static OPUS_INLINE opus_int32 celt_sudiv(opus_int32 n, opus_int32 d) {
-   celt_assert(d>0);
+   celt_sig_assert(d>0);
 #ifdef USE_SMALL_DIV_TABLE
    if (n<0)
       return -(opus_int32)celt_udiv(-n, d);

+ 1 - 1
thirdparty/opus/celt/entdec.h

@@ -85,7 +85,7 @@ int ec_dec_icdf(ec_dec *_this,const unsigned char *_icdf,unsigned _ftb);
   The bits must have been encoded with ec_enc_uint().
   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);
 

+ 1 - 1
thirdparty/opus/celt/entenc.h

@@ -67,7 +67,7 @@ void ec_enc_icdf(ec_enc *_this,int _s,const unsigned char *_icdf,unsigned _ftb);
 /*Encodes a raw unsigned integer in the stream.
   _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.

+ 79 - 0
thirdparty/opus/celt/fixed_c5x.h

@@ -0,0 +1,79 @@
+/* Copyright (C) 2003 Jean-Marc Valin */
+/**
+   @file fixed_c5x.h
+   @brief Fixed-point operations for the TI C5x DSP family
+*/
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef FIXED_C5X_H
+#define FIXED_C5X_H
+
+#include "dsplib.h"
+
+#undef IMUL32
+static OPUS_INLINE long IMUL32(long i, long j)
+{
+   long ac0, ac1;
+   ac0 = _lmpy(i>>16,j);
+   ac1 = ac0 + _lmpy(i,j>>16);
+   return _lmpyu(i,j) + (ac1<<16);
+}
+
+#undef MAX16
+#define MAX16(a,b) _max(a,b)
+
+#undef MIN16
+#define MIN16(a,b) _min(a,b)
+
+#undef MAX32
+#define MAX32(a,b) _lmax(a,b)
+
+#undef MIN32
+#define MIN32(a,b) _lmin(a,b)
+
+#undef VSHR32
+#define VSHR32(a, shift) _lshl(a,-(shift))
+
+#undef MULT16_16_Q15
+#define MULT16_16_Q15(a,b) (_smpy(a,b))
+
+#undef MULT16_16SU
+#define MULT16_16SU(a,b) _lmpysu(a,b)
+
+#undef MULT_16_16
+#define MULT_16_16(a,b) _lmpy(a,b)
+
+/* FIXME: This is technically incorrect and is bound to cause problems. Is there any cleaner solution? */
+#undef MULT16_32_Q15
+#define MULT16_32_Q15(a,b) ADD32(SHL(MULT16_16((a),SHR((b),16)),1), SHR(MULT16_16SU((a),(b)),15))
+
+#define celt_ilog2(x) (30 - _lnorm(x))
+#define OVERRIDE_CELT_ILOG2
+
+#define celt_maxabs16(x, len) MAX32(EXTEND32(maxval((DATA *)x, len)),-EXTEND32(minval((DATA *)x, len)))
+#define OVERRIDE_CELT_MAXABS16
+
+#endif /* FIXED_C5X_H */

+ 70 - 0
thirdparty/opus/celt/fixed_c6x.h

@@ -0,0 +1,70 @@
+/* Copyright (C) 2008 CSIRO */
+/**
+   @file fixed_c6x.h
+   @brief Fixed-point operations for the TI C6x DSP family
+*/
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef FIXED_C6X_H
+#define FIXED_C6X_H
+
+#undef MULT16_16SU
+#define MULT16_16SU(a,b) _mpysu(a,b)
+
+#undef MULT_16_16
+#define MULT_16_16(a,b) _mpy(a,b)
+
+#define celt_ilog2(x) (30 - _norm(x))
+#define OVERRIDE_CELT_ILOG2
+
+#undef MULT16_32_Q15
+#define MULT16_32_Q15(a,b) (_mpylill(a, b) >> 15)
+
+#if 0
+#include "dsplib.h"
+
+#undef MAX16
+#define MAX16(a,b) _max(a,b)
+
+#undef MIN16
+#define MIN16(a,b) _min(a,b)
+
+#undef MAX32
+#define MAX32(a,b) _lmax(a,b)
+
+#undef MIN32
+#define MIN32(a,b) _lmin(a,b)
+
+#undef VSHR32
+#define VSHR32(a, shift) _lshl(a,-(shift))
+
+#undef MULT16_16_Q15
+#define MULT16_16_Q15(a,b) (_smpy(a,b))
+
+#define celt_maxabs16(x, len) MAX32(EXTEND32(maxval((DATA *)x, len)),-EXTEND32(minval((DATA *)x, len)))
+#define OVERRIDE_CELT_MAXABS16
+
+#endif /* FIXED_C6X_H */

+ 10 - 3
thirdparty/opus/celt/fixed_debug.h

@@ -59,6 +59,14 @@ extern opus_int64 celt_mips;
 #define SHR(a,b) SHR32(a,b)
 #define PSHR(a,b) PSHR32(a,b)
 
+/** Add two 32-bit values, ignore any overflows */
+#define ADD32_ovflw(a,b) (celt_mips+=2,(opus_val32)((opus_uint32)(a)+(opus_uint32)(b)))
+/** Subtract two 32-bit values, ignore any overflows */
+#define SUB32_ovflw(a,b) (celt_mips+=2,(opus_val32)((opus_uint32)(a)-(opus_uint32)(b)))
+/* Avoid MSVC warning C4146: unary minus operator applied to unsigned type */
+/** Negate 32-bit value, ignore any overflows */
+#define NEG32_ovflw(a) (celt_mips+=2,(opus_val32)(0-(opus_uint32)(a)))
+
 static OPUS_INLINE short NEG16(int x)
 {
    int res;
@@ -227,12 +235,11 @@ static OPUS_INLINE int SHL32_(opus_int64 a, int shift, char *file, int line)
 #define VSHR32(a, shift) (((shift)>0) ? SHR32(a, shift) : SHL32(a, -(shift)))
 
 #define ROUND16(x,a) (celt_mips--,EXTRACT16(PSHR32((x),(a))))
+#define SROUND16(x,a) (celt_mips--,EXTRACT16(SATURATE(PSHR32(x,a), 32767)));
+
 #define HALF16(x)  (SHR16(x,1))
 #define HALF32(x)  (SHR32(x,1))
 
-//#define SHR(a,shift) ((a) >> (shift))
-//#define SHL(a,shift) ((a) << (shift))
-
 #define ADD16(a, b) ADD16_(a, b, __FILE__, __LINE__)
 static OPUS_INLINE short ADD16_(int a, int b, char *file, int line)
 {

+ 11 - 0
thirdparty/opus/celt/fixed_generic.h

@@ -104,6 +104,9 @@
 
 /** Shift by a and round-to-neareast 32-bit value. Result is a 16-bit value */
 #define ROUND16(x,a) (EXTRACT16(PSHR32((x),(a))))
+/** Shift by a and round-to-neareast 32-bit value. Result is a saturated 16-bit value */
+#define SROUND16(x,a) EXTRACT16(SATURATE(PSHR32(x,a), 32767));
+
 /** Divide by two */
 #define HALF16(x)  (SHR16(x,1))
 #define HALF32(x)  (SHR32(x,1))
@@ -117,6 +120,14 @@
 /** Subtract two 32-bit values */
 #define SUB32(a,b) ((opus_val32)(a)-(opus_val32)(b))
 
+/** Add two 32-bit values, ignore any overflows */
+#define ADD32_ovflw(a,b) ((opus_val32)((opus_uint32)(a)+(opus_uint32)(b)))
+/** Subtract two 32-bit values, ignore any overflows */
+#define SUB32_ovflw(a,b) ((opus_val32)((opus_uint32)(a)-(opus_uint32)(b)))
+/* Avoid MSVC warning C4146: unary minus operator applied to unsigned type */
+/** Negate 32-bit value, ignore any overflows */
+#define NEG32_ovflw(a) ((opus_val32)(0-(opus_uint32)(a)))
+
 /** 16x16 multiplication where the result fits in 16 bits */
 #define MULT16_16_16(a,b)     ((((opus_val16)(a))*((opus_val16)(b))))
 

+ 10 - 4
thirdparty/opus/celt/float_cast.h

@@ -61,7 +61,13 @@
 **      the config.h file.
 */
 
-#if (HAVE_LRINTF)
+/* With GCC, when SSE is available, the fastest conversion is cvtss2si. */
+#if defined(__GNUC__) && defined(__SSE__)
+
+#include <xmmintrin.h>
+static OPUS_INLINE opus_int32 float2int(float x) {return _mm_cvt_ss2si(_mm_set_ss(x));}
+
+#elif defined(HAVE_LRINTF)
 
 /*      These defines enable functionality introduced with the 1999 ISO C
 **      standard. They must be defined before the inclusion of math.h to
@@ -90,10 +96,10 @@
 #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)
+        static __inline long int float2int(float value)
         {
                 return _mm_cvtss_si32(_mm_load_ss(&value));
         }
@@ -104,7 +110,7 @@
         **      Therefore implement OPUS_INLINE versions of these functions here.
         */
 
-        __inline long int
+        static __inline long int
         float2int (float flt)
         {       int intgr;
 

+ 28 - 28
thirdparty/opus/celt/kiss_fft.c

@@ -82,8 +82,8 @@ static void kf_bfly2(
          C_SUB( Fout2[0] ,  Fout[0] , t );
          C_ADDTO( Fout[0] ,  t );
 
-         t.r = S_MUL(Fout2[1].r+Fout2[1].i, tw);
-         t.i = S_MUL(Fout2[1].i-Fout2[1].r, tw);
+         t.r = S_MUL(ADD32_ovflw(Fout2[1].r, Fout2[1].i), tw);
+         t.i = S_MUL(SUB32_ovflw(Fout2[1].i, Fout2[1].r), tw);
          C_SUB( Fout2[1] ,  Fout[1] , t );
          C_ADDTO( Fout[1] ,  t );
 
@@ -92,8 +92,8 @@ static void kf_bfly2(
          C_SUB( Fout2[2] ,  Fout[2] , t );
          C_ADDTO( Fout[2] ,  t );
 
-         t.r = S_MUL(Fout2[3].i-Fout2[3].r, tw);
-         t.i = S_MUL(-Fout2[3].i-Fout2[3].r, tw);
+         t.r = S_MUL(SUB32_ovflw(Fout2[3].i, Fout2[3].r), tw);
+         t.i = S_MUL(NEG32_ovflw(ADD32_ovflw(Fout2[3].i, Fout2[3].r)), tw);
          C_SUB( Fout2[3] ,  Fout[3] , t );
          C_ADDTO( Fout[3] ,  t );
          Fout += 8;
@@ -126,10 +126,10 @@ static void kf_bfly4(
          C_ADDTO( *Fout , scratch1 );
          C_SUB( scratch1 , Fout[1] , Fout[3] );
 
-         Fout[1].r = scratch0.r + scratch1.i;
-         Fout[1].i = scratch0.i - scratch1.r;
-         Fout[3].r = scratch0.r - scratch1.i;
-         Fout[3].i = scratch0.i + scratch1.r;
+         Fout[1].r = ADD32_ovflw(scratch0.r, scratch1.i);
+         Fout[1].i = SUB32_ovflw(scratch0.i, scratch1.r);
+         Fout[3].r = SUB32_ovflw(scratch0.r, scratch1.i);
+         Fout[3].i = ADD32_ovflw(scratch0.i, scratch1.r);
          Fout+=4;
       }
    } else {
@@ -160,10 +160,10 @@ static void kf_bfly4(
             tw3 += fstride*3;
             C_ADDTO( *Fout , scratch[3] );
 
-            Fout[m].r = scratch[5].r + scratch[4].i;
-            Fout[m].i = scratch[5].i - scratch[4].r;
-            Fout[m3].r = scratch[5].r - scratch[4].i;
-            Fout[m3].i = scratch[5].i + scratch[4].r;
+            Fout[m].r = ADD32_ovflw(scratch[5].r, scratch[4].i);
+            Fout[m].i = SUB32_ovflw(scratch[5].i, scratch[4].r);
+            Fout[m3].r = SUB32_ovflw(scratch[5].r, scratch[4].i);
+            Fout[m3].i = ADD32_ovflw(scratch[5].i, scratch[4].r);
             ++Fout;
          }
       }
@@ -212,18 +212,18 @@ static void kf_bfly3(
          tw1 += fstride;
          tw2 += fstride*2;
 
-         Fout[m].r = Fout->r - HALF_OF(scratch[3].r);
-         Fout[m].i = Fout->i - HALF_OF(scratch[3].i);
+         Fout[m].r = SUB32_ovflw(Fout->r, HALF_OF(scratch[3].r));
+         Fout[m].i = SUB32_ovflw(Fout->i, HALF_OF(scratch[3].i));
 
          C_MULBYSCALAR( scratch[0] , epi3.i );
 
          C_ADDTO(*Fout,scratch[3]);
 
-         Fout[m2].r = Fout[m].r + scratch[0].i;
-         Fout[m2].i = Fout[m].i - scratch[0].r;
+         Fout[m2].r = ADD32_ovflw(Fout[m].r, scratch[0].i);
+         Fout[m2].i = SUB32_ovflw(Fout[m].i, scratch[0].r);
 
-         Fout[m].r -= scratch[0].i;
-         Fout[m].i += scratch[0].r;
+         Fout[m].r = SUB32_ovflw(Fout[m].r, scratch[0].i);
+         Fout[m].i = ADD32_ovflw(Fout[m].i, scratch[0].r);
 
          ++Fout;
       } while(--k);
@@ -282,22 +282,22 @@ static void kf_bfly5(
          C_ADD( scratch[8],scratch[2],scratch[3]);
          C_SUB( scratch[9],scratch[2],scratch[3]);
 
-         Fout0->r += scratch[7].r + scratch[8].r;
-         Fout0->i += scratch[7].i + scratch[8].i;
+         Fout0->r = ADD32_ovflw(Fout0->r, ADD32_ovflw(scratch[7].r, scratch[8].r));
+         Fout0->i = ADD32_ovflw(Fout0->i, ADD32_ovflw(scratch[7].i, scratch[8].i));
 
-         scratch[5].r = scratch[0].r + S_MUL(scratch[7].r,ya.r) + S_MUL(scratch[8].r,yb.r);
-         scratch[5].i = scratch[0].i + S_MUL(scratch[7].i,ya.r) + S_MUL(scratch[8].i,yb.r);
+         scratch[5].r = ADD32_ovflw(scratch[0].r, ADD32_ovflw(S_MUL(scratch[7].r,ya.r), S_MUL(scratch[8].r,yb.r)));
+         scratch[5].i = ADD32_ovflw(scratch[0].i, ADD32_ovflw(S_MUL(scratch[7].i,ya.r), S_MUL(scratch[8].i,yb.r)));
 
-         scratch[6].r =  S_MUL(scratch[10].i,ya.i) + S_MUL(scratch[9].i,yb.i);
-         scratch[6].i = -S_MUL(scratch[10].r,ya.i) - S_MUL(scratch[9].r,yb.i);
+         scratch[6].r =  ADD32_ovflw(S_MUL(scratch[10].i,ya.i), S_MUL(scratch[9].i,yb.i));
+         scratch[6].i = NEG32_ovflw(ADD32_ovflw(S_MUL(scratch[10].r,ya.i), S_MUL(scratch[9].r,yb.i)));
 
          C_SUB(*Fout1,scratch[5],scratch[6]);
          C_ADD(*Fout4,scratch[5],scratch[6]);
 
-         scratch[11].r = scratch[0].r + S_MUL(scratch[7].r,yb.r) + S_MUL(scratch[8].r,ya.r);
-         scratch[11].i = scratch[0].i + S_MUL(scratch[7].i,yb.r) + S_MUL(scratch[8].i,ya.r);
-         scratch[12].r = - S_MUL(scratch[10].i,yb.i) + S_MUL(scratch[9].i,ya.i);
-         scratch[12].i = S_MUL(scratch[10].r,yb.i) - S_MUL(scratch[9].r,ya.i);
+         scratch[11].r = ADD32_ovflw(scratch[0].r, ADD32_ovflw(S_MUL(scratch[7].r,yb.r), S_MUL(scratch[8].r,ya.r)));
+         scratch[11].i = ADD32_ovflw(scratch[0].i, ADD32_ovflw(S_MUL(scratch[7].i,yb.r), S_MUL(scratch[8].i,ya.r)));
+         scratch[12].r = SUB32_ovflw(S_MUL(scratch[9].i,ya.i), S_MUL(scratch[10].i,yb.i));
+         scratch[12].i = SUB32_ovflw(S_MUL(scratch[10].r,yb.i), S_MUL(scratch[9].r,ya.i));
 
          C_ADD(*Fout2,scratch[11],scratch[12]);
          C_SUB(*Fout3,scratch[11],scratch[12]);

+ 3 - 2
thirdparty/opus/celt/mathops.c

@@ -38,7 +38,8 @@
 #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;
@@ -182,7 +183,7 @@ opus_val32 celt_rcp(opus_val32 x)
    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;

+ 34 - 2
thirdparty/opus/celt/mathops.h

@@ -38,11 +38,44 @@
 #include "entcode.h"
 #include "os_support.h"
 
+#define PI 3.141592653f
+
 /* Multiplies two 16-bit fractional values. Bit-exactness of this macro is important */
 #define FRAC_MUL16(a,b) ((16384+((opus_int32)(opus_int16)(a)*(opus_int16)(b)))>>15)
 
 unsigned isqrt32(opus_uint32 _val);
 
+/* CELT doesn't need it for fixed-point, by analysis.c does. */
+#if !defined(FIXED_POINT) || defined(ANALYSIS_C)
+#define cA 0.43157974f
+#define cB 0.67848403f
+#define cC 0.08595542f
+#define cE ((float)PI/2)
+static OPUS_INLINE float fast_atan2f(float y, float x) {
+   float x2, y2;
+   x2 = x*x;
+   y2 = y*y;
+   /* For very small values, we don't care about the answer, so
+      we can just return 0. */
+   if (x2 + y2 < 1e-18f)
+   {
+      return 0;
+   }
+   if(x2<y2){
+      float den = (y2 + cB*x2) * (y2 + cC*x2);
+      return -x*y*(y2 + cA*x2) / den + (y<0 ? -cE : cE);
+   }else{
+      float den = (x2 + cB*y2) * (x2 + cC*y2);
+      return  x*y*(x2 + cA*y2) / den + (y<0 ? -cE : cE) - (x*y<0 ? -cE : cE);
+   }
+}
+#undef cA
+#undef cB
+#undef cC
+#undef cE
+#endif
+
+
 #ifndef OVERRIDE_CELT_MAXABS16
 static OPUS_INLINE opus_val32 celt_maxabs16(const opus_val16 *x, int len)
 {
@@ -80,7 +113,6 @@ static OPUS_INLINE opus_val32 celt_maxabs32(const opus_val32 *x, int len)
 
 #ifndef FIXED_POINT
 
-#define PI 3.141592653f
 #define celt_sqrt(x) ((float)sqrt(x))
 #define celt_rsqrt(x) (1.f/celt_sqrt(x))
 #define celt_rsqrt_norm(x) (celt_rsqrt(x))
@@ -147,7 +179,7 @@ static OPUS_INLINE float celt_exp2(float x)
 /** 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

+ 8 - 8
thirdparty/opus/celt/mdct.c

@@ -270,8 +270,8 @@ void clt_mdct_backward_c(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_sca
          int rev;
          kiss_fft_scalar yr, yi;
          rev = *bitrev++;
-         yr = S_MUL(*xp2, t[i]) + S_MUL(*xp1, t[N4+i]);
-         yi = S_MUL(*xp1, t[i]) - S_MUL(*xp2, t[N4+i]);
+         yr = ADD32_ovflw(S_MUL(*xp2, t[i]), S_MUL(*xp1, t[N4+i]));
+         yi = SUB32_ovflw(S_MUL(*xp1, t[i]), S_MUL(*xp2, t[N4+i]));
          /* We swap real and imag because we use an FFT instead of an IFFT. */
          yp[2*rev+1] = yr;
          yp[2*rev] = yi;
@@ -301,8 +301,8 @@ void clt_mdct_backward_c(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_sca
          t0 = t[i];
          t1 = t[N4+i];
          /* We'd scale up by 2 here, but instead it's done when mixing the windows */
-         yr = S_MUL(re,t0) + S_MUL(im,t1);
-         yi = S_MUL(re,t1) - S_MUL(im,t0);
+         yr = ADD32_ovflw(S_MUL(re,t0), S_MUL(im,t1));
+         yi = SUB32_ovflw(S_MUL(re,t1), S_MUL(im,t0));
          /* We swap real and imag because we're using an FFT instead of an IFFT. */
          re = yp1[1];
          im = yp1[0];
@@ -312,8 +312,8 @@ void clt_mdct_backward_c(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_sca
          t0 = t[(N4-i-1)];
          t1 = t[(N2-i-1)];
          /* We'd scale up by 2 here, but instead it's done when mixing the windows */
-         yr = S_MUL(re,t0) + S_MUL(im,t1);
-         yi = S_MUL(re,t1) - S_MUL(im,t0);
+         yr = ADD32_ovflw(S_MUL(re,t0), S_MUL(im,t1));
+         yi = SUB32_ovflw(S_MUL(re,t1), S_MUL(im,t0));
          yp1[0] = yr;
          yp0[1] = yi;
          yp0 += 2;
@@ -333,8 +333,8 @@ void clt_mdct_backward_c(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_sca
          kiss_fft_scalar x1, x2;
          x1 = *xp1;
          x2 = *yp1;
-         *yp1++ = MULT16_32_Q15(*wp2, x2) - MULT16_32_Q15(*wp1, x1);
-         *xp1-- = MULT16_32_Q15(*wp1, x2) + MULT16_32_Q15(*wp2, x1);
+         *yp1++ = SUB32_ovflw(MULT16_32_Q15(*wp2, x2), MULT16_32_Q15(*wp1, x1));
+         *xp1-- = ADD32_ovflw(MULT16_32_Q15(*wp1, x2), MULT16_32_Q15(*wp2, x1));
          wp1++;
          wp2--;
       }

+ 1 - 0
thirdparty/opus/celt/mips/celt_mipsr1.h

@@ -53,6 +53,7 @@
 #include "celt_lpc.h"
 #include "vq.h"
 
+#define OVERRIDE_COMB_FILTER_CONST
 #define OVERRIDE_comb_filter
 void comb_filter(opus_val32 *y, opus_val32 *x, int T0, int T1, int N,
       opus_val16 g0, opus_val16 g1, int tapset0, int tapset1,

+ 1 - 10
thirdparty/opus/celt/mips/vq_mipsr1.h

@@ -36,11 +36,6 @@
 #include "mathops.h"
 #include "arch.h"
 
-static unsigned extract_collapse_mask(int *iy, int N, int B);
-static void normalise_residual(int * OPUS_RESTRICT iy, celt_norm * OPUS_RESTRICT X, int N, opus_val32 Ryy, opus_val16 gain);
-static void exp_rotation(celt_norm *X, int len, int dir, int stride, int K, int spread);
-static void renormalise_vector_mips(celt_norm *X, int N, opus_val16 gain, int arch);
-
 #define OVERRIDE_vq_exp_rotation1
 static void exp_rotation1(celt_norm *X, int len, int stride, opus_val16 c, opus_val16 s)
 {
@@ -69,11 +64,7 @@ static void exp_rotation1(celt_norm *X, int len, int stride, opus_val16 c, opus_
 }
 
 #define OVERRIDE_renormalise_vector
-
-#define renormalise_vector(X, N, gain, arch) \
- (renormalise_vector_mips(X, N, gain, arch))
-
-void renormalise_vector_mips(celt_norm *X, int N, opus_val16 gain, int arch)
+void renormalise_vector(celt_norm *X, int N, opus_val16 gain, int arch)
 {
    int i;
 #ifdef FIXED_POINT

+ 1 - 1
thirdparty/opus/celt/modes.c

@@ -427,7 +427,7 @@ void opus_custom_mode_destroy(CELTMode *mode)
    }
 #endif /* CUSTOM_MODES_ONLY */
    opus_free((opus_int16*)mode->eBands);
-   opus_free((opus_int16*)mode->allocVectors);
+   opus_free((unsigned char*)mode->allocVectors);
 
    opus_free((opus_val16*)mode->window);
    opus_free((opus_int16*)mode->logN);

+ 13 - 33
thirdparty/opus/celt/pitch.c

@@ -102,11 +102,9 @@ static void find_best_pitch(opus_val32 *xcorr, opus_val16 *y, int len,
    }
 }
 
-static void celt_fir5(const opus_val16 *x,
+static void celt_fir5(opus_val16 *x,
          const opus_val16 *num,
-         opus_val16 *y,
-         int N,
-         opus_val16 *mem)
+         int N)
 {
    int i;
    opus_val16 num0, num1, num2, num3, num4;
@@ -116,11 +114,11 @@ static void celt_fir5(const opus_val16 *x,
    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);
@@ -134,13 +132,8 @@ static void celt_fir5(const opus_val16 *x,
       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;
 }
 
 
@@ -150,7 +143,7 @@ void pitch_downsample(celt_sig * OPUS_RESTRICT x[], opus_val16 * OPUS_RESTRICT x
    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
@@ -211,7 +204,7 @@ void pitch_downsample(celt_sig * OPUS_RESTRICT x[], opus_val16 * OPUS_RESTRICT x
    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. */
@@ -220,13 +213,8 @@ opus_val32
 #else
 void
 #endif
-#if defined(OVERRIDE_PITCH_XCORR)
 celt_pitch_xcorr_c(const opus_val16 *_x, const opus_val16 *_y,
-      opus_val32 *xcorr, int len, int max_pitch)
-#else
-celt_pitch_xcorr(const opus_val16 *_x, const opus_val16 *_y,
       opus_val32 *xcorr, int len, int max_pitch, int arch)
-#endif
 {
 
 #if 0 /* This is a simple version of the pitch correlation that should work
@@ -261,15 +249,11 @@ celt_pitch_xcorr(const opus_val16 *_x, const opus_val16 *_y,
    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};
-#if defined(OVERRIDE_PITCH_XCORR)
-      xcorr_kernel_c(_x, _y+i, sum, len);
-#else
       xcorr_kernel(_x, _y+i, sum, len, arch);
-#endif
       xcorr[i]=sum[0];
       xcorr[i+1]=sum[1];
       xcorr[i+2]=sum[2];
@@ -285,11 +269,7 @@ celt_pitch_xcorr(const opus_val16 *_x, const opus_val16 *_y,
    for (;i<max_pitch;i++)
    {
       opus_val32 sum;
-#if defined(OVERRIDE_PITCH_XCORR)
-      sum = celt_inner_prod_c(_x, _y+i, len);
-#else
       sum = celt_inner_prod(_x, _y+i, len, arch);
-#endif
       xcorr[i] = sum;
 #ifdef FIXED_POINT
       maxcorr = MAX32(maxcorr, sum);
@@ -378,7 +358,7 @@ void pitch_search(const opus_val16 * OPUS_RESTRICT x_lp, opus_val16 * OPUS_RESTR
       for (j=0;j<len>>1;j++)
          sum += SHR32(MULT16_16(x_lp[j],y[i+j]), shift);
 #else
-      sum = celt_inner_prod_c(x_lp, y+i, len>>1);
+      sum = celt_inner_prod(x_lp, y+i, len>>1, arch);
 #endif
       xcorr[i] = MAX32(-1, sum);
 #ifdef FIXED_POINT
@@ -424,7 +404,7 @@ static opus_val16 compute_pitch_gain(opus_val32 xy, opus_val32 xx, opus_val32 yy
    sx = celt_ilog2(xx)-14;
    sy = celt_ilog2(yy)-14;
    shift = sx + sy;
-   x2y2 = MULT16_16_Q14(VSHR32(xx, sx), VSHR32(yy, sy));
+   x2y2 = SHR32(MULT16_16(VSHR32(xx, sx), VSHR32(yy, sy)), 14);
    if (shift & 1) {
       if (x2y2 < 32768)
       {

+ 3 - 11
thirdparty/opus/celt/pitch.h

@@ -46,8 +46,7 @@
 #include "mips/pitch_mipsr1.h"
 #endif
 
-#if ((defined(OPUS_ARM_ASM) && defined(FIXED_POINT)) \
-  || defined(OPUS_ARM_MAY_HAVE_NEON_INTR))
+#if (defined(OPUS_ARM_ASM) || defined(OPUS_ARM_MAY_HAVE_NEON_INTR))
 # include "arm/pitch_arm.h"
 #endif
 
@@ -184,17 +183,10 @@ opus_val32
 void
 #endif
 celt_pitch_xcorr_c(const opus_val16 *_x, const opus_val16 *_y,
-      opus_val32 *xcorr, int len, int max_pitch);
-
-#if !defined(OVERRIDE_PITCH_XCORR)
-#ifdef FIXED_POINT
-opus_val32
-#else
-void
-#endif
-celt_pitch_xcorr(const opus_val16 *_x, const opus_val16 *_y,
       opus_val32 *xcorr, int len, int max_pitch, int arch);
 
+#ifndef OVERRIDE_PITCH_XCORR
+# define celt_pitch_xcorr celt_pitch_xcorr_c
 #endif
 
 #endif

+ 9 - 2
thirdparty/opus/celt/quant_bands.c

@@ -418,6 +418,7 @@ void quant_energy_finalise(const CELTMode *m, int start, int end, opus_val16 *ol
             offset = (q2-.5f)*(1<<(14-fine_quant[i]-1))*(1.f/16384);
 #endif
             oldEBands[i+c*m->nbEBands] += offset;
+            error[i+c*m->nbEBands] -= offset;
             bits_left--;
          } while (++c < C);
       }
@@ -456,7 +457,7 @@ void unquant_coarse_energy(const CELTMode *m, int start, int end, opus_val16 *ol
          /* It would be better to express this invariant as a
             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)
          {
@@ -547,9 +548,15 @@ void amp2Log2(const CELTMode *m, int effEnd, int end,
    c=0;
    do {
       for (i=0;i<effEnd;i++)
+      {
          bandLogE[i+c*m->nbEBands] =
-               celt_log2(SHL32(bandE[i+c*m->nbEBands],2))
+               celt_log2(bandE[i+c*m->nbEBands])
                - SHL16((opus_val16)eMeans[i],6);
+#ifdef FIXED_POINT
+         /* Compensate for bandE[] being Q12 but celt_log2() taking a Q14 input. */
+         bandLogE[i+c*m->nbEBands] += QCONST16(2.f, DB_SHIFT);
+#endif
+      }
       for (i=effEnd;i<end;i++)
          bandLogE[c*m->nbEBands+i] = -QCONST16(14.f,DB_SHIFT);
    } while (++c < C);

+ 9 - 4
thirdparty/opus/celt/rate.c

@@ -348,12 +348,17 @@ static OPUS_INLINE int interp_bits2pulses(const CELTMode *m, int start, int end,
             /*This if() block is the only part of the allocation function that
                is not a mandatory part of the bitstream: any bands we choose to
                skip here must be explicitly signaled.*/
-            /*Choose a threshold with some hysteresis to keep bands from
-               fluctuating in and out.*/
+            int depth_threshold;
+            /*We choose a threshold with some hysteresis to keep bands from
+               fluctuating in and out, but we try not to fold below a certain point. */
+            if (codedBands > 17)
+               depth_threshold = j<prev ? 7 : 9;
+            else
+               depth_threshold = 0;
 #ifdef FUZZING
             if ((rand()&0x1) == 0)
 #else
-            if (codedBands<=start+2 || (band_bits > ((j<prev?7:9)*band_width<<LM<<BITRES)>>4 && j<=signalBandwidth))
+            if (codedBands<=start+2 || (band_bits > (depth_threshold*band_width<<LM<<BITRES)>>4 && j<=signalBandwidth))
 #endif
             {
                ec_enc_bit_logp(ec, 1, 1);
@@ -524,7 +529,7 @@ static OPUS_INLINE int interp_bits2pulses(const CELTMode *m, int start, int end,
    return codedBands;
 }
 
-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;

+ 1 - 1
thirdparty/opus/celt/rate.h

@@ -95,7 +95,7 @@ static OPUS_INLINE int pulses2bits(const CELTMode *m, int band, int LM, int puls
  @param pulses Number of pulses per band (returned)
  @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_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);
 
 #endif

+ 1 - 1
thirdparty/opus/celt/static_modes_fixed_arm_ne10.h

@@ -1,7 +1,7 @@
 /* The contents of this file was automatically generated by
  * dump_mode_arm_ne10.c with arguments: 48000 960
  * It contains static definitions for some pre-defined modes. */
-#include <NE10_init.h>
+#include <NE10_types.h>
 
 #ifndef NE10_FFT_PARAMS48000_960
 #define NE10_FFT_PARAMS48000_960

+ 1 - 1
thirdparty/opus/celt/static_modes_float_arm_ne10.h

@@ -1,7 +1,7 @@
 /* The contents of this file was automatically generated by
  * dump_mode_arm_ne10.c with arguments: 48000 960
  * It contains static definitions for some pre-defined modes. */
-#include <NE10_init.h>
+#include <NE10_types.h>
 
 #ifndef NE10_FFT_PARAMS48000_960
 #define NE10_FFT_PARAMS48000_960

+ 0 - 161
thirdparty/opus/celt/tests/test_unit_cwrs32.c

@@ -1,161 +0,0 @@
-/* Copyright (c) 2008-2011 Xiph.Org Foundation, Mozilla Corporation,
-                           Gregory Maxwell
-   Written by Jean-Marc Valin, Gregory Maxwell, and Timothy B. Terriberry */
-/*
-   Redistribution and use in source and binary forms, with or without
-   modification, are permitted provided that the following conditions
-   are met:
-
-   - Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-
-   - Redistributions in binary form must reproduce the above copyright
-   notice, this list of conditions and the following disclaimer in the
-   documentation and/or other materials provided with the distribution.
-
-   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
-   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <stdio.h>
-#include <string.h>
-
-#ifndef CUSTOM_MODES
-#define CUSTOM_MODES
-#else
-#define TEST_CUSTOM_MODES
-#endif
-
-#define CELT_C
-#include "stack_alloc.h"
-#include "entenc.c"
-#include "entdec.c"
-#include "entcode.c"
-#include "cwrs.c"
-#include "mathops.c"
-#include "rate.h"
-
-#define NMAX (240)
-#define KMAX (128)
-
-#ifdef TEST_CUSTOM_MODES
-
-#define NDIMS (44)
-static const int pn[NDIMS]={
-   2,   3,   4,   5,   6,   7,   8,   9,  10,
-  11,  12,  13,  14,  15,  16,  18,  20,  22,
-  24,  26,  28,  30,  32,  36,  40,  44,  48,
-  52,  56,  60,  64,  72,  80,  88,  96, 104,
- 112, 120, 128, 144, 160, 176, 192, 208
-};
-static const int pkmax[NDIMS]={
- 128, 128, 128, 128,  88,  52,  36,  26,  22,
-  18,  16,  15,  13,  12,  12,  11,  10,   9,
-   9,   8,   8,   7,   7,   7,   7,   6,   6,
-   6,   6,   6,   5,   5,   5,   5,   5,   5,
-   4,   4,   4,   4,   4,   4,   4,   4
-};
-
-#else /* TEST_CUSTOM_MODES */
-
-#define NDIMS (22)
-static const int pn[NDIMS]={
-   2,   3,   4,   6,   8,   9,  11,  12,  16,
-  18,  22,  24,  32,  36,  44,  48,  64,  72,
-  88,  96, 144, 176
-};
-static const int pkmax[NDIMS]={
- 128, 128, 128,  88,  36,  26,  18,  16,  12,
-  11,   9,   9,   7,   7,   6,   6,   5,   5,
-   5,   5,   4,   4
-};
-
-#endif
-
-int main(void){
-  int t;
-  int n;
-  ALLOC_STACK;
-  for(t=0;t<NDIMS;t++){
-    int pseudo;
-    n=pn[t];
-    for(pseudo=1;pseudo<41;pseudo++)
-    {
-      int k;
-#if defined(SMALL_FOOTPRINT)
-      opus_uint32 uu[KMAX+2U];
-#endif
-      opus_uint32 inc;
-      opus_uint32 nc;
-      opus_uint32 i;
-      k=get_pulses(pseudo);
-      if (k>pkmax[t])break;
-      printf("Testing CWRS with N=%i, K=%i...\n",n,k);
-#if defined(SMALL_FOOTPRINT)
-      nc=ncwrs_urow(n,k,uu);
-#else
-      nc=CELT_PVQ_V(n,k);
-#endif
-      inc=nc/20000;
-      if(inc<1)inc=1;
-      for(i=0;i<nc;i+=inc){
-#if defined(SMALL_FOOTPRINT)
-        opus_uint32 u[KMAX+2U];
-#endif
-        int         y[NMAX];
-        int         sy;
-        opus_uint32 v;
-        opus_uint32 ii;
-        int         j;
-#if defined(SMALL_FOOTPRINT)
-        memcpy(u,uu,(k+2U)*sizeof(*u));
-        cwrsi(n,k,i,y,u);
-#else
-        cwrsi(n,k,i,y);
-#endif
-        sy=0;
-        for(j=0;j<n;j++)sy+=abs(y[j]);
-        if(sy!=k){
-          fprintf(stderr,"N=%d Pulse count mismatch in cwrsi (%d!=%d).\n",
-           n,sy,k);
-          return 99;
-        }
-        /*printf("%6u of %u:",i,nc);
-        for(j=0;j<n;j++)printf(" %+3i",y[j]);
-        printf(" ->");*/
-#if defined(SMALL_FOOTPRINT)
-        ii=icwrs(n,k,&v,y,u);
-#else
-        ii=icwrs(n,y);
-        v=CELT_PVQ_V(n,k);
-#endif
-        if(ii!=i){
-          fprintf(stderr,"Combination-index mismatch (%lu!=%lu).\n",
-           (long)ii,(long)i);
-          return 1;
-        }
-        if(v!=nc){
-          fprintf(stderr,"Combination count mismatch (%lu!=%lu).\n",
-           (long)v,(long)nc);
-          return 2;
-        }
-        /*printf(" %6u\n",i);*/
-      }
-      /*printf("\n");*/
-    }
-  }
-  return 0;
-}

+ 0 - 189
thirdparty/opus/celt/tests/test_unit_dft.c

@@ -1,189 +0,0 @@
-/* Copyright (c) 2008 Xiph.Org Foundation
-   Written by Jean-Marc Valin */
-/*
-   Redistribution and use in source and binary forms, with or without
-   modification, are permitted provided that the following conditions
-   are met:
-
-   - Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-
-   - Redistributions in binary form must reproduce the above copyright
-   notice, this list of conditions and the following disclaimer in the
-   documentation and/or other materials provided with the distribution.
-
-   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
-   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#define SKIP_CONFIG_H
-
-#ifndef CUSTOM_MODES
-#define CUSTOM_MODES
-#endif
-
-#include <stdio.h>
-
-#define CELT_C
-#define TEST_UNIT_DFT_C
-#include "stack_alloc.h"
-#include "kiss_fft.h"
-#include "kiss_fft.c"
-#include "mathops.c"
-#include "entcode.c"
-
-#if defined(OPUS_X86_MAY_HAVE_SSE2) || defined(OPUS_X86_MAY_HAVE_SSE4_1)
-# include "x86/x86cpu.c"
-#elif defined(OPUS_ARM_ASM) || defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
-# include "arm/armcpu.c"
-# include "celt_lpc.c"
-# include "pitch.c"
-# if defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
-#  include "arm/celt_neon_intr.c"
-#  if defined(HAVE_ARM_NE10)
-#   include "mdct.c"
-#   include "arm/celt_ne10_fft.c"
-#   include "arm/celt_ne10_mdct.c"
-#  endif
-# endif
-# include "arm/arm_celt_map.c"
-#endif
-
-#ifndef M_PI
-#define M_PI 3.141592653
-#endif
-
-int ret = 0;
-
-void check(kiss_fft_cpx  * in,kiss_fft_cpx  * out,int nfft,int isinverse)
-{
-    int bin,k;
-    double errpow=0,sigpow=0, snr;
-
-    for (bin=0;bin<nfft;++bin) {
-        double ansr = 0;
-        double ansi = 0;
-        double difr;
-        double difi;
-
-        for (k=0;k<nfft;++k) {
-            double phase = -2*M_PI*bin*k/nfft;
-            double re = cos(phase);
-            double im = sin(phase);
-            if (isinverse)
-                im = -im;
-
-            if (!isinverse)
-            {
-               re /= nfft;
-               im /= nfft;
-            }
-
-            ansr += in[k].r * re - in[k].i * im;
-            ansi += in[k].r * im + in[k].i * re;
-        }
-        /*printf ("%d %d ", (int)ansr, (int)ansi);*/
-        difr = ansr - out[bin].r;
-        difi = ansi - out[bin].i;
-        errpow += difr*difr + difi*difi;
-        sigpow += ansr*ansr+ansi*ansi;
-    }
-    snr = 10*log10(sigpow/errpow);
-    printf("nfft=%d inverse=%d,snr = %f\n",nfft,isinverse,snr );
-    if (snr<60) {
-       printf( "** poor snr: %f ** \n", snr);
-       ret = 1;
-    }
-}
-
-void test1d(int nfft,int isinverse,int arch)
-{
-    size_t buflen = sizeof(kiss_fft_cpx)*nfft;
-
-    kiss_fft_cpx  * in = (kiss_fft_cpx*)malloc(buflen);
-    kiss_fft_cpx  * out= (kiss_fft_cpx*)malloc(buflen);
-    kiss_fft_state *cfg = opus_fft_alloc(nfft,0,0,arch);
-    int k;
-
-    for (k=0;k<nfft;++k) {
-        in[k].r = (rand() % 32767) - 16384;
-        in[k].i = (rand() % 32767) - 16384;
-    }
-
-    for (k=0;k<nfft;++k) {
-       in[k].r *= 32768;
-       in[k].i *= 32768;
-    }
-
-    if (isinverse)
-    {
-       for (k=0;k<nfft;++k) {
-          in[k].r /= nfft;
-          in[k].i /= nfft;
-       }
-    }
-
-    /*for (k=0;k<nfft;++k) printf("%d %d ", in[k].r, in[k].i);printf("\n");*/
-
-    if (isinverse)
-       opus_ifft(cfg,in,out, arch);
-    else
-       opus_fft(cfg,in,out, arch);
-
-    /*for (k=0;k<nfft;++k) printf("%d %d ", out[k].r, out[k].i);printf("\n");*/
-
-    check(in,out,nfft,isinverse);
-
-    free(in);
-    free(out);
-    opus_fft_free(cfg, arch);
-}
-
-int main(int argc,char ** argv)
-{
-    ALLOC_STACK;
-    int arch = opus_select_arch();
-
-    if (argc>1) {
-        int k;
-        for (k=1;k<argc;++k) {
-            test1d(atoi(argv[k]),0,arch);
-            test1d(atoi(argv[k]),1,arch);
-        }
-    }else{
-        test1d(32,0,arch);
-        test1d(32,1,arch);
-        test1d(128,0,arch);
-        test1d(128,1,arch);
-        test1d(256,0,arch);
-        test1d(256,1,arch);
-#ifndef RADIX_TWO_ONLY
-        test1d(36,0,arch);
-        test1d(36,1,arch);
-        test1d(50,0,arch);
-        test1d(50,1,arch);
-        test1d(60,0,arch);
-        test1d(60,1,arch);
-        test1d(120,0,arch);
-        test1d(120,1,arch);
-        test1d(240,0,arch);
-        test1d(240,1,arch);
-        test1d(480,0,arch);
-        test1d(480,1,arch);
-#endif
-    }
-    return ret;
-}

+ 0 - 382
thirdparty/opus/celt/tests/test_unit_entropy.c

@@ -1,382 +0,0 @@
-/* Copyright (c) 2007-2011 Xiph.Org Foundation, Mozilla Corporation,
-                           Gregory Maxwell
-   Written by Jean-Marc Valin, Gregory Maxwell, and Timothy B. Terriberry */
-/*
-   Redistribution and use in source and binary forms, with or without
-   modification, are permitted provided that the following conditions
-   are met:
-
-   - Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-
-   - Redistributions in binary form must reproduce the above copyright
-   notice, this list of conditions and the following disclaimer in the
-   documentation and/or other materials provided with the distribution.
-
-   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
-   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include <time.h>
-#include "entcode.h"
-#include "entenc.h"
-#include "entdec.h"
-#include <string.h>
-
-#include "entenc.c"
-#include "entdec.c"
-#include "entcode.c"
-
-#ifndef M_LOG2E
-# define M_LOG2E    1.4426950408889634074
-#endif
-#define DATA_SIZE 10000000
-#define DATA_SIZE2 10000
-
-int main(int _argc,char **_argv){
-  ec_enc         enc;
-  ec_dec         dec;
-  long           nbits;
-  long           nbits2;
-  double         entropy;
-  int            ft;
-  int            ftb;
-  int            sz;
-  int            i;
-  int            ret;
-  unsigned int   sym;
-  unsigned int   seed;
-  unsigned char *ptr;
-  const char    *env_seed;
-  ret=0;
-  entropy=0;
-  if (_argc > 2) {
-    fprintf(stderr, "Usage: %s [<seed>]\n", _argv[0]);
-    return 1;
-  }
-  env_seed = getenv("SEED");
-  if (_argc > 1)
-    seed = atoi(_argv[1]);
-  else if (env_seed)
-    seed = atoi(env_seed);
-  else
-    seed = time(NULL);
-  /*Testing encoding of raw bit values.*/
-  ptr = (unsigned char *)malloc(DATA_SIZE);
-  ec_enc_init(&enc,ptr, DATA_SIZE);
-  for(ft=2;ft<1024;ft++){
-    for(i=0;i<ft;i++){
-      entropy+=log(ft)*M_LOG2E;
-      ec_enc_uint(&enc,i,ft);
-    }
-  }
-  /*Testing encoding of raw bit values.*/
-  for(ftb=1;ftb<16;ftb++){
-    for(i=0;i<(1<<ftb);i++){
-      entropy+=ftb;
-      nbits=ec_tell(&enc);
-      ec_enc_bits(&enc,i,ftb);
-      nbits2=ec_tell(&enc);
-      if(nbits2-nbits!=ftb){
-        fprintf(stderr,"Used %li bits to encode %i bits directly.\n",
-         nbits2-nbits,ftb);
-        ret=-1;
-      }
-    }
-  }
-  nbits=ec_tell_frac(&enc);
-  ec_enc_done(&enc);
-  fprintf(stderr,
-   "Encoded %0.2lf bits of entropy to %0.2lf bits (%0.3lf%% wasted).\n",
-   entropy,ldexp(nbits,-3),100*(nbits-ldexp(entropy,3))/nbits);
-  fprintf(stderr,"Packed to %li bytes.\n",(long)ec_range_bytes(&enc));
-  ec_dec_init(&dec,ptr,DATA_SIZE);
-  for(ft=2;ft<1024;ft++){
-    for(i=0;i<ft;i++){
-      sym=ec_dec_uint(&dec,ft);
-      if(sym!=(unsigned)i){
-        fprintf(stderr,"Decoded %i instead of %i with ft of %i.\n",sym,i,ft);
-        ret=-1;
-      }
-    }
-  }
-  for(ftb=1;ftb<16;ftb++){
-    for(i=0;i<(1<<ftb);i++){
-      sym=ec_dec_bits(&dec,ftb);
-      if(sym!=(unsigned)i){
-        fprintf(stderr,"Decoded %i instead of %i with ftb of %i.\n",sym,i,ftb);
-        ret=-1;
-      }
-    }
-  }
-  nbits2=ec_tell_frac(&dec);
-  if(nbits!=nbits2){
-    fprintf(stderr,
-     "Reported number of bits used was %0.2lf, should be %0.2lf.\n",
-     ldexp(nbits2,-3),ldexp(nbits,-3));
-    ret=-1;
-  }
-  /*Testing an encoder bust prefers range coder data over raw bits.
-    This isn't a general guarantee, will only work for data that is buffered in
-     the encoder state and not yet stored in the user buffer, and should never
-     get used in practice.
-    It's mostly here for code coverage completeness.*/
-  /*Start with a 16-bit buffer.*/
-  ec_enc_init(&enc,ptr,2);
-  /*Write 7 raw bits.*/
-  ec_enc_bits(&enc,0x55,7);
-  /*Write 12.3 bits of range coder data.*/
-  ec_enc_uint(&enc,1,2);
-  ec_enc_uint(&enc,1,3);
-  ec_enc_uint(&enc,1,4);
-  ec_enc_uint(&enc,1,5);
-  ec_enc_uint(&enc,2,6);
-  ec_enc_uint(&enc,6,7);
-  ec_enc_done(&enc);
-  ec_dec_init(&dec,ptr,2);
-  if(!enc.error
-   /*The raw bits should have been overwritten by the range coder data.*/
-   ||ec_dec_bits(&dec,7)!=0x05
-   /*And all the range coder data should have been encoded correctly.*/
-   ||ec_dec_uint(&dec,2)!=1
-   ||ec_dec_uint(&dec,3)!=1
-   ||ec_dec_uint(&dec,4)!=1
-   ||ec_dec_uint(&dec,5)!=1
-   ||ec_dec_uint(&dec,6)!=2
-   ||ec_dec_uint(&dec,7)!=6){
-    fprintf(stderr,"Encoder bust overwrote range coder data with raw bits.\n");
-    ret=-1;
-  }
-  srand(seed);
-  fprintf(stderr,"Testing random streams... Random seed: %u (%.4X)\n", seed, rand() % 65536);
-  for(i=0;i<409600;i++){
-    unsigned *data;
-    unsigned *tell;
-    unsigned tell_bits;
-    int       j;
-    int zeros;
-    ft=rand()/((RAND_MAX>>(rand()%11U))+1U)+10;
-    sz=rand()/((RAND_MAX>>(rand()%9U))+1U);
-    data=(unsigned *)malloc(sz*sizeof(*data));
-    tell=(unsigned *)malloc((sz+1)*sizeof(*tell));
-    ec_enc_init(&enc,ptr,DATA_SIZE2);
-    zeros = rand()%13==0;
-    tell[0]=ec_tell_frac(&enc);
-    for(j=0;j<sz;j++){
-      if (zeros)
-        data[j]=0;
-      else
-        data[j]=rand()%ft;
-      ec_enc_uint(&enc,data[j],ft);
-      tell[j+1]=ec_tell_frac(&enc);
-    }
-    if (rand()%2==0)
-      while(ec_tell(&enc)%8 != 0)
-        ec_enc_uint(&enc, rand()%2, 2);
-    tell_bits = ec_tell(&enc);
-    ec_enc_done(&enc);
-    if(tell_bits!=(unsigned)ec_tell(&enc)){
-      fprintf(stderr,"ec_tell() changed after ec_enc_done(): %i instead of %i (Random seed: %u)\n",
-       ec_tell(&enc),tell_bits,seed);
-      ret=-1;
-    }
-    if ((tell_bits+7)/8 < ec_range_bytes(&enc))
-    {
-      fprintf (stderr, "ec_tell() lied, there's %i bytes instead of %d (Random seed: %u)\n",
-               ec_range_bytes(&enc), (tell_bits+7)/8,seed);
-      ret=-1;
-    }
-    ec_dec_init(&dec,ptr,DATA_SIZE2);
-    if(ec_tell_frac(&dec)!=tell[0]){
-      fprintf(stderr,
-       "Tell mismatch between encoder and decoder at symbol %i: %i instead of %i (Random seed: %u).\n",
-       0,ec_tell_frac(&dec),tell[0],seed);
-    }
-    for(j=0;j<sz;j++){
-      sym=ec_dec_uint(&dec,ft);
-      if(sym!=data[j]){
-        fprintf(stderr,
-         "Decoded %i instead of %i with ft of %i at position %i of %i (Random seed: %u).\n",
-         sym,data[j],ft,j,sz,seed);
-        ret=-1;
-      }
-      if(ec_tell_frac(&dec)!=tell[j+1]){
-        fprintf(stderr,
-         "Tell mismatch between encoder and decoder at symbol %i: %i instead of %i (Random seed: %u).\n",
-         j+1,ec_tell_frac(&dec),tell[j+1],seed);
-      }
-    }
-    free(tell);
-    free(data);
-  }
-  /*Test compatibility between multiple different encode/decode routines.*/
-  for(i=0;i<409600;i++){
-    unsigned *logp1;
-    unsigned *data;
-    unsigned *tell;
-    unsigned *enc_method;
-    int       j;
-    sz=rand()/((RAND_MAX>>(rand()%9U))+1U);
-    logp1=(unsigned *)malloc(sz*sizeof(*logp1));
-    data=(unsigned *)malloc(sz*sizeof(*data));
-    tell=(unsigned *)malloc((sz+1)*sizeof(*tell));
-    enc_method=(unsigned *)malloc(sz*sizeof(*enc_method));
-    ec_enc_init(&enc,ptr,DATA_SIZE2);
-    tell[0]=ec_tell_frac(&enc);
-    for(j=0;j<sz;j++){
-      data[j]=rand()/((RAND_MAX>>1)+1);
-      logp1[j]=(rand()%15)+1;
-      enc_method[j]=rand()/((RAND_MAX>>2)+1);
-      switch(enc_method[j]){
-        case 0:{
-          ec_encode(&enc,data[j]?(1<<logp1[j])-1:0,
-           (1<<logp1[j])-(data[j]?0:1),1<<logp1[j]);
-        }break;
-        case 1:{
-          ec_encode_bin(&enc,data[j]?(1<<logp1[j])-1:0,
-           (1<<logp1[j])-(data[j]?0:1),logp1[j]);
-        }break;
-        case 2:{
-          ec_enc_bit_logp(&enc,data[j],logp1[j]);
-        }break;
-        case 3:{
-          unsigned char icdf[2];
-          icdf[0]=1;
-          icdf[1]=0;
-          ec_enc_icdf(&enc,data[j],icdf,logp1[j]);
-        }break;
-      }
-      tell[j+1]=ec_tell_frac(&enc);
-    }
-    ec_enc_done(&enc);
-    if((ec_tell(&enc)+7U)/8U<ec_range_bytes(&enc)){
-      fprintf(stderr,"tell() lied, there's %i bytes instead of %d (Random seed: %u)\n",
-       ec_range_bytes(&enc),(ec_tell(&enc)+7)/8,seed);
-      ret=-1;
-    }
-    ec_dec_init(&dec,ptr,DATA_SIZE2);
-    if(ec_tell_frac(&dec)!=tell[0]){
-      fprintf(stderr,
-       "Tell mismatch between encoder and decoder at symbol %i: %i instead of %i (Random seed: %u).\n",
-       0,ec_tell_frac(&dec),tell[0],seed);
-    }
-    for(j=0;j<sz;j++){
-      int fs;
-      int dec_method;
-      dec_method=rand()/((RAND_MAX>>2)+1);
-      switch(dec_method){
-        case 0:{
-          fs=ec_decode(&dec,1<<logp1[j]);
-          sym=fs>=(1<<logp1[j])-1;
-          ec_dec_update(&dec,sym?(1<<logp1[j])-1:0,
-           (1<<logp1[j])-(sym?0:1),1<<logp1[j]);
-        }break;
-        case 1:{
-          fs=ec_decode_bin(&dec,logp1[j]);
-          sym=fs>=(1<<logp1[j])-1;
-          ec_dec_update(&dec,sym?(1<<logp1[j])-1:0,
-           (1<<logp1[j])-(sym?0:1),1<<logp1[j]);
-        }break;
-        case 2:{
-          sym=ec_dec_bit_logp(&dec,logp1[j]);
-        }break;
-        case 3:{
-          unsigned char icdf[2];
-          icdf[0]=1;
-          icdf[1]=0;
-          sym=ec_dec_icdf(&dec,icdf,logp1[j]);
-        }break;
-      }
-      if(sym!=data[j]){
-        fprintf(stderr,
-         "Decoded %i instead of %i with logp1 of %i at position %i of %i (Random seed: %u).\n",
-         sym,data[j],logp1[j],j,sz,seed);
-        fprintf(stderr,"Encoding method: %i, decoding method: %i\n",
-         enc_method[j],dec_method);
-        ret=-1;
-      }
-      if(ec_tell_frac(&dec)!=tell[j+1]){
-        fprintf(stderr,
-         "Tell mismatch between encoder and decoder at symbol %i: %i instead of %i (Random seed: %u).\n",
-         j+1,ec_tell_frac(&dec),tell[j+1],seed);
-      }
-    }
-    free(enc_method);
-    free(tell);
-    free(data);
-    free(logp1);
-  }
-  ec_enc_init(&enc,ptr,DATA_SIZE2);
-  ec_enc_bit_logp(&enc,0,1);
-  ec_enc_bit_logp(&enc,0,1);
-  ec_enc_bit_logp(&enc,0,1);
-  ec_enc_bit_logp(&enc,0,1);
-  ec_enc_bit_logp(&enc,0,2);
-  ec_enc_patch_initial_bits(&enc,3,2);
-  if(enc.error){
-    fprintf(stderr,"patch_initial_bits failed");
-    ret=-1;
-  }
-  ec_enc_patch_initial_bits(&enc,0,5);
-  if(!enc.error){
-    fprintf(stderr,"patch_initial_bits didn't fail when it should have");
-    ret=-1;
-  }
-  ec_enc_done(&enc);
-  if(ec_range_bytes(&enc)!=1||ptr[0]!=192){
-    fprintf(stderr,"Got %d when expecting 192 for patch_initial_bits",ptr[0]);
-    ret=-1;
-  }
-  ec_enc_init(&enc,ptr,DATA_SIZE2);
-  ec_enc_bit_logp(&enc,0,1);
-  ec_enc_bit_logp(&enc,0,1);
-  ec_enc_bit_logp(&enc,1,6);
-  ec_enc_bit_logp(&enc,0,2);
-  ec_enc_patch_initial_bits(&enc,0,2);
-  if(enc.error){
-    fprintf(stderr,"patch_initial_bits failed");
-    ret=-1;
-  }
-  ec_enc_done(&enc);
-  if(ec_range_bytes(&enc)!=2||ptr[0]!=63){
-    fprintf(stderr,"Got %d when expecting 63 for patch_initial_bits",ptr[0]);
-    ret=-1;
-  }
-  ec_enc_init(&enc,ptr,2);
-  ec_enc_bit_logp(&enc,0,2);
-  for(i=0;i<48;i++){
-    ec_enc_bits(&enc,0,1);
-  }
-  ec_enc_done(&enc);
-  if(!enc.error){
-    fprintf(stderr,"Raw bits overfill didn't fail when it should have");
-    ret=-1;
-  }
-  ec_enc_init(&enc,ptr,2);
-  for(i=0;i<17;i++){
-    ec_enc_bits(&enc,0,1);
-  }
-  ec_enc_done(&enc);
-  if(!enc.error){
-    fprintf(stderr,"17 raw bits encoded in two bytes");
-    ret=-1;
-  }
-  free(ptr);
-  return ret;
-}

+ 0 - 93
thirdparty/opus/celt/tests/test_unit_laplace.c

@@ -1,93 +0,0 @@
-/* Copyright (c) 2008-2011 Xiph.Org Foundation, Mozilla Corporation
-   Written by Jean-Marc Valin and Timothy B. Terriberry */
-/*
-   Redistribution and use in source and binary forms, with or without
-   modification, are permitted provided that the following conditions
-   are met:
-
-   - Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-
-   - Redistributions in binary form must reproduce the above copyright
-   notice, this list of conditions and the following disclaimer in the
-   documentation and/or other materials provided with the distribution.
-
-   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
-   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-#include "laplace.h"
-#define CELT_C
-#include "stack_alloc.h"
-
-#include "entenc.c"
-#include "entdec.c"
-#include "entcode.c"
-#include "laplace.c"
-
-#define DATA_SIZE 40000
-
-int ec_laplace_get_start_freq(int decay)
-{
-   opus_uint32 ft = 32768 - LAPLACE_MINP*(2*LAPLACE_NMIN+1);
-   int fs = (ft*(16384-decay))/(16384+decay);
-   return fs+LAPLACE_MINP;
-}
-
-int main(void)
-{
-   int i;
-   int ret = 0;
-   ec_enc enc;
-   ec_dec dec;
-   unsigned char *ptr;
-   int val[10000], decay[10000];
-   ALLOC_STACK;
-   ptr = (unsigned char *)malloc(DATA_SIZE);
-   ec_enc_init(&enc,ptr,DATA_SIZE);
-
-   val[0] = 3; decay[0] = 6000;
-   val[1] = 0; decay[1] = 5800;
-   val[2] = -1; decay[2] = 5600;
-   for (i=3;i<10000;i++)
-   {
-      val[i] = rand()%15-7;
-      decay[i] = rand()%11000+5000;
-   }
-   for (i=0;i<10000;i++)
-      ec_laplace_encode(&enc, &val[i],
-            ec_laplace_get_start_freq(decay[i]), decay[i]);
-
-   ec_enc_done(&enc);
-
-   ec_dec_init(&dec,ec_get_buffer(&enc),ec_range_bytes(&enc));
-
-   for (i=0;i<10000;i++)
-   {
-      int d = ec_laplace_decode(&dec,
-            ec_laplace_get_start_freq(decay[i]), decay[i]);
-      if (d != val[i])
-      {
-         fprintf (stderr, "Got %d instead of %d\n", d, val[i]);
-         ret = 1;
-      }
-   }
-
-   free(ptr);
-   return ret;
-}

+ 0 - 304
thirdparty/opus/celt/tests/test_unit_mathops.c

@@ -1,304 +0,0 @@
-/* Copyright (c) 2008-2011 Xiph.Org Foundation, Mozilla Corporation,
-                           Gregory Maxwell
-   Written by Jean-Marc Valin, Gregory Maxwell, and Timothy B. Terriberry */
-/*
-   Redistribution and use in source and binary forms, with or without
-   modification, are permitted provided that the following conditions
-   are met:
-
-   - Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-
-   - Redistributions in binary form must reproduce the above copyright
-   notice, this list of conditions and the following disclaimer in the
-   documentation and/or other materials provided with the distribution.
-
-   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
-   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#ifndef CUSTOM_MODES
-#define CUSTOM_MODES
-#endif
-
-#define CELT_C
-
-#include <stdio.h>
-#include <math.h>
-#include "mathops.c"
-#include "entenc.c"
-#include "entdec.c"
-#include "entcode.c"
-#include "bands.c"
-#include "quant_bands.c"
-#include "laplace.c"
-#include "vq.c"
-#include "cwrs.c"
-#include "pitch.c"
-#include "celt_lpc.c"
-#include "celt.c"
-
-#if defined(OPUS_X86_MAY_HAVE_SSE) || defined(OPUS_X86_MAY_HAVE_SSE2) || defined(OPUS_X86_MAY_HAVE_SSE4_1)
-# if defined(OPUS_X86_MAY_HAVE_SSE)
-#  include "x86/pitch_sse.c"
-# endif
-# if defined(OPUS_X86_MAY_HAVE_SSE2)
-#  include "x86/pitch_sse2.c"
-# endif
-# if defined(OPUS_X86_MAY_HAVE_SSE4_1)
-#  include "x86/pitch_sse4_1.c"
-#  include "x86/celt_lpc_sse.c"
-# endif
-# include "x86/x86_celt_map.c"
-#elif defined(OPUS_ARM_ASM) || defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
-# include "arm/armcpu.c"
-# if defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
-#  include "arm/celt_neon_intr.c"
-#  if defined(HAVE_ARM_NE10)
-#   include "kiss_fft.c"
-#   include "mdct.c"
-#   include "arm/celt_ne10_fft.c"
-#   include "arm/celt_ne10_mdct.c"
-#  endif
-# endif
-# include "arm/arm_celt_map.c"
-#endif
-
-#ifdef FIXED_POINT
-#define WORD "%d"
-#else
-#define WORD "%f"
-#endif
-
-int ret = 0;
-
-void testdiv(void)
-{
-   opus_int32 i;
-   for (i=1;i<=327670;i++)
-   {
-      double prod;
-      opus_val32 val;
-      val = celt_rcp(i);
-#ifdef FIXED_POINT
-      prod = (1./32768./65526.)*val*i;
-#else
-      prod = val*i;
-#endif
-      if (fabs(prod-1) > .00025)
-      {
-         fprintf (stderr, "div failed: 1/%d="WORD" (product = %f)\n", i, val, prod);
-         ret = 1;
-      }
-   }
-}
-
-void testsqrt(void)
-{
-   opus_int32 i;
-   for (i=1;i<=1000000000;i++)
-   {
-      double ratio;
-      opus_val16 val;
-      val = celt_sqrt(i);
-      ratio = val/sqrt(i);
-      if (fabs(ratio - 1) > .0005 && fabs(val-sqrt(i)) > 2)
-      {
-         fprintf (stderr, "sqrt failed: sqrt(%d)="WORD" (ratio = %f)\n", i, val, ratio);
-         ret = 1;
-      }
-      i+= i>>10;
-   }
-}
-
-void testbitexactcos(void)
-{
-   int i;
-   opus_int32 min_d,max_d,last,chk;
-   chk=max_d=0;
-   last=min_d=32767;
-   for(i=64;i<=16320;i++)
-   {
-      opus_int32 d;
-      opus_int32 q=bitexact_cos(i);
-      chk ^= q*i;
-      d = last - q;
-      if (d>max_d)max_d=d;
-      if (d<min_d)min_d=d;
-      last = q;
-   }
-   if ((chk!=89408644)||(max_d!=5)||(min_d!=0)||(bitexact_cos(64)!=32767)||
-       (bitexact_cos(16320)!=200)||(bitexact_cos(8192)!=23171))
-   {
-      fprintf (stderr, "bitexact_cos failed\n");
-      ret = 1;
-   }
-}
-
-void testbitexactlog2tan(void)
-{
-   int i,fail;
-   opus_int32 min_d,max_d,last,chk;
-   fail=chk=max_d=0;
-   last=min_d=15059;
-   for(i=64;i<8193;i++)
-   {
-      opus_int32 d;
-      opus_int32 mid=bitexact_cos(i);
-      opus_int32 side=bitexact_cos(16384-i);
-      opus_int32 q=bitexact_log2tan(mid,side);
-      chk ^= q*i;
-      d = last - q;
-      if (q!=-1*bitexact_log2tan(side,mid))
-        fail = 1;
-      if (d>max_d)max_d=d;
-      if (d<min_d)min_d=d;
-      last = q;
-   }
-   if ((chk!=15821257)||(max_d!=61)||(min_d!=-2)||fail||
-       (bitexact_log2tan(32767,200)!=15059)||(bitexact_log2tan(30274,12540)!=2611)||
-       (bitexact_log2tan(23171,23171)!=0))
-   {
-      fprintf (stderr, "bitexact_log2tan failed\n");
-      ret = 1;
-   }
-}
-
-#ifndef FIXED_POINT
-void testlog2(void)
-{
-   float x;
-   for (x=0.001;x<1677700.0;x+=(x/8.0))
-   {
-      float error = fabs((1.442695040888963387*log(x))-celt_log2(x));
-      if (error>0.0009)
-      {
-         fprintf (stderr, "celt_log2 failed: fabs((1.442695040888963387*log(x))-celt_log2(x))>0.001 (x = %f, error = %f)\n", x,error);
-         ret = 1;
-      }
-   }
-}
-
-void testexp2(void)
-{
-   float x;
-   for (x=-11.0;x<24.0;x+=0.0007)
-   {
-      float error = fabs(x-(1.442695040888963387*log(celt_exp2(x))));
-      if (error>0.0002)
-      {
-         fprintf (stderr, "celt_exp2 failed: fabs(x-(1.442695040888963387*log(celt_exp2(x))))>0.0005 (x = %f, error = %f)\n", x,error);
-         ret = 1;
-      }
-   }
-}
-
-void testexp2log2(void)
-{
-   float x;
-   for (x=-11.0;x<24.0;x+=0.0007)
-   {
-      float error = fabs(x-(celt_log2(celt_exp2(x))));
-      if (error>0.001)
-      {
-         fprintf (stderr, "celt_log2/celt_exp2 failed: fabs(x-(celt_log2(celt_exp2(x))))>0.001 (x = %f, error = %f)\n", x,error);
-         ret = 1;
-      }
-   }
-}
-#else
-void testlog2(void)
-{
-   opus_val32 x;
-   for (x=8;x<1073741824;x+=(x>>3))
-   {
-      float error = fabs((1.442695040888963387*log(x/16384.0))-celt_log2(x)/1024.0);
-      if (error>0.003)
-      {
-         fprintf (stderr, "celt_log2 failed: x = %ld, error = %f\n", (long)x,error);
-         ret = 1;
-      }
-   }
-}
-
-void testexp2(void)
-{
-   opus_val16 x;
-   for (x=-32768;x<15360;x++)
-   {
-      float error1 = fabs(x/1024.0-(1.442695040888963387*log(celt_exp2(x)/65536.0)));
-      float error2 = fabs(exp(0.6931471805599453094*x/1024.0)-celt_exp2(x)/65536.0);
-      if (error1>0.0002&&error2>0.00004)
-      {
-         fprintf (stderr, "celt_exp2 failed: x = "WORD", error1 = %f, error2 = %f\n", x,error1,error2);
-         ret = 1;
-      }
-   }
-}
-
-void testexp2log2(void)
-{
-   opus_val32 x;
-   for (x=8;x<65536;x+=(x>>3))
-   {
-      float error = fabs(x-0.25*celt_exp2(celt_log2(x)))/16384;
-      if (error>0.004)
-      {
-         fprintf (stderr, "celt_log2/celt_exp2 failed: fabs(x-(celt_exp2(celt_log2(x))))>0.001 (x = %ld, error = %f)\n", (long)x,error);
-         ret = 1;
-      }
-   }
-}
-
-void testilog2(void)
-{
-   opus_val32 x;
-   for (x=1;x<=268435455;x+=127)
-   {
-      opus_val32 lg;
-      opus_val32 y;
-
-      lg = celt_ilog2(x);
-      if (lg<0 || lg>=31)
-      {
-         printf("celt_ilog2 failed: 0<=celt_ilog2(x)<31 (x = %d, celt_ilog2(x) = %d)\n",x,lg);
-         ret = 1;
-      }
-      y = 1<<lg;
-
-      if (x<y || (x>>1)>=y)
-      {
-         printf("celt_ilog2 failed: 2**celt_ilog2(x)<=x<2**(celt_ilog2(x)+1) (x = %d, 2**celt_ilog2(x) = %d)\n",x,y);
-         ret = 1;
-      }
-   }
-}
-#endif
-
-int main(void)
-{
-   testbitexactcos();
-   testbitexactlog2tan();
-   testdiv();
-   testsqrt();
-   testlog2();
-   testexp2();
-   testexp2log2();
-#ifdef FIXED_POINT
-   testilog2();
-#endif
-   return ret;
-}

+ 0 - 230
thirdparty/opus/celt/tests/test_unit_mdct.c

@@ -1,230 +0,0 @@
-/* Copyright (c) 2008-2011 Xiph.Org Foundation
-   Written by Jean-Marc Valin */
-/*
-   Redistribution and use in source and binary forms, with or without
-   modification, are permitted provided that the following conditions
-   are met:
-
-   - Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-
-   - Redistributions in binary form must reproduce the above copyright
-   notice, this list of conditions and the following disclaimer in the
-   documentation and/or other materials provided with the distribution.
-
-   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
-   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#define SKIP_CONFIG_H
-
-#ifndef CUSTOM_MODES
-#define CUSTOM_MODES
-#endif
-
-#include <stdio.h>
-
-#define CELT_C
-#include "mdct.h"
-#include "stack_alloc.h"
-
-#include "kiss_fft.c"
-#include "mdct.c"
-#include "mathops.c"
-#include "entcode.c"
-
-#if defined(OPUS_X86_MAY_HAVE_SSE2) || defined(OPUS_X86_MAY_HAVE_SSE4_1)
-# include "x86/x86cpu.c"
-#elif defined(OPUS_ARM_ASM) || defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
-# include "arm/armcpu.c"
-# include "pitch.c"
-# include "celt_lpc.c"
-# if defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
-#  include "arm/celt_neon_intr.c"
-#  if defined(HAVE_ARM_NE10)
-#   include "arm/celt_ne10_fft.c"
-#   include "arm/celt_ne10_mdct.c"
-#  endif
-# endif
-# include "arm/arm_celt_map.c"
-#endif
-
-#ifndef M_PI
-#define M_PI 3.141592653
-#endif
-
-int ret = 0;
-void check(kiss_fft_scalar  * in,kiss_fft_scalar  * out,int nfft,int isinverse)
-{
-    int bin,k;
-    double errpow=0,sigpow=0;
-    double snr;
-    for (bin=0;bin<nfft/2;++bin) {
-        double ansr = 0;
-        double difr;
-
-        for (k=0;k<nfft;++k) {
-           double phase = 2*M_PI*(k+.5+.25*nfft)*(bin+.5)/nfft;
-           double re = cos(phase);
-
-           re /= nfft/4;
-
-           ansr += in[k] * re;
-        }
-        /*printf ("%f %f\n", ansr, out[bin]);*/
-        difr = ansr - out[bin];
-        errpow += difr*difr;
-        sigpow += ansr*ansr;
-    }
-    snr = 10*log10(sigpow/errpow);
-    printf("nfft=%d inverse=%d,snr = %f\n",nfft,isinverse,snr );
-    if (snr<60) {
-       printf( "** poor snr: %f **\n", snr);
-       ret = 1;
-    }
-}
-
-void check_inv(kiss_fft_scalar  * in,kiss_fft_scalar  * out,int nfft,int isinverse)
-{
-   int bin,k;
-   double errpow=0,sigpow=0;
-   double snr;
-   for (bin=0;bin<nfft;++bin) {
-      double ansr = 0;
-      double difr;
-
-      for (k=0;k<nfft/2;++k) {
-         double phase = 2*M_PI*(bin+.5+.25*nfft)*(k+.5)/nfft;
-         double re = cos(phase);
-
-         /*re *= 2;*/
-
-         ansr += in[k] * re;
-      }
-      /*printf ("%f %f\n", ansr, out[bin]);*/
-      difr = ansr - out[bin];
-      errpow += difr*difr;
-      sigpow += ansr*ansr;
-   }
-   snr = 10*log10(sigpow/errpow);
-   printf("nfft=%d inverse=%d,snr = %f\n",nfft,isinverse,snr );
-   if (snr<60) {
-      printf( "** poor snr: %f **\n", snr);
-      ret = 1;
-   }
-}
-
-
-void test1d(int nfft,int isinverse,int arch)
-{
-    mdct_lookup cfg;
-    size_t buflen = sizeof(kiss_fft_scalar)*nfft;
-
-    kiss_fft_scalar  * in = (kiss_fft_scalar*)malloc(buflen);
-    kiss_fft_scalar  * in_copy = (kiss_fft_scalar*)malloc(buflen);
-    kiss_fft_scalar  * out= (kiss_fft_scalar*)malloc(buflen);
-    opus_val16  * window= (opus_val16*)malloc(sizeof(opus_val16)*nfft/2);
-    int k;
-
-    clt_mdct_init(&cfg, nfft, 0, arch);
-    for (k=0;k<nfft;++k) {
-        in[k] = (rand() % 32768) - 16384;
-    }
-
-    for (k=0;k<nfft/2;++k) {
-       window[k] = Q15ONE;
-    }
-    for (k=0;k<nfft;++k) {
-       in[k] *= 32768;
-    }
-
-    if (isinverse)
-    {
-       for (k=0;k<nfft;++k) {
-          in[k] /= nfft;
-       }
-    }
-
-    for (k=0;k<nfft;++k)
-       in_copy[k] = in[k];
-    /*for (k=0;k<nfft;++k) printf("%d %d ", in[k].r, in[k].i);printf("\n");*/
-
-    if (isinverse)
-    {
-       for (k=0;k<nfft;++k)
-          out[k] = 0;
-       clt_mdct_backward(&cfg,in,out, window, nfft/2, 0, 1, arch);
-       /* apply TDAC because clt_mdct_backward() no longer does that */
-       for (k=0;k<nfft/4;++k)
-          out[nfft-k-1] = out[nfft/2+k];
-       check_inv(in,out,nfft,isinverse);
-    } else {
-       clt_mdct_forward(&cfg,in,out,window, nfft/2, 0, 1, arch);
-       check(in_copy,out,nfft,isinverse);
-    }
-    /*for (k=0;k<nfft;++k) printf("%d %d ", out[k].r, out[k].i);printf("\n");*/
-
-
-    free(in);
-    free(in_copy);
-    free(out);
-    free(window);
-    clt_mdct_clear(&cfg, arch);
-}
-
-int main(int argc,char ** argv)
-{
-    ALLOC_STACK;
-    int arch = opus_select_arch();
-
-    if (argc>1) {
-        int k;
-        for (k=1;k<argc;++k) {
-            test1d(atoi(argv[k]),0,arch);
-            test1d(atoi(argv[k]),1,arch);
-        }
-    }else{
-        test1d(32,0,arch);
-        test1d(32,1,arch);
-        test1d(256,0,arch);
-        test1d(256,1,arch);
-        test1d(512,0,arch);
-        test1d(512,1,arch);
-        test1d(1024,0,arch);
-        test1d(1024,1,arch);
-        test1d(2048,0,arch);
-        test1d(2048,1,arch);
-#ifndef RADIX_TWO_ONLY
-        test1d(36,0,arch);
-        test1d(36,1,arch);
-        test1d(40,0,arch);
-        test1d(40,1,arch);
-        test1d(60,0,arch);
-        test1d(60,1,arch);
-        test1d(120,0,arch);
-        test1d(120,1,arch);
-        test1d(240,0,arch);
-        test1d(240,1,arch);
-        test1d(480,0,arch);
-        test1d(480,1,arch);
-        test1d(960,0,arch);
-        test1d(960,1,arch);
-        test1d(1920,0,arch);
-        test1d(1920,1,arch);
-#endif
-    }
-    return ret;
-}

+ 0 - 120
thirdparty/opus/celt/tests/test_unit_rotation.c

@@ -1,120 +0,0 @@
-/* Copyright (c) 2008-2011 Xiph.Org Foundation
-   Written by Jean-Marc Valin */
-/*
-   Redistribution and use in source and binary forms, with or without
-   modification, are permitted provided that the following conditions
-   are met:
-
-   - Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-
-   - Redistributions in binary form must reproduce the above copyright
-   notice, this list of conditions and the following disclaimer in the
-   documentation and/or other materials provided with the distribution.
-
-   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
-   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#ifndef CUSTOM_MODES
-#define CUSTOM_MODES
-#endif
-
-#define CELT_C
-
-#include <stdio.h>
-#include <stdlib.h>
-#include "vq.c"
-#include "cwrs.c"
-#include "entcode.c"
-#include "entenc.c"
-#include "entdec.c"
-#include "mathops.c"
-#include "bands.h"
-#include "pitch.c"
-#include "celt_lpc.c"
-#include "celt.c"
-#include <math.h>
-
-#if defined(OPUS_X86_MAY_HAVE_SSE) || defined(OPUS_X86_MAY_HAVE_SSE2) || defined(OPUS_X86_MAY_HAVE_SSE4_1)
-# if defined(OPUS_X86_MAY_HAVE_SSE)
-#  include "x86/pitch_sse.c"
-# endif
-# if defined(OPUS_X86_MAY_HAVE_SSE2)
-#  include "x86/pitch_sse2.c"
-# endif
-# if defined(OPUS_X86_MAY_HAVE_SSE4_1)
-#  include "x86/pitch_sse4_1.c"
-#  include "x86/celt_lpc_sse.c"
-# endif
-# include "x86/x86_celt_map.c"
-#elif defined(OPUS_ARM_ASM) || defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
-# include "arm/armcpu.c"
-# if defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
-#  include "arm/celt_neon_intr.c"
-#  if defined(HAVE_ARM_NE10)
-#   include "kiss_fft.c"
-#   include "mdct.c"
-#   include "arm/celt_ne10_fft.c"
-#   include "arm/celt_ne10_mdct.c"
-#  endif
-# endif
-# include "arm/arm_celt_map.c"
-#endif
-
-#define MAX_SIZE 100
-
-int ret=0;
-void test_rotation(int N, int K)
-{
-   int i;
-   double err = 0, ener = 0, snr, snr0;
-   opus_val16 x0[MAX_SIZE];
-   opus_val16 x1[MAX_SIZE];
-   for (i=0;i<N;i++)
-      x1[i] = x0[i] = rand()%32767-16384;
-   exp_rotation(x1, N, 1, 1, K, SPREAD_NORMAL);
-   for (i=0;i<N;i++)
-   {
-      err += (x0[i]-(double)x1[i])*(x0[i]-(double)x1[i]);
-      ener += x0[i]*(double)x0[i];
-   }
-   snr0 = 20*log10(ener/err);
-   err = ener = 0;
-   exp_rotation(x1, N, -1, 1, K, SPREAD_NORMAL);
-   for (i=0;i<N;i++)
-   {
-      err += (x0[i]-(double)x1[i])*(x0[i]-(double)x1[i]);
-      ener += x0[i]*(double)x0[i];
-   }
-   snr = 20*log10(ener/err);
-   printf ("SNR for size %d (%d pulses) is %f (was %f without inverse)\n", N, K, snr, snr0);
-   if (snr < 60 || snr0 > 20)
-   {
-      fprintf(stderr, "FAIL!\n");
-      ret = 1;
-   }
-}
-
-int main(void)
-{
-   ALLOC_STACK;
-   test_rotation(15, 3);
-   test_rotation(23, 5);
-   test_rotation(50, 3);
-   test_rotation(80, 1);
-   return ret;
-}

+ 76 - 42
thirdparty/opus/celt/vq.c

@@ -39,6 +39,10 @@
 #include "rate.h"
 #include "pitch.h"
 
+#if defined(MIPSr1_ASM)
+#include "mips/vq_mipsr1.h"
+#endif
+
 #ifndef OVERRIDE_vq_exp_rotation1
 static void exp_rotation1(celt_norm *X, int len, int stride, opus_val16 c, opus_val16 s)
 {
@@ -67,7 +71,7 @@ static void exp_rotation1(celt_norm *X, int len, int stride, opus_val16 c, opus_
 }
 #endif /* OVERRIDE_vq_exp_rotation1 */
 
-static void exp_rotation(celt_norm *X, int len, int dir, int stride, int K, int spread)
+void exp_rotation(celt_norm *X, int len, int dir, int stride, int K, int spread)
 {
    static const int SPREAD_FACTOR[3]={15,10,5};
    int i;
@@ -158,42 +162,27 @@ static unsigned extract_collapse_mask(int *iy, int N, int B)
    return collapse_mask;
 }
 
-unsigned alg_quant(celt_norm *X, int N, int K, int spread, int B, ec_enc *enc
-#ifdef RESYNTH
-   , opus_val16 gain
-#endif
-   )
+opus_val16 op_pvq_search_c(celt_norm *X, int *iy, int K, int N, int arch)
 {
    VARDECL(celt_norm, y);
-   VARDECL(int, iy);
-   VARDECL(opus_val16, signx);
+   VARDECL(int, signx);
    int i, j;
-   opus_val16 s;
    int pulsesLeft;
    opus_val32 sum;
    opus_val32 xy;
    opus_val16 yy;
-   unsigned collapse_mask;
    SAVE_STACK;
 
-   celt_assert2(K>0, "alg_quant() needs at least one pulse");
-   celt_assert2(N>1, "alg_quant() needs at least two dimensions");
-
+   (void)arch;
    ALLOC(y, N, celt_norm);
-   ALLOC(iy, N, int);
-   ALLOC(signx, N, opus_val16);
-
-   exp_rotation(X, N, 1, B, K, spread);
+   ALLOC(signx, N, int);
 
    /* Get rid of the sign */
    sum = 0;
    j=0; do {
-      if (X[j]>0)
-         signx[j]=1;
-      else {
-         signx[j]=-1;
-         X[j]=-X[j];
-      }
+      signx[j] = X[j]<0;
+      /* OPT: Make sure the compiler doesn't use a branch on ABS16(). */
+      X[j] = ABS16(X[j]);
       iy[j] = 0;
       y[j] = 0;
    } while (++j<N);
@@ -225,7 +214,12 @@ unsigned alg_quant(celt_norm *X, int N, int K, int spread, int B, ec_enc *enc
          while (++j<N);
          sum = QCONST16(1.f,14);
       }
-      rcp = EXTRACT16(MULT16_32_Q16(K-1, celt_rcp(sum)));
+#ifdef FIXED_POINT
+      rcp = EXTRACT16(MULT16_32_Q16(K, celt_rcp(sum)));
+#else
+      /* Using K+e with e < 1 guarantees we cannot get more than K pulses. */
+      rcp = EXTRACT16(MULT16_32_Q16(K+0.8f, celt_rcp(sum)));
+#endif
       j=0; do {
 #ifdef FIXED_POINT
          /* It's really important to round *towards zero* here */
@@ -240,12 +234,12 @@ unsigned alg_quant(celt_norm *X, int N, int K, int spread, int B, ec_enc *enc
          pulsesLeft -= iy[j];
       }  while (++j<N);
    }
-   celt_assert2(pulsesLeft>=1, "Allocated too many pulses in the quick pass");
+   celt_sig_assert(pulsesLeft>=0);
 
    /* This should never happen, but just in case it does (e.g. on silence)
       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)
    {
@@ -256,12 +250,12 @@ unsigned alg_quant(celt_norm *X, int N, int K, int spread, int B, ec_enc *enc
       pulsesLeft=0;
    }
 
-   s = 1;
    for (i=0;i<pulsesLeft;i++)
    {
+      opus_val16 Rxy, Ryy;
       int best_id;
-      opus_val32 best_num = -VERY_LARGE16;
-      opus_val16 best_den = 0;
+      opus_val32 best_num;
+      opus_val16 best_den;
 #ifdef FIXED_POINT
       int rshift;
 #endif
@@ -272,9 +266,22 @@ unsigned alg_quant(celt_norm *X, int N, int K, int spread, int B, ec_enc *enc
       /* The squared magnitude term gets added anyway, so we might as well
          add it outside the loop */
       yy = ADD16(yy, 1);
-      j=0;
+
+      /* Calculations for position 0 are out of the loop, in part to reduce
+         mispredicted branches (since the if condition is usually false)
+         in the loop. */
+      /* Temporary sums of the new pulse(s) */
+      Rxy = EXTRACT16(SHR32(ADD32(xy, EXTEND32(X[0])),rshift));
+      /* We're multiplying y[j] by two so we don't have to do it here */
+      Ryy = ADD16(yy, y[0]);
+
+      /* Approximate score: we maximise Rxy/sqrt(Ryy) (we're guaranteed that
+         Rxy is positive because the sign is pre-computed) */
+      Rxy = MULT16_16_Q15(Rxy,Rxy);
+      best_den = Ryy;
+      best_num = Rxy;
+      j=1;
       do {
-         opus_val16 Rxy, Ryy;
          /* Temporary sums of the new pulse(s) */
          Rxy = EXTRACT16(SHR32(ADD32(xy, EXTEND32(X[j])),rshift));
          /* We're multiplying y[j] by two so we don't have to do it here */
@@ -285,8 +292,11 @@ unsigned alg_quant(celt_norm *X, int N, int K, int spread, int B, ec_enc *enc
          Rxy = MULT16_16_Q15(Rxy,Rxy);
          /* The idea is to check for num/den >= best_num/best_den, but that way
             we can do it without any division */
-         /* OPT: Make sure to use conditional moves here */
-         if (MULT16_16(best_den, Rxy) > MULT16_16(Ryy, best_num))
+         /* OPT: It's not clear whether a cmov is faster than a branch here
+            since the condition is more often false than true and using
+            a cmov introduces data dependencies across iterations. The optimal
+            choice may be architecture-dependent. */
+         if (opus_unlikely(MULT16_16(best_den, Rxy) > MULT16_16(Ryy, best_num)))
          {
             best_den = Ryy;
             best_num = Rxy;
@@ -301,23 +311,47 @@ unsigned alg_quant(celt_norm *X, int N, int K, int spread, int B, ec_enc *enc
 
       /* Only now that we've made the final choice, update y/iy */
       /* Multiplying y[j] by 2 so we don't have to do it everywhere else */
-      y[best_id] += 2*s;
+      y[best_id] += 2;
       iy[best_id]++;
    }
 
    /* Put the original sign back */
    j=0;
    do {
-      X[j] = MULT16_16(signx[j],X[j]);
-      if (signx[j] < 0)
-         iy[j] = -iy[j];
+      /*iy[j] = signx[j] ? -iy[j] : iy[j];*/
+      /* OPT: The is more likely to be compiled without a branch than the code above
+         but has the same performance otherwise. */
+      iy[j] = (iy[j]^-signx[j]) + signx[j];
    } while (++j<N);
+   RESTORE_STACK;
+   return yy;
+}
+
+unsigned alg_quant(celt_norm *X, int N, int K, int spread, int B, ec_enc *enc,
+      opus_val16 gain, int resynth, int arch)
+{
+   VARDECL(int, iy);
+   opus_val16 yy;
+   unsigned collapse_mask;
+   SAVE_STACK;
+
+   celt_assert2(K>0, "alg_quant() needs at least one pulse");
+   celt_assert2(N>1, "alg_quant() needs at least two dimensions");
+
+   /* Covers vectorization by up to 4. */
+   ALLOC(iy, N+3, int);
+
+   exp_rotation(X, N, 1, B, K, spread);
+
+   yy = op_pvq_search(X, iy, K, N, arch);
+
    encode_pulses(iy, N, K, enc);
 
-#ifdef RESYNTH
-   normalise_residual(iy, X, N, yy, gain);
-   exp_rotation(X, N, -1, B, K, spread);
-#endif
+   if (resynth)
+   {
+      normalise_residual(iy, X, N, yy, gain);
+      exp_rotation(X, N, -1, B, K, spread);
+   }
 
    collapse_mask = extract_collapse_mask(iy, N, B);
    RESTORE_STACK;
@@ -401,7 +435,7 @@ int stereo_itheta(const celt_norm *X, const celt_norm *Y, int stereo, int N, int
    /* 0.63662 = 2/pi */
    itheta = MULT16_16_Q15(QCONST16(0.63662f,15),celt_atan2p(side, mid));
 #else
-   itheta = (int)floor(.5f+16384*0.63662f*atan2(side,mid));
+   itheta = (int)floor(.5f+16384*0.63662f*fast_atan2f(side,mid));
 #endif
 
    return itheta;

+ 12 - 8
thirdparty/opus/celt/vq.h

@@ -37,10 +37,18 @@
 #include "entdec.h"
 #include "modes.h"
 
-#if defined(MIPSr1_ASM)
-#include "mips/vq_mipsr1.h"
+#if (defined(OPUS_X86_MAY_HAVE_SSE2) && !defined(FIXED_POINT))
+#include "x86/vq_sse.h"
 #endif
 
+void exp_rotation(celt_norm *X, int len, int dir, int stride, int K, int spread);
+
+opus_val16 op_pvq_search_c(celt_norm *X, int *iy, int K, int N, int arch);
+
+#if !defined(OVERRIDE_OP_PVQ_SEARCH)
+#define op_pvq_search(x, iy, K, N, arch) \
+    (op_pvq_search_c(x, iy, K, N, arch))
+#endif
 
 /** Algebraic pulse-vector quantiser. The signal x is replaced by the sum of
   * the pitch and a combination of pulses such that its norm is still equal
@@ -51,12 +59,8 @@
  * @param enc Entropy encoder state
  * @ret A mask indicating which blocks in the band received pulses
 */
-unsigned alg_quant(celt_norm *X, int N, int K, int spread, int B,
-      ec_enc *enc
-#ifdef RESYNTH
-      , opus_val16 gain
-#endif
-      );
+unsigned alg_quant(celt_norm *X, int N, int K, int spread, int B, ec_enc *enc,
+      opus_val16 gain, int resynth, int arch);
 
 /** Algebraic pulse decoder
  * @param X Decoded normalised spectrum (returned)

+ 4 - 6
thirdparty/opus/celt/x86/celt_lpc_sse.h

@@ -41,12 +41,11 @@ void celt_fir_sse4_1(
          opus_val16 *y,
          int N,
          int ord,
-         opus_val16 *mem,
          int arch);
 
 #if defined(OPUS_X86_PRESUME_SSE4_1)
-#define celt_fir(x, num, y, N, ord, mem, arch) \
-    ((void)arch, celt_fir_sse4_1(x, num, y, N, ord, mem, arch))
+#define celt_fir(x, num, y, N, ord, arch) \
+    ((void)arch, celt_fir_sse4_1(x, num, y, N, ord, arch))
 
 #else
 
@@ -56,11 +55,10 @@ extern void (*const CELT_FIR_IMPL[OPUS_ARCHMASK + 1])(
          opus_val16 *y,
          int N,
          int ord,
-         opus_val16 *mem,
          int arch);
 
-#  define celt_fir(x, num, y, N, ord, mem, arch) \
-    ((*CELT_FIR_IMPL[(arch) & OPUS_ARCHMASK])(x, num, y, N, ord, mem, arch))
+#  define celt_fir(x, num, y, N, ord, arch) \
+    ((*CELT_FIR_IMPL[(arch) & OPUS_ARCHMASK])(x, num, y, N, ord, arch))
 
 #endif
 #endif

+ 7 - 50
thirdparty/opus/celt/x86/celt_lpc_sse.c → thirdparty/opus/celt/x86/celt_lpc_sse4_1.c

@@ -40,65 +40,23 @@
 
 #if defined(FIXED_POINT)
 
-void celt_fir_sse4_1(const opus_val16 *_x,
+void celt_fir_sse4_1(const opus_val16 *x,
          const opus_val16 *num,
-         opus_val16 *_y,
+         opus_val16 *y,
          int N,
          int ord,
-         opus_val16 *mem,
          int arch)
 {
     int i,j;
     VARDECL(opus_val16, rnum);
-    VARDECL(opus_val16, x);
 
     __m128i vecNoA;
     opus_int32 noA ;
     SAVE_STACK;
 
    ALLOC(rnum, ord, opus_val16);
-   ALLOC(x, N+ord, opus_val16);
    for(i=0;i<ord;i++)
       rnum[i] = num[ord-i-1];
-   for(i=0;i<ord;i++)
-      x[i] = mem[ord-i-1];
-
-   for (i=0;i<N-7;i+=8)
-   {
-       x[i+ord  ]=_x[i  ];
-       x[i+ord+1]=_x[i+1];
-       x[i+ord+2]=_x[i+2];
-       x[i+ord+3]=_x[i+3];
-       x[i+ord+4]=_x[i+4];
-       x[i+ord+5]=_x[i+5];
-       x[i+ord+6]=_x[i+6];
-       x[i+ord+7]=_x[i+7];
-   }
-
-   for (;i<N-3;i+=4)
-   {
-       x[i+ord  ]=_x[i  ];
-       x[i+ord+1]=_x[i+1];
-       x[i+ord+2]=_x[i+2];
-       x[i+ord+3]=_x[i+3];
-   }
-
-   for (;i<N;i++)
-         x[i+ord]=_x[i];
-
-   for(i=0;i<ord;i++)
-      mem[i] = _x[N-i-1];
-#ifdef SMALL_FOOTPRINT
-   for (i=0;i<N;i++)
-   {
-      opus_val32 sum = SHL32(EXTEND32(_x[i]), SIG_SHIFT);
-      for (j=0;j<ord;j++)
-      {
-         sum = MAC16_16(sum,rnum[j],x[i+j]);
-      }
-      _y[i] = SATURATE16(PSHR32(sum, SIG_SHIFT));
-   }
-#else
    noA = EXTEND32(1) << SIG_SHIFT >> 1;
    vecNoA = _mm_set_epi32(noA, noA, noA, noA);
 
@@ -107,25 +65,24 @@ void celt_fir_sse4_1(const opus_val16 *_x,
       opus_val32 sums[4] = {0};
       __m128i vecSum, vecX;
 
-      xcorr_kernel(rnum, x+i, sums, ord, arch);
+      xcorr_kernel(rnum, x+i-ord, sums, ord, arch);
 
       vecSum = _mm_loadu_si128((__m128i *)sums);
       vecSum = _mm_add_epi32(vecSum, vecNoA);
       vecSum = _mm_srai_epi32(vecSum, SIG_SHIFT);
-      vecX = OP_CVTEPI16_EPI32_M64(_x + i);
+      vecX = OP_CVTEPI16_EPI32_M64(x + i);
       vecSum = _mm_add_epi32(vecSum, vecX);
       vecSum = _mm_packs_epi32(vecSum, vecSum);
-      _mm_storel_epi64((__m128i *)(_y + i), vecSum);
+      _mm_storel_epi64((__m128i *)(y + i), vecSum);
    }
    for (;i<N;i++)
    {
       opus_val32 sum = 0;
       for (j=0;j<ord;j++)
-         sum = MAC16_16(sum, rnum[j], x[i + j]);
-      _y[i] = SATURATE16(ADD32(EXTEND32(_x[i]), PSHR32(sum, SIG_SHIFT)));
+         sum = MAC16_16(sum, rnum[j], x[i+j-ord]);
+      y[i] = SATURATE16(ADD32(EXTEND32(x[i]), PSHR32(sum, SIG_SHIFT)));
    }
 
-#endif
    RESTORE_STACK;
 }
 

+ 23 - 23
thirdparty/opus/celt/tests/test_unit_types.c → thirdparty/opus/celt/x86/vq_sse.h

@@ -1,5 +1,4 @@
-/* Copyright (c) 2008-2011 Xiph.Org Foundation
-   Written by Jean-Marc Valin */
+/* Copyright (c) 2016  Jean-Marc Valin */
 /*
    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions
@@ -25,26 +24,27 @@
    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
+#ifndef VQ_SSE_H
+#define VQ_SSE_H
+
+#if defined(OPUS_X86_MAY_HAVE_SSE2) && !defined(FIXED_POINT)
+#define OVERRIDE_OP_PVQ_SEARCH
+
+opus_val16 op_pvq_search_sse2(celt_norm *_X, int *iy, int K, int N, int arch);
+
+#if defined(OPUS_X86_PRESUME_SSE2)
+#define op_pvq_search(x, iy, K, N, arch) \
+    (op_pvq_search_sse2(x, iy, K, N, arch))
+
+#else
+
+extern opus_val16 (*const OP_PVQ_SEARCH_IMPL[OPUS_ARCHMASK + 1])(
+      celt_norm *_X, int *iy, int K, int N, int arch);
+
+#  define op_pvq_search(X, iy, K, N, arch) \
+    ((*OP_PVQ_SEARCH_IMPL[(arch) & OPUS_ARCHMASK])(X, iy, K, N, arch))
+
+#endif
 #endif
 
-#include "opus_types.h"
-#include <stdio.h>
-
-int main(void)
-{
-   opus_int16 i = 1;
-   i <<= 14;
-   if (i>>14 != 1)
-   {
-      fprintf(stderr, "opus_int16 isn't 16 bits\n");
-      return 1;
-   }
-   if (sizeof(opus_int16)*2 != sizeof(opus_int32))
-   {
-      fprintf(stderr, "16*2 != 32\n");
-      return 1;
-   }
-   return 0;
-}
+#endif

+ 217 - 0
thirdparty/opus/celt/x86/vq_sse2.c

@@ -0,0 +1,217 @@
+/* Copyright (c) 2007-2008 CSIRO
+   Copyright (c) 2007-2009 Xiph.Org Foundation
+   Copyright (c) 2007-2016 Jean-Marc Valin */
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <xmmintrin.h>
+#include <emmintrin.h>
+#include "celt_lpc.h"
+#include "stack_alloc.h"
+#include "mathops.h"
+#include "vq.h"
+#include "x86cpu.h"
+
+
+#ifndef FIXED_POINT
+
+opus_val16 op_pvq_search_sse2(celt_norm *_X, int *iy, int K, int N, int arch)
+{
+   int i, j;
+   int pulsesLeft;
+   float xy, yy;
+   VARDECL(celt_norm, y);
+   VARDECL(celt_norm, X);
+   VARDECL(float, signy);
+   __m128 signmask;
+   __m128 sums;
+   __m128i fours;
+   SAVE_STACK;
+
+   (void)arch;
+   /* All bits set to zero, except for the sign bit. */
+   signmask = _mm_set_ps1(-0.f);
+   fours = _mm_set_epi32(4, 4, 4, 4);
+   ALLOC(y, N+3, celt_norm);
+   ALLOC(X, N+3, celt_norm);
+   ALLOC(signy, N+3, float);
+
+   OPUS_COPY(X, _X, N);
+   X[N] = X[N+1] = X[N+2] = 0;
+   sums = _mm_setzero_ps();
+   for (j=0;j<N;j+=4)
+   {
+      __m128 x4, s4;
+      x4 = _mm_loadu_ps(&X[j]);
+      s4 = _mm_cmplt_ps(x4, _mm_setzero_ps());
+      /* Get rid of the sign */
+      x4 = _mm_andnot_ps(signmask, x4);
+      sums = _mm_add_ps(sums, x4);
+      /* Clear y and iy in case we don't do the projection. */
+      _mm_storeu_ps(&y[j], _mm_setzero_ps());
+      _mm_storeu_si128((__m128i*)&iy[j], _mm_setzero_si128());
+      _mm_storeu_ps(&X[j], x4);
+      _mm_storeu_ps(&signy[j], s4);
+   }
+   sums = _mm_add_ps(sums, _mm_shuffle_ps(sums, sums, _MM_SHUFFLE(1, 0, 3, 2)));
+   sums = _mm_add_ps(sums, _mm_shuffle_ps(sums, sums, _MM_SHUFFLE(2, 3, 0, 1)));
+
+   xy = yy = 0;
+
+   pulsesLeft = K;
+
+   /* Do a pre-search by projecting on the pyramid */
+   if (K > (N>>1))
+   {
+      __m128i pulses_sum;
+      __m128 yy4, xy4;
+      __m128 rcp4;
+      opus_val32 sum = _mm_cvtss_f32(sums);
+      /* If X is too small, just replace it with a pulse at 0 */
+      /* Prevents infinities and NaNs from causing too many pulses
+         to be allocated. 64 is an approximation of infinity here. */
+      if (!(sum > EPSILON && sum < 64))
+      {
+         X[0] = QCONST16(1.f,14);
+         j=1; do
+            X[j]=0;
+         while (++j<N);
+         sums = _mm_set_ps1(1.f);
+      }
+      /* Using K+e with e < 1 guarantees we cannot get more than K pulses. */
+      rcp4 = _mm_mul_ps(_mm_set_ps1((float)(K+.8)), _mm_rcp_ps(sums));
+      xy4 = yy4 = _mm_setzero_ps();
+      pulses_sum = _mm_setzero_si128();
+      for (j=0;j<N;j+=4)
+      {
+         __m128 rx4, x4, y4;
+         __m128i iy4;
+         x4 = _mm_loadu_ps(&X[j]);
+         rx4 = _mm_mul_ps(x4, rcp4);
+         iy4 = _mm_cvttps_epi32(rx4);
+         pulses_sum = _mm_add_epi32(pulses_sum, iy4);
+         _mm_storeu_si128((__m128i*)&iy[j], iy4);
+         y4 = _mm_cvtepi32_ps(iy4);
+         xy4 = _mm_add_ps(xy4, _mm_mul_ps(x4, y4));
+         yy4 = _mm_add_ps(yy4, _mm_mul_ps(y4, y4));
+         /* double the y[] vector so we don't have to do it in the search loop. */
+         _mm_storeu_ps(&y[j], _mm_add_ps(y4, y4));
+      }
+      pulses_sum = _mm_add_epi32(pulses_sum, _mm_shuffle_epi32(pulses_sum, _MM_SHUFFLE(1, 0, 3, 2)));
+      pulses_sum = _mm_add_epi32(pulses_sum, _mm_shuffle_epi32(pulses_sum, _MM_SHUFFLE(2, 3, 0, 1)));
+      pulsesLeft -= _mm_cvtsi128_si32(pulses_sum);
+      xy4 = _mm_add_ps(xy4, _mm_shuffle_ps(xy4, xy4, _MM_SHUFFLE(1, 0, 3, 2)));
+      xy4 = _mm_add_ps(xy4, _mm_shuffle_ps(xy4, xy4, _MM_SHUFFLE(2, 3, 0, 1)));
+      xy = _mm_cvtss_f32(xy4);
+      yy4 = _mm_add_ps(yy4, _mm_shuffle_ps(yy4, yy4, _MM_SHUFFLE(1, 0, 3, 2)));
+      yy4 = _mm_add_ps(yy4, _mm_shuffle_ps(yy4, yy4, _MM_SHUFFLE(2, 3, 0, 1)));
+      yy = _mm_cvtss_f32(yy4);
+   }
+   X[N] = X[N+1] = X[N+2] = -100;
+   y[N] = y[N+1] = y[N+2] = 100;
+   celt_sig_assert(pulsesLeft>=0);
+
+   /* This should never happen, but just in case it does (e.g. on silence)
+      we fill the first bin with pulses. */
+   if (pulsesLeft > N+3)
+   {
+      opus_val16 tmp = (opus_val16)pulsesLeft;
+      yy = MAC16_16(yy, tmp, tmp);
+      yy = MAC16_16(yy, tmp, y[0]);
+      iy[0] += pulsesLeft;
+      pulsesLeft=0;
+   }
+
+   for (i=0;i<pulsesLeft;i++)
+   {
+      int best_id;
+      __m128 xy4, yy4;
+      __m128 max, max2;
+      __m128i count;
+      __m128i pos;
+      /* The squared magnitude term gets added anyway, so we might as well
+         add it outside the loop */
+      yy = ADD16(yy, 1);
+      xy4 = _mm_load1_ps(&xy);
+      yy4 = _mm_load1_ps(&yy);
+      max = _mm_setzero_ps();
+      pos = _mm_setzero_si128();
+      count = _mm_set_epi32(3, 2, 1, 0);
+      for (j=0;j<N;j+=4)
+      {
+         __m128 x4, y4, r4;
+         x4 = _mm_loadu_ps(&X[j]);
+         y4 = _mm_loadu_ps(&y[j]);
+         x4 = _mm_add_ps(x4, xy4);
+         y4 = _mm_add_ps(y4, yy4);
+         y4 = _mm_rsqrt_ps(y4);
+         r4 = _mm_mul_ps(x4, y4);
+         /* Update the index of the max. */
+         pos = _mm_max_epi16(pos, _mm_and_si128(count, _mm_castps_si128(_mm_cmpgt_ps(r4, max))));
+         /* Update the max. */
+         max = _mm_max_ps(max, r4);
+         /* Update the indices (+4) */
+         count = _mm_add_epi32(count, fours);
+      }
+      /* Horizontal max */
+      max2 = _mm_max_ps(max, _mm_shuffle_ps(max, max, _MM_SHUFFLE(1, 0, 3, 2)));
+      max2 = _mm_max_ps(max2, _mm_shuffle_ps(max2, max2, _MM_SHUFFLE(2, 3, 0, 1)));
+      /* Now that max2 contains the max at all positions, look at which value(s) of the
+         partial max is equal to the global max. */
+      pos = _mm_and_si128(pos, _mm_castps_si128(_mm_cmpeq_ps(max, max2)));
+      pos = _mm_max_epi16(pos, _mm_unpackhi_epi64(pos, pos));
+      pos = _mm_max_epi16(pos, _mm_shufflelo_epi16(pos, _MM_SHUFFLE(1, 0, 3, 2)));
+      best_id = _mm_cvtsi128_si32(pos);
+
+      /* Updating the sums of the new pulse(s) */
+      xy = ADD32(xy, EXTEND32(X[best_id]));
+      /* We're multiplying y[j] by two so we don't have to do it here */
+      yy = ADD16(yy, y[best_id]);
+
+      /* Only now that we've made the final choice, update y/iy */
+      /* Multiplying y[j] by 2 so we don't have to do it everywhere else */
+      y[best_id] += 2;
+      iy[best_id]++;
+   }
+
+   /* Put the original sign back */
+   for (j=0;j<N;j+=4)
+   {
+      __m128i y4;
+      __m128i s4;
+      y4 = _mm_loadu_si128((__m128i*)&iy[j]);
+      s4 = _mm_castps_si128(_mm_loadu_ps(&signy[j]));
+      y4 = _mm_xor_si128(_mm_add_epi32(y4, s4), s4);
+      _mm_storeu_si128((__m128i*)&iy[j], y4);
+   }
+   RESTORE_STACK;
+   return yy;
+}
+
+#endif

+ 13 - 1
thirdparty/opus/celt/x86/x86_celt_map.c

@@ -33,6 +33,7 @@
 #include "celt_lpc.h"
 #include "pitch.h"
 #include "pitch_sse.h"
+#include "vq.h"
 
 #if defined(OPUS_HAVE_RTCD)
 
@@ -46,7 +47,6 @@ void (*const CELT_FIR_IMPL[OPUS_ARCHMASK + 1])(
          opus_val16       *y,
          int              N,
          int              ord,
-         opus_val16       *mem,
          int              arch
 ) = {
   celt_fir_c,                /* non-sse */
@@ -151,5 +151,17 @@ void (*const COMB_FILTER_CONST_IMPL[OPUS_ARCHMASK + 1])(
 
 #endif
 
+#if defined(OPUS_X86_MAY_HAVE_SSE2) && !defined(OPUS_X86_PRESUME_SSE2)
+opus_val16 (*const OP_PVQ_SEARCH_IMPL[OPUS_ARCHMASK + 1])(
+      celt_norm *_X, int *iy, int K, int N, int arch
+) = {
+  op_pvq_search_c,                /* non-sse */
+  op_pvq_search_c,
+  MAY_HAVE_SSE2(op_pvq_search),
+  MAY_HAVE_SSE2(op_pvq_search),
+  MAY_HAVE_SSE2(op_pvq_search)
+};
+#endif
+
 #endif
 #endif

+ 3 - 1
thirdparty/opus/celt/x86/x86cpu.h

@@ -82,7 +82,9 @@ int opus_select_arch(void);
  (_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

+ 118 - 3
thirdparty/opus/config.h

@@ -1,5 +1,44 @@
-/* Opus configuration header */
-/* Based on the output of libopus configure script */
+/* config.h.  Generated from config.h.in by configure.  */
+/* config.h.in.  Generated from configure.ac by autoheader.  */
+
+/* Get CPU Info by asm method */
+#define CPU_INFO_BY_ASM 1
+
+/* Get CPU Info by c method */
+/* #undef CPU_INFO_BY_C */
+
+/* Custom modes */
+/* #undef CUSTOM_MODES */
+
+/* Do not build the float API */
+/* #undef DISABLE_FLOAT_API */
+
+/* Disable bitstream fixes from RFC 8251 */
+/* #undef DISABLE_UPDATE_DRAFT */
+
+/* Assertions */
+/* #undef ENABLE_ASSERTIONS */
+
+/* Hardening */
+#define ENABLE_HARDENING 1
+
+/* Debug fixed-point implementation */
+/* #undef FIXED_DEBUG */
+
+/* Compile as fixed-point (for machines without a fast enough FPU) */
+/* #undef FIXED_POINT */
+
+/* Float approximations */
+/* #undef FLOAT_APPROX */
+
+/* Fuzzing */
+/* #undef FUZZING */
+
+/* Define to 1 if you have the <alloca.h> header file. */
+/*  #undef HAVE_ALLOCA_H  */
+
+/* NE10 library is installed on host. Make sure it is on target! */
+/* #undef HAVE_ARM_NE10 */
 
 /* Define to 1 if you have the <dlfcn.h> header file. */
 #define HAVE_DLFCN_H 1
@@ -41,6 +80,9 @@
 /* Define to 1 if you have the <unistd.h> header file. */
 #define HAVE_UNISTD_H 1
 
+/* Define to 1 if you have the `__malloc_hook' function. */
+#define HAVE___MALLOC_HOOK 1
+
 /* Define to the sub-directory in which libtool stores uninstalled libraries.
    */
 #define LT_OBJDIR ".libs/"
@@ -92,9 +134,80 @@
 
 #endif // OPUS_ARM64_OPT
 
+/* Define if binary requires Aarch64 Neon Intrinsics */
+/* #undef OPUS_ARM_PRESUME_AARCH64_NEON_INTR */
+
+/* Define if binary requires EDSP instruction support */
+/* #undef OPUS_ARM_PRESUME_EDSP */
+
+/* Define if binary requires ARMv6 media instruction support */
+/* #undef OPUS_ARM_PRESUME_MEDIA */
+
+/* Define if binary requires NEON instruction support */
+/* #undef OPUS_ARM_PRESUME_NEON */
+
+/* Define if binary requires NEON intrinsics support */
+/* #undef OPUS_ARM_PRESUME_NEON_INTR */
+
 /* This is a build of OPUS */
 #define OPUS_BUILD /**/
 
+/* Run bit-exactness checks between optimized and c implementations */
+/* #undef OPUS_CHECK_ASM */
+
+#ifndef OPUS_ARM_OPT
+/* Use run-time CPU capabilities detection */
+#define OPUS_HAVE_RTCD 1
+#endif
+
+/* Compiler supports X86 AVX Intrinsics */
+/* #define OPUS_X86_MAY_HAVE_AVX */
+
+/* Compiler supports X86 SSE Intrinsics */
+/* #define OPUS_X86_MAY_HAVE_SSE */
+
+/* Compiler supports X86 SSE2 Intrinsics */
+/* #define OPUS_X86_MAY_HAVE_SSE2 */
+
+/* Compiler supports X86 SSE4.1 Intrinsics */
+/* #define OPUS_X86_MAY_HAVE_SSE4_1 */
+
+/* Define if binary requires AVX intrinsics support */
+/* #undef OPUS_X86_PRESUME_AVX */
+
+/* Define if binary requires SSE intrinsics support */
+#define OPUS_X86_PRESUME_SSE 1
+
+/* Define if binary requires SSE2 intrinsics support */
+#define OPUS_X86_PRESUME_SSE2 1
+
+/* Define if binary requires SSE4.1 intrinsics support */
+#define OPUS_X86_PRESUME_SSE4_1 1
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "[email protected]"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "opus"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "opus unknown"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "opus"
+
+/* Define to the home page for this package. */
+#define PACKAGE_URL ""
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "unknown"
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Make use of alloca */
+/* #undef USE_ALLOCA */
+
 #ifndef WIN32
 	/* Use C99 variable-size arrays */
 	#define VAR_ARRAYS 1
@@ -103,11 +216,13 @@
 	#define USE_ALLOCA 1
 #endif
 
+/* Define to empty if `const' does not conform to ANSI C. */
+/* #undef const */
+
 #ifndef OPUS_FIXED_POINT
 #define FLOAT_APPROX 1
 #endif
 
-
 /* Define to `__inline__' or `__inline' if that's what the C compiler
    calls it, or to nothing if 'inline' is not supported under any name.  */
 #ifndef __cplusplus

+ 44 - 31
thirdparty/opus/info.c

@@ -107,26 +107,32 @@ static int op_tags_ensure_capacity(OpusTags *_tags,size_t _ncomments){
   char   **user_comments;
   int     *comment_lengths;
   int      cur_ncomments;
-  char    *binary_suffix_data;
-  int      binary_suffix_len;
   size_t   size;
   if(OP_UNLIKELY(_ncomments>=(size_t)INT_MAX))return OP_EFAULT;
   size=sizeof(*_tags->comment_lengths)*(_ncomments+1);
   if(size/sizeof(*_tags->comment_lengths)!=_ncomments+1)return OP_EFAULT;
   cur_ncomments=_tags->comments;
-  comment_lengths=_tags->comment_lengths;
-  binary_suffix_len=comment_lengths==NULL?0:comment_lengths[cur_ncomments];
+  /*We only support growing.
+    Trimming requires cleaning up the allocated strings in the old space, and
+     is best handled separately if it's ever needed.*/
+  OP_ASSERT(_ncomments>=(size_t)cur_ncomments);
   comment_lengths=(int *)_ogg_realloc(_tags->comment_lengths,size);
   if(OP_UNLIKELY(comment_lengths==NULL))return OP_EFAULT;
-  comment_lengths[_ncomments]=binary_suffix_len;
+  if(_tags->comment_lengths==NULL){
+    OP_ASSERT(cur_ncomments==0);
+    comment_lengths[cur_ncomments]=0;
+  }
+  comment_lengths[_ncomments]=comment_lengths[cur_ncomments];
   _tags->comment_lengths=comment_lengths;
   size=sizeof(*_tags->user_comments)*(_ncomments+1);
   if(size/sizeof(*_tags->user_comments)!=_ncomments+1)return OP_EFAULT;
-  user_comments=_tags->user_comments;
-  binary_suffix_data=user_comments==NULL?NULL:user_comments[cur_ncomments];
   user_comments=(char **)_ogg_realloc(_tags->user_comments,size);
   if(OP_UNLIKELY(user_comments==NULL))return OP_EFAULT;
-  user_comments[_ncomments]=binary_suffix_data;
+  if(_tags->user_comments==NULL){
+    OP_ASSERT(cur_ncomments==0);
+    user_comments[cur_ncomments]=NULL;
+  }
+  user_comments[_ncomments]=user_comments[cur_ncomments];
   _tags->user_comments=user_comments;
   return 0;
 }
@@ -275,28 +281,30 @@ int opus_tags_copy(OpusTags *_dst,const OpusTags *_src){
   ret=opus_tags_copy_impl(&dst,_src);
   if(OP_UNLIKELY(ret<0))opus_tags_clear(&dst);
   else *_dst=*&dst;
-  return 0;
+  return ret;
 }
 
 int opus_tags_add(OpusTags *_tags,const char *_tag,const char *_value){
-  char *comment;
-  int   tag_len;
-  int   value_len;
-  int   ncomments;
-  int   ret;
+  char   *comment;
+  size_t  tag_len;
+  size_t  value_len;
+  int     ncomments;
+  int     ret;
   ncomments=_tags->comments;
   ret=op_tags_ensure_capacity(_tags,ncomments+1);
   if(OP_UNLIKELY(ret<0))return ret;
   tag_len=strlen(_tag);
   value_len=strlen(_value);
   /*+2 for '=' and '\0'.*/
+  if(tag_len+value_len<tag_len)return OP_EFAULT;
+  if(tag_len+value_len>(size_t)INT_MAX-2)return OP_EFAULT;
   comment=(char *)_ogg_malloc(sizeof(*comment)*(tag_len+value_len+2));
   if(OP_UNLIKELY(comment==NULL))return OP_EFAULT;
   memcpy(comment,_tag,sizeof(*comment)*tag_len);
   comment[tag_len]='=';
   memcpy(comment+tag_len+1,_value,sizeof(*comment)*(value_len+1));
   _tags->user_comments[ncomments]=comment;
-  _tags->comment_lengths[ncomments]=tag_len+value_len+1;
+  _tags->comment_lengths[ncomments]=(int)(tag_len+value_len+1);
   _tags->comments=ncomments+1;
   return 0;
 }
@@ -337,7 +345,10 @@ int opus_tags_set_binary_suffix(OpusTags *_tags,
 }
 
 int opus_tagcompare(const char *_tag_name,const char *_comment){
-  return opus_tagncompare(_tag_name,strlen(_tag_name),_comment);
+  size_t tag_len;
+  tag_len=strlen(_tag_name);
+  if(OP_UNLIKELY(tag_len>(size_t)INT_MAX))return -1;
+  return opus_tagncompare(_tag_name,(int)tag_len,_comment);
 }
 
 int opus_tagncompare(const char *_tag_name,int _tag_len,const char *_comment){
@@ -348,17 +359,18 @@ int opus_tagncompare(const char *_tag_name,int _tag_len,const char *_comment){
 }
 
 const char *opus_tags_query(const OpusTags *_tags,const char *_tag,int _count){
-  char **user_comments;
-  int    tag_len;
-  int    found;
-  int    ncomments;
-  int    ci;
+  char   **user_comments;
+  size_t   tag_len;
+  int      found;
+  int      ncomments;
+  int      ci;
   tag_len=strlen(_tag);
+  if(OP_UNLIKELY(tag_len>(size_t)INT_MAX))return NULL;
   ncomments=_tags->comments;
   user_comments=_tags->user_comments;
   found=0;
   for(ci=0;ci<ncomments;ci++){
-    if(!opus_tagncompare(_tag,tag_len,user_comments[ci])){
+    if(!opus_tagncompare(_tag,(int)tag_len,user_comments[ci])){
       /*We return a pointer to the data, not a copy.*/
       if(_count==found++)return user_comments[ci]+tag_len+1;
     }
@@ -368,17 +380,18 @@ const char *opus_tags_query(const OpusTags *_tags,const char *_tag,int _count){
 }
 
 int opus_tags_query_count(const OpusTags *_tags,const char *_tag){
-  char **user_comments;
-  int    tag_len;
-  int    found;
-  int    ncomments;
-  int    ci;
+  char   **user_comments;
+  size_t   tag_len;
+  int      found;
+  int      ncomments;
+  int      ci;
   tag_len=strlen(_tag);
+  if(OP_UNLIKELY(tag_len>(size_t)INT_MAX))return 0;
   ncomments=_tags->comments;
   user_comments=_tags->user_comments;
   found=0;
   for(ci=0;ci<ncomments;ci++){
-    if(!opus_tagncompare(_tag,tag_len,user_comments[ci]))found++;
+    if(!opus_tagncompare(_tag,(int)tag_len,user_comments[ci]))found++;
   }
   return found;
 }
@@ -403,7 +416,8 @@ static int opus_tags_get_gain(const OpusTags *_tags,int *_gain_q8,
   ncomments=_tags->comments;
   /*Look for the first valid tag with the name _tag_name and use that.*/
   for(ci=0;ci<ncomments;ci++){
-    if(opus_tagncompare(_tag_name,_tag_len,comments[ci])==0){
+    OP_ASSERT(_tag_len<=(size_t)INT_MAX);
+    if(opus_tagncompare(_tag_name,(int)_tag_len,comments[ci])==0){
       char       *p;
       opus_int32  gain_q8;
       int         negative;
@@ -439,8 +453,7 @@ int opus_tags_get_track_gain(const OpusTags *_tags,int *_gain_q8){
 }
 
 static int op_is_jpeg(const unsigned char *_buf,size_t _buf_sz){
-  return _buf_sz>=11&&memcmp(_buf,"\xFF\xD8\xFF\xE0",4)==0
-   &&(_buf[4]<<8|_buf[5])>=16&&memcmp(_buf+6,"JFIF",5)==0;
+  return _buf_sz>=3&&memcmp(_buf,"\xFF\xD8\xFF",3)==0;
 }
 
 /*Tries to extract the width, height, bits per pixel, and palette size of a

+ 14 - 9
thirdparty/opus/internal.h

@@ -136,6 +136,9 @@ struct OggOpusLink{
      that end-trimming calculations work properly.
     This is only valid for seekable sources.*/
   opus_int64   end_offset;
+  /*The total duration of all prior links.
+    This is always zero for non-seekable sources.*/
+  ogg_int64_t  pcm_file_offset;
   /*The granule position of the last sample.
     This is only valid for seekable sources.*/
   ogg_int64_t  pcm_end;
@@ -150,23 +153,25 @@ struct OggOpusLink{
 };
 
 struct OggOpusFile{
-  /*The callbacks used to access the data source.*/
+  /*The callbacks used to access the stream.*/
   OpusFileCallbacks  callbacks;
-  /*A FILE *, memory bufer, etc.*/
-  void              *source;
-  /*Whether or not we can seek with this data source.*/
+  /*A FILE *, memory buffer, etc.*/
+  void              *stream;
+  /*Whether or not we can seek with this stream.*/
   int                seekable;
   /*The number of links in this chained Ogg Opus file.*/
   int                nlinks;
   /*The cached information from each link in a chained Ogg Opus file.
-    If source isn't seekable (e.g., it's a pipe), only the current link
+    If stream isn't seekable (e.g., it's a pipe), only the current link
      appears.*/
   OggOpusLink       *links;
   /*The number of serial numbers from a single link.*/
   int                nserialnos;
   /*The capacity of the list of serial numbers from a single link.*/
   int                cserialnos;
-  /*Storage for the list of serial numbers from a single link.*/
+  /*Storage for the list of serial numbers from a single link.
+    This is a scratch buffer used when scanning the BOS pages at the start of
+     each link.*/
   ogg_uint32_t      *serialnos;
   /*This is the current offset of the data processed by the ogg_sync_state.
     After a seek, this should be set to the target offset so that we can track
@@ -174,9 +179,9 @@ struct OggOpusFile{
     After a call to op_get_next_page(), this will point to the first byte after
      that page.*/
   opus_int64         offset;
-  /*The total size of this data source, or -1 if it's unseekable.*/
+  /*The total size of this stream, or -1 if it's unseekable.*/
   opus_int64         end;
-  /*Used to locate pages in the data source.*/
+  /*Used to locate pages in the stream.*/
   ogg_sync_state     oy;
   /*One of OP_NOTOPEN, OP_PARTOPEN, OP_OPENED, OP_STREAMSET, OP_INITSET.*/
   int                ready_state;
@@ -227,7 +232,7 @@ struct OggOpusFile{
   /*The number of valid samples in the decoded buffer.*/
   int                od_buffer_size;
   /*The type of gain offset to apply.
-    One of OP_HEADER_GAIN, OP_TRACK_GAIN, or OP_ABSOLUTE_GAIN.*/
+    One of OP_HEADER_GAIN, OP_ALBUM_GAIN, OP_TRACK_GAIN, or OP_ABSOLUTE_GAIN.*/
   int                gain_type;
   /*The offset to apply to the gain.*/
   opus_int32         gain_offset_q8;

+ 378 - 0
thirdparty/opus/mapping_matrix.c

@@ -0,0 +1,378 @@
+/* Copyright (c) 2017 Google Inc.
+   Written by Andrew Allen */
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "arch.h"
+#include "float_cast.h"
+#include "opus_private.h"
+#include "opus_defines.h"
+#include "mapping_matrix.h"
+
+#define MATRIX_INDEX(nb_rows, row, col) (nb_rows * col + row)
+
+opus_int32 mapping_matrix_get_size(int rows, int cols)
+{
+  opus_int32 size;
+
+  /* Mapping Matrix must only support up to 255 channels in or out.
+   * Additionally, the total cell count must be <= 65004 octets in order
+   * for the matrix to be stored in an OGG header.
+   */
+  if (rows > 255 || cols > 255)
+      return 0;
+  size = rows * (opus_int32)cols * sizeof(opus_int16);
+  if (size > 65004)
+    return 0;
+
+  return align(sizeof(MappingMatrix)) + align(size);
+}
+
+opus_int16 *mapping_matrix_get_data(const MappingMatrix *matrix)
+{
+  /* void* cast avoids clang -Wcast-align warning */
+  return (opus_int16*)(void*)((char*)matrix + align(sizeof(MappingMatrix)));
+}
+
+void mapping_matrix_init(MappingMatrix * const matrix,
+  int rows, int cols, int gain, const opus_int16 *data, opus_int32 data_size)
+{
+  int i;
+  opus_int16 *ptr;
+
+#if !defined(ENABLE_ASSERTIONS)
+  (void)data_size;
+#endif
+  celt_assert(align(data_size) == align(rows * cols * sizeof(opus_int16)));
+
+  matrix->rows = rows;
+  matrix->cols = cols;
+  matrix->gain = gain;
+  ptr = mapping_matrix_get_data(matrix);
+  for (i = 0; i < rows * cols; i++)
+  {
+     ptr[i] = data[i];
+  }
+}
+
+#ifndef DISABLE_FLOAT_API
+void mapping_matrix_multiply_channel_in_float(
+    const MappingMatrix *matrix,
+    const float *input,
+    int input_rows,
+    opus_val16 *output,
+    int output_row,
+    int output_rows,
+    int frame_size)
+{
+  /* Matrix data is ordered col-wise. */
+  opus_int16* matrix_data;
+  int i, col;
+
+  celt_assert(input_rows <= matrix->cols && output_rows <= matrix->rows);
+
+  matrix_data = mapping_matrix_get_data(matrix);
+
+  for (i = 0; i < frame_size; i++)
+  {
+    float tmp = 0;
+    for (col = 0; col < input_rows; col++)
+    {
+      tmp +=
+        matrix_data[MATRIX_INDEX(matrix->rows, output_row, col)] *
+        input[MATRIX_INDEX(input_rows, col, i)];
+    }
+#if defined(FIXED_POINT)
+    output[output_rows * i] = FLOAT2INT16((1/32768.f)*tmp);
+#else
+    output[output_rows * i] = (1/32768.f)*tmp;
+#endif
+  }
+}
+
+void mapping_matrix_multiply_channel_out_float(
+    const MappingMatrix *matrix,
+    const opus_val16 *input,
+    int input_row,
+    int input_rows,
+    float *output,
+    int output_rows,
+    int frame_size
+)
+{
+  /* Matrix data is ordered col-wise. */
+  opus_int16* matrix_data;
+  int i, row;
+  float input_sample;
+
+  celt_assert(input_rows <= matrix->cols && output_rows <= matrix->rows);
+
+  matrix_data = mapping_matrix_get_data(matrix);
+
+  for (i = 0; i < frame_size; i++)
+  {
+#if defined(FIXED_POINT)
+    input_sample = (1/32768.f)*input[input_rows * i];
+#else
+    input_sample = input[input_rows * i];
+#endif
+    for (row = 0; row < output_rows; row++)
+    {
+      float tmp =
+        (1/32768.f)*matrix_data[MATRIX_INDEX(matrix->rows, row, input_row)] *
+        input_sample;
+      output[MATRIX_INDEX(output_rows, row, i)] += tmp;
+    }
+  }
+}
+#endif /* DISABLE_FLOAT_API */
+
+void mapping_matrix_multiply_channel_in_short(
+    const MappingMatrix *matrix,
+    const opus_int16 *input,
+    int input_rows,
+    opus_val16 *output,
+    int output_row,
+    int output_rows,
+    int frame_size)
+{
+  /* Matrix data is ordered col-wise. */
+  opus_int16* matrix_data;
+  int i, col;
+
+  celt_assert(input_rows <= matrix->cols && output_rows <= matrix->rows);
+
+  matrix_data = mapping_matrix_get_data(matrix);
+
+  for (i = 0; i < frame_size; i++)
+  {
+    opus_val32 tmp = 0;
+    for (col = 0; col < input_rows; col++)
+    {
+#if defined(FIXED_POINT)
+      tmp +=
+        ((opus_int32)matrix_data[MATRIX_INDEX(matrix->rows, output_row, col)] *
+        (opus_int32)input[MATRIX_INDEX(input_rows, col, i)]) >> 8;
+#else
+      tmp +=
+        matrix_data[MATRIX_INDEX(matrix->rows, output_row, col)] *
+        input[MATRIX_INDEX(input_rows, col, i)];
+#endif
+    }
+#if defined(FIXED_POINT)
+    output[output_rows * i] = (opus_int16)((tmp + 64) >> 7);
+#else
+    output[output_rows * i] = (1/(32768.f*32768.f))*tmp;
+#endif
+  }
+}
+
+void mapping_matrix_multiply_channel_out_short(
+    const MappingMatrix *matrix,
+    const opus_val16 *input,
+    int input_row,
+    int input_rows,
+    opus_int16 *output,
+    int output_rows,
+    int frame_size)
+{
+  /* Matrix data is ordered col-wise. */
+  opus_int16* matrix_data;
+  int i, row;
+  opus_int32 input_sample;
+
+  celt_assert(input_rows <= matrix->cols && output_rows <= matrix->rows);
+
+  matrix_data = mapping_matrix_get_data(matrix);
+
+  for (i = 0; i < frame_size; i++)
+  {
+#if defined(FIXED_POINT)
+    input_sample = (opus_int32)input[input_rows * i];
+#else
+    input_sample = (opus_int32)FLOAT2INT16(input[input_rows * i]);
+#endif
+    for (row = 0; row < output_rows; row++)
+    {
+      opus_int32 tmp =
+        (opus_int32)matrix_data[MATRIX_INDEX(matrix->rows, row, input_row)] *
+        input_sample;
+      output[MATRIX_INDEX(output_rows, row, i)] += (tmp + 16384) >> 15;
+    }
+  }
+}
+
+const MappingMatrix mapping_matrix_foa_mixing = { 6, 6, 0 };
+const opus_int16 mapping_matrix_foa_mixing_data[36] = {
+     16384,      0, -16384,  23170,      0,      0,  16384,  23170,
+     16384,      0,      0,      0,  16384,      0, -16384, -23170,
+         0,      0,  16384, -23170,  16384,      0,      0,      0,
+         0,      0,      0,      0,  32767,      0,      0,      0,
+         0,      0,      0,  32767
+};
+
+const MappingMatrix mapping_matrix_soa_mixing = { 11, 11, 0 };
+const opus_int16 mapping_matrix_soa_mixing_data[121] = {
+     10923,   7723,  13377, -13377,  11585,   9459,   7723, -16384,
+     -6689,      0,      0,  10923,   7723,  13377,  13377, -11585,
+      9459,   7723,  16384,  -6689,      0,      0,  10923, -15447,
+     13377,      0,      0, -18919,   7723,      0,  13377,      0,
+         0,  10923,   7723, -13377, -13377,  11585,  -9459,   7723,
+     16384,  -6689,      0,      0,  10923,  -7723,      0,  13377,
+    -16384,      0, -15447,      0,   9459,      0,      0,  10923,
+     -7723,      0, -13377,  16384,      0, -15447,      0,   9459,
+         0,      0,  10923,  15447,      0,      0,      0,      0,
+    -15447,      0, -18919,      0,      0,  10923,   7723, -13377,
+     13377, -11585,  -9459,   7723, -16384,  -6689,      0,      0,
+     10923, -15447, -13377,      0,      0,  18919,   7723,      0,
+     13377,      0,      0,      0,      0,      0,      0,      0,
+         0,      0,      0,      0,  32767,      0,      0,      0,
+         0,      0,      0,      0,      0,      0,      0,      0,
+     32767
+};
+
+const MappingMatrix mapping_matrix_toa_mixing = { 18, 18, 0 };
+const opus_int16 mapping_matrix_toa_mixing_data[324] = {
+      8208,      0,   -881,  14369,      0,      0,  -8192,  -4163,
+     13218,      0,      0,      0,  11095,  -8836,  -6218,  14833,
+         0,      0,   8208, -10161,    881,  10161, -13218,  -2944,
+     -8192,   2944,      0, -10488,  -6218,   6248, -11095,  -6248,
+         0, -10488,      0,      0,   8208,  10161,    881, -10161,
+    -13218,   2944,  -8192,  -2944,      0,  10488,  -6218,  -6248,
+    -11095,   6248,      0,  10488,      0,      0,   8176,   5566,
+    -11552,   5566,   9681, -11205,   8192, -11205,      0,   4920,
+    -15158,   9756,  -3334,   9756,      0,  -4920,      0,      0,
+      8176,   7871,  11552,      0,      0,  15846,   8192,      0,
+     -9681,  -6958,      0,  13797,   3334,      0, -15158,      0,
+         0,      0,   8176,      0,  11552,   7871,      0,      0,
+      8192,  15846,   9681,      0,      0,      0,   3334,  13797,
+     15158,   6958,      0,      0,   8176,   5566, -11552,  -5566,
+     -9681, -11205,   8192,  11205,      0,   4920,  15158,   9756,
+     -3334,  -9756,      0,   4920,      0,      0,   8208,  14369,
+      -881,      0,      0,  -4163,  -8192,      0, -13218, -14833,
+         0,  -8836,  11095,      0,   6218,      0,      0,      0,
+      8208,  10161,    881,  10161,  13218,   2944,  -8192,   2944,
+         0,  10488,   6218,  -6248, -11095,  -6248,      0, -10488,
+         0,      0,   8208, -14369,   -881,      0,      0,   4163,
+     -8192,      0, -13218,  14833,      0,   8836,  11095,      0,
+      6218,      0,      0,      0,   8208,      0,   -881, -14369,
+         0,      0,  -8192,   4163,  13218,      0,      0,      0,
+     11095,   8836,  -6218, -14833,      0,      0,   8176,  -5566,
+    -11552,   5566,  -9681,  11205,   8192, -11205,      0,  -4920,
+     15158,  -9756,  -3334,   9756,      0,  -4920,      0,      0,
+      8176,      0,  11552,  -7871,      0,      0,   8192, -15846,
+      9681,      0,      0,      0,   3334, -13797,  15158,  -6958,
+         0,      0,   8176,  -7871,  11552,      0,      0, -15846,
+      8192,      0,  -9681,   6958,      0, -13797,   3334,      0,
+    -15158,      0,      0,      0,   8176,  -5566, -11552,  -5566,
+      9681,  11205,   8192,  11205,      0,  -4920, -15158,  -9756,
+     -3334,  -9756,      0,   4920,      0,      0,   8208, -10161,
+       881, -10161,  13218,  -2944,  -8192,  -2944,      0, -10488,
+      6218,   6248, -11095,   6248,      0,  10488,      0,      0,
+         0,      0,      0,      0,      0,      0,      0,      0,
+         0,      0,      0,      0,      0,      0,      0,      0,
+     32767,      0,      0,      0,      0,      0,      0,      0,
+         0,      0,      0,      0,      0,      0,      0,      0,
+         0,      0,      0,  32767
+};
+
+const MappingMatrix mapping_matrix_foa_demixing = { 6, 6, 0 };
+const opus_int16 mapping_matrix_foa_demixing_data[36] = {
+     16384,  16384,  16384,  16384,      0,      0,      0,  23170,
+         0, -23170,      0,      0, -16384,  16384, -16384,  16384,
+         0,      0,  23170,      0, -23170,      0,      0,      0,
+         0,      0,      0,      0,  32767,      0,      0,      0,
+         0,      0,      0,  32767
+};
+
+const MappingMatrix mapping_matrix_soa_demixing = { 11, 11, 3050 };
+const opus_int16 mapping_matrix_soa_demixing_data[121] = {
+      2771,   2771,   2771,   2771,   2771,   2771,   2771,   2771,
+      2771,      0,      0,  10033,  10033, -20066,  10033,  14189,
+     14189, -28378,  10033, -20066,      0,      0,   3393,   3393,
+      3393,  -3393,      0,      0,      0,  -3393,  -3393,      0,
+         0, -17378,  17378,      0, -17378, -24576,  24576,      0,
+     17378,      0,      0,      0, -14189,  14189,      0, -14189,
+    -28378,  28378,      0,  14189,      0,      0,      0,   2399,
+      2399,  -4799,  -2399,      0,      0,      0,  -2399,   4799,
+         0,      0,   1959,   1959,   1959,   1959,  -3918,  -3918,
+     -3918,   1959,   1959,      0,      0,  -4156,   4156,      0,
+      4156,      0,      0,      0,  -4156,      0,      0,      0,
+      8192,   8192, -16384,   8192,  16384,  16384, -32768,   8192,
+    -16384,      0,      0,      0,      0,      0,      0,      0,
+         0,      0,      0,      0,   8312,      0,      0,      0,
+         0,      0,      0,      0,      0,      0,      0,      0,
+      8312
+};
+
+const MappingMatrix mapping_matrix_toa_demixing = { 18, 18, 0 };
+const opus_int16 mapping_matrix_toa_demixing_data[324] = {
+      8192,   8192,   8192,   8192,   8192,   8192,   8192,   8192,
+      8192,   8192,   8192,   8192,   8192,   8192,   8192,   8192,
+         0,      0,      0,  -9779,   9779,   6263,   8857,      0,
+      6263,  13829,   9779, -13829,      0,  -6263,      0,  -8857,
+     -6263,  -9779,      0,      0,  -3413,   3413,   3413, -11359,
+     11359,  11359, -11359,  -3413,   3413,  -3413,  -3413, -11359,
+     11359,  11359, -11359,   3413,      0,      0,  13829,   9779,
+     -9779,   6263,      0,   8857,  -6263,      0,   9779,      0,
+    -13829,   6263,  -8857,      0,  -6263,  -9779,      0,      0,
+         0, -15617, -15617,   6406,      0,      0,  -6406,      0,
+     15617,      0,      0,  -6406,      0,      0,   6406,  15617,
+         0,      0,      0,  -5003,   5003, -10664,  15081,      0,
+    -10664,  -7075,   5003,   7075,      0,  10664,      0, -15081,
+     10664,  -5003,      0,      0,  -8176,  -8176,  -8176,   8208,
+      8208,   8208,   8208,  -8176,  -8176,  -8176,  -8176,   8208,
+      8208,   8208,   8208,  -8176,      0,      0,  -7075,   5003,
+     -5003, -10664,      0,  15081,  10664,      0,   5003,      0,
+      7075, -10664, -15081,      0,  10664,  -5003,      0,      0,
+     15617,      0,      0,      0,  -6406,   6406,      0, -15617,
+         0, -15617,  15617,      0,   6406,  -6406,      0,      0,
+         0,      0,      0, -11393,  11393,   2993,  -4233,      0,
+      2993, -16112,  11393,  16112,      0,  -2993,      0,   4233,
+     -2993, -11393,      0,      0,      0,  -9974,  -9974, -13617,
+         0,      0,  13617,      0,   9974,      0,      0,  13617,
+         0,      0, -13617,   9974,      0,      0,      0,   5579,
+     -5579,  10185,  14403,      0,  10185,  -7890,  -5579,   7890,
+         0, -10185,      0, -14403, -10185,   5579,      0,      0,
+     11826, -11826, -11826,   -901,    901,    901,   -901,  11826,
+    -11826,  11826,  11826,   -901,    901,    901,   -901, -11826,
+         0,      0,  -7890,  -5579,   5579,  10185,      0,  14403,
+    -10185,      0,  -5579,      0,   7890,  10185, -14403,      0,
+    -10185,   5579,      0,      0,  -9974,      0,      0,      0,
+    -13617,  13617,      0,   9974,      0,   9974,  -9974,      0,
+     13617, -13617,      0,      0,      0,      0,  16112, -11393,
+     11393,  -2993,      0,   4233,   2993,      0, -11393,      0,
+    -16112,  -2993,  -4233,      0,   2993,  11393,      0,      0,
+         0,      0,      0,      0,      0,      0,      0,      0,
+         0,      0,      0,      0,      0,      0,      0,      0,
+     32767,      0,      0,      0,      0,      0,      0,      0,
+         0,      0,      0,      0,      0,      0,      0,      0,
+         0,      0,      0,  32767
+};
+

+ 133 - 0
thirdparty/opus/mapping_matrix.h

@@ -0,0 +1,133 @@
+/* Copyright (c) 2017 Google Inc.
+   Written by Andrew Allen */
+/*
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/**
+ * @file mapping_matrix.h
+ * @brief Opus reference implementation mapping matrix API
+ */
+
+#ifndef MAPPING_MATRIX_H
+#define MAPPING_MATRIX_H
+
+#include "opus_types.h"
+#include "opus_projection.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct MappingMatrix
+{
+    int rows; /* number of channels outputted from matrix. */
+    int cols; /* number of channels inputted to matrix. */
+    int gain; /* in dB. S7.8-format. */
+    /* Matrix cell data goes here using col-wise ordering. */
+} MappingMatrix;
+
+opus_int32 mapping_matrix_get_size(int rows, int cols);
+
+opus_int16 *mapping_matrix_get_data(const MappingMatrix *matrix);
+
+void mapping_matrix_init(
+    MappingMatrix * const matrix,
+    int rows,
+    int cols,
+    int gain,
+    const opus_int16 *data,
+    opus_int32 data_size
+);
+
+#ifndef DISABLE_FLOAT_API
+void mapping_matrix_multiply_channel_in_float(
+    const MappingMatrix *matrix,
+    const float *input,
+    int input_rows,
+    opus_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 */

+ 77 - 78
thirdparty/opus/mlp.c

@@ -1,5 +1,5 @@
 /* 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
@@ -29,42 +29,13 @@
 #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;
@@ -92,54 +63,82 @@ static OPUS_INLINE float tansig_approx(float x)
     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);
+}
+
+static void gemm_accum(float *out, const opus_int8 *weights, int rows, int cols, int col_stride, const float *x)
+{
+   int i, j;
+   for (i=0;i<rows;i++)
+   {
+      for (j=0;j<cols;j++)
+         out[i] += weights[j*col_stride + i]*x[j];
+   }
 }
-#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;
+   int N, M;
+   int stride;
+   M = layer->nb_inputs;
+   N = layer->nb_neurons;
+   stride = N;
+   for (i=0;i<N;i++)
+      output[i] = layer->bias[i];
+   gemm_accum(output, layer->input_weights, N, M, stride, input);
+   for (i=0;i<N;i++)
+      output[i] *= WEIGHTS_SCALE;
+   if (layer->sigmoid) {
+      for (i=0;i<N;i++)
+         output[i] = sigmoid_approx(output[i]);
+   } else {
+      for (i=0;i<N;i++)
+         output[i] = tansig_approx(output[i]);
+   }
 }
-#endif
+
+void compute_gru(const GRULayer *gru, float *state, const float *input)
+{
+   int i;
+   int N, M;
+   int stride;
+   float tmp[MAX_NEURONS];
+   float z[MAX_NEURONS];
+   float r[MAX_NEURONS];
+   float h[MAX_NEURONS];
+   M = gru->nb_inputs;
+   N = gru->nb_neurons;
+   stride = 3*N;
+   /* Compute update gate. */
+   for (i=0;i<N;i++)
+      z[i] = gru->bias[i];
+   gemm_accum(z, gru->input_weights, N, M, stride, input);
+   gemm_accum(z, gru->recurrent_weights, N, N, stride, state);
+   for (i=0;i<N;i++)
+      z[i] = sigmoid_approx(WEIGHTS_SCALE*z[i]);
+
+   /* Compute reset gate. */
+   for (i=0;i<N;i++)
+      r[i] = gru->bias[N + i];
+   gemm_accum(r, &gru->input_weights[N], N, M, stride, input);
+   gemm_accum(r, &gru->recurrent_weights[N], N, N, stride, state);
+   for (i=0;i<N;i++)
+      r[i] = sigmoid_approx(WEIGHTS_SCALE*r[i]);
+
+   /* Compute output. */
+   for (i=0;i<N;i++)
+      h[i] = gru->bias[2*N + i];
+   for (i=0;i<N;i++)
+      tmp[i] = state[i] * r[i];
+   gemm_accum(h, &gru->input_weights[2*N], N, M, stride, input);
+   gemm_accum(h, &gru->recurrent_weights[2*N], N, N, stride, tmp);
+   for (i=0;i<N;i++)
+      h[i] = z[i]*state[i] + (1-z[i])*tansig_approx(WEIGHTS_SCALE*h[i]);
+   for (i=0;i<N;i++)
+      state[i] = h[i];
+}
+

+ 26 - 9
thirdparty/opus/mlp.h

@@ -1,5 +1,4 @@
-/* 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
@@ -28,16 +27,34 @@
 #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_ */

+ 659 - 96
thirdparty/opus/mlp_data.c

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

+ 2 - 2
thirdparty/opus/opus.c

@@ -107,7 +107,7 @@ OPUS_EXPORT void opus_pcm_soft_clip(float *_x, int N, int C, float *declip_mem)
          /* Slightly boost "a" by 2^-22. This is just enough to ensure -ffast-math
             does not cause output values larger than +/-1, but small enough not
             to matter even for 24-bit output.  */
-         a += a*2.4e-7;
+         a += a*2.4e-7f;
          if (x[i*C]>0)
             a = -a;
          /* Apply soft clipping */
@@ -252,7 +252,7 @@ int opus_packet_parse_impl(const unsigned char *data, opus_int32 len,
       /* 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 */

+ 1 - 1
thirdparty/opus/opus/opus.h

@@ -531,7 +531,7 @@ OPUS_EXPORT int opus_packet_parse(
    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

+ 49 - 3
thirdparty/opus/opus/opus_defines.h

@@ -165,8 +165,13 @@ extern "C" {
 #define OPUS_GET_EXPERT_FRAME_DURATION_REQUEST 4041
 #define OPUS_SET_PREDICTION_DISABLED_REQUEST 4042
 #define OPUS_GET_PREDICTION_DISABLED_REQUEST 4043
-
 /* Don't use 4045, it's already taken by OPUS_GET_GAIN_REQUEST */
+#define OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST 4046
+#define OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST 4047
+#define OPUS_GET_IN_DTX_REQUEST              4049
+
+/** 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))
@@ -208,6 +213,9 @@ extern "C" {
 #define OPUS_FRAMESIZE_20_MS                 5004 /**< Use 20 ms frames */
 #define OPUS_FRAMESIZE_40_MS                 5005 /**< Use 40 ms frames */
 #define OPUS_FRAMESIZE_60_MS                 5006 /**< Use 60 ms frames */
+#define OPUS_FRAMESIZE_80_MS                 5007 /**< Use 80 ms frames */
+#define OPUS_FRAMESIZE_100_MS                5008 /**< Use 100 ms frames */
+#define OPUS_FRAMESIZE_120_MS                5009 /**< Use 120 ms frames */
 
 /**@}*/
 
@@ -566,7 +574,9 @@ extern "C" {
   * <dt>OPUS_FRAMESIZE_20_MS</dt><dd>Use 20 ms frames.</dd>
   * <dt>OPUS_FRAMESIZE_40_MS</dt><dd>Use 40 ms frames.</dd>
   * <dt>OPUS_FRAMESIZE_60_MS</dt><dd>Use 60 ms frames.</dd>
-  * <dt>OPUS_FRAMESIZE_VARIABLE</dt><dd>Optimize the frame size dynamically.</dd>
+  * <dt>OPUS_FRAMESIZE_80_MS</dt><dd>Use 80 ms frames.</dd>
+  * <dt>OPUS_FRAMESIZE_100_MS</dt><dd>Use 100 ms frames.</dd>
+  * <dt>OPUS_FRAMESIZE_120_MS</dt><dd>Use 120 ms frames.</dd>
   * </dl>
   * @hideinitializer */
 #define OPUS_SET_EXPERT_FRAME_DURATION(x) OPUS_SET_EXPERT_FRAME_DURATION_REQUEST, __opus_check_int(x)
@@ -581,7 +591,9 @@ extern "C" {
   * <dt>OPUS_FRAMESIZE_20_MS</dt><dd>Use 20 ms frames.</dd>
   * <dt>OPUS_FRAMESIZE_40_MS</dt><dd>Use 40 ms frames.</dd>
   * <dt>OPUS_FRAMESIZE_60_MS</dt><dd>Use 60 ms frames.</dd>
-  * <dt>OPUS_FRAMESIZE_VARIABLE</dt><dd>Optimize the frame size dynamically.</dd>
+  * <dt>OPUS_FRAMESIZE_80_MS</dt><dd>Use 80 ms frames.</dd>
+  * <dt>OPUS_FRAMESIZE_100_MS</dt><dd>Use 100 ms frames.</dd>
+  * <dt>OPUS_FRAMESIZE_120_MS</dt><dd>Use 120 ms frames.</dd>
   * </dl>
   * @hideinitializer */
 #define OPUS_GET_EXPERT_FRAME_DURATION(x) OPUS_GET_EXPERT_FRAME_DURATION_REQUEST, __opus_check_int_ptr(x)
@@ -681,6 +693,40 @@ extern "C" {
   */
 #define OPUS_GET_SAMPLE_RATE(x) OPUS_GET_SAMPLE_RATE_REQUEST, __opus_check_int_ptr(x)
 
+/** If set to 1, disables the use of phase inversion for intensity stereo,
+  * improving the quality of mono downmixes, but slightly reducing normal
+  * stereo quality. Disabling phase inversion in the decoder does not comply
+  * with RFC 6716, although it does not cause any interoperability issue and
+  * is expected to become part of the Opus standard once RFC 6716 is updated
+  * by draft-ietf-codec-opus-update.
+  * @see OPUS_GET_PHASE_INVERSION_DISABLED
+  * @param[in] x <tt>opus_int32</tt>: Allowed values:
+  * <dl>
+  * <dt>0</dt><dd>Enable phase inversion (default).</dd>
+  * <dt>1</dt><dd>Disable phase inversion.</dd>
+  * </dl>
+  * @hideinitializer */
+#define OPUS_SET_PHASE_INVERSION_DISABLED(x) OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST, __opus_check_int(x)
+/** Gets the encoder's configured phase inversion status.
+  * @see OPUS_SET_PHASE_INVERSION_DISABLED
+  * @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
+  * <dl>
+  * <dt>0</dt><dd>Stereo phase inversion enabled (default).</dd>
+  * <dt>1</dt><dd>Stereo phase inversion disabled.</dd>
+  * </dl>
+  * @hideinitializer */
+#define OPUS_GET_PHASE_INVERSION_DISABLED(x) OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST, __opus_check_int_ptr(x)
+/** Gets the DTX state of the encoder.
+  * Returns whether the last encoded frame was either a comfort noise update
+  * during DTX or not encoded because of DTX.
+  * @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
+  * <dl>
+  * <dt>0</dt><dd>The encoder is not in DTX.</dd>
+  * <dt>1</dt><dd>The encoder is in DTX.</dd>
+  * </dl>
+  * @hideinitializer */
+#define OPUS_GET_IN_DTX(x) OPUS_GET_IN_DTX_REQUEST, __opus_check_int_ptr(x)
+
 /**@}*/
 
 /** @defgroup opus_decoderctls Decoder related CTLs

+ 2 - 2
thirdparty/opus/opus/opus_multistream.h

@@ -273,7 +273,7 @@ OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusMSEncoder *opus_multistream_surround_enc
       unsigned char *mapping,
       int application,
       int *error
-) OPUS_ARG_NONNULL(5);
+) OPUS_ARG_NONNULL(4) OPUS_ARG_NONNULL(5) OPUS_ARG_NONNULL(6);
 
 /** Initialize a previously allocated multistream encoder state.
   * The memory pointed to by \a st must be at least the size returned by
@@ -342,7 +342,7 @@ OPUS_EXPORT int opus_multistream_surround_encoder_init(
       int *coupled_streams,
       unsigned char *mapping,
       int application
-) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(6);
+) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(5) OPUS_ARG_NONNULL(6) OPUS_ARG_NONNULL(7);
 
 /** Encodes a multistream Opus frame.
   * @param st <tt>OpusMSEncoder*</tt>: Multistream encoder state.

+ 568 - 0
thirdparty/opus/opus/opus_projection.h

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

+ 17 - 10
thirdparty/opus/opus/opus_types.h

@@ -33,14 +33,29 @@
 #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__ && __STDC_VERSION__ >= 199901L) || (defined(__GNUC__) && (defined(_STDINT_H) || defined(_STDINT_H_)) || defined (HAVE_STDINT_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__)
@@ -148,12 +163,4 @@
 
 #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 */

+ 33 - 26
thirdparty/opus/opus/opusfile.h

@@ -239,7 +239,8 @@ struct OpusHead{
       -32768...32767.
      The <tt>libopusfile</tt> API will automatically apply this gain to the
       decoded output before returning it, scaling it by
-      <code>pow(10,output_gain/(20.0*256))</code>.*/
+      <code>pow(10,output_gain/(20.0*256))</code>.
+     You can adjust this behavior with op_set_gain_offset().*/
   int           output_gain;
   /**The channel mapping family, in the range 0...255.
      Channel mapping family 0 covers mono or stereo in a single stream.
@@ -1154,16 +1155,18 @@ OP_WARN_UNUSED_RESULT OggOpusFile *op_open_url(const char *_url,
  int *_error,...) OP_ARG_NONNULL(1);
 
 /**Open a stream using the given set of callbacks to access it.
-   \param _source        The stream to read from (e.g., a <code>FILE *</code>).
+   \param _stream        The stream to read from (e.g., a <code>FILE *</code>).
+                         This value will be passed verbatim as the first
+                          argument to all of the callbacks.
    \param _cb            The callbacks with which to access the stream.
                          <code><a href="#op_read_func">read()</a></code> must
                           be implemented.
                          <code><a href="#op_seek_func">seek()</a></code> and
                           <code><a href="#op_tell_func">tell()</a></code> may
                           be <code>NULL</code>, or may always return -1 to
-                          indicate a source is unseekable, but if
+                          indicate a stream is unseekable, but if
                           <code><a href="#op_seek_func">seek()</a></code> is
-                          implemented and succeeds on a particular source, then
+                          implemented and succeeds on a particular stream, then
                           <code><a href="#op_tell_func">tell()</a></code> must
                           also.
                          <code><a href="#op_close_func">close()</a></code> may
@@ -1226,11 +1229,11 @@ OP_WARN_UNUSED_RESULT OggOpusFile *op_open_url(const char *_url,
                             basic validity checks.</dd>
                          </dl>
    \return A freshly opened \c OggOpusFile, or <code>NULL</code> on error.
-           <tt>libopusfile</tt> does <em>not</em> take ownership of the source
+           <tt>libopusfile</tt> does <em>not</em> take ownership of the stream
             if the call fails.
-           The calling application is responsible for closing the source if
+           The calling application is responsible for closing the stream if
             this call returns an error.*/
-OP_WARN_UNUSED_RESULT OggOpusFile *op_open_callbacks(void *_source,
+OP_WARN_UNUSED_RESULT OggOpusFile *op_open_callbacks(void *_stream,
  const OpusFileCallbacks *_cb,const unsigned char *_initial_data,
  size_t _initial_bytes,int *_error) OP_ARG_NONNULL(2);
 
@@ -1332,18 +1335,20 @@ OP_WARN_UNUSED_RESULT OggOpusFile *op_test_url(const char *_url,
    For new code, you are likely better off using op_test() instead, which
     is less resource-intensive, requires less data to succeed, and imposes a
     hard limit on the amount of data it examines (important for unseekable
-    sources, where all such data must be buffered until you are sure of the
+    streams, where all such data must be buffered until you are sure of the
     stream type).
-   \param _source        The stream to read from (e.g., a <code>FILE *</code>).
+   \param _stream        The stream to read from (e.g., a <code>FILE *</code>).
+                         This value will be passed verbatim as the first
+                          argument to all of the callbacks.
    \param _cb            The callbacks with which to access the stream.
                          <code><a href="#op_read_func">read()</a></code> must
                           be implemented.
                          <code><a href="#op_seek_func">seek()</a></code> and
                           <code><a href="#op_tell_func">tell()</a></code> may
                           be <code>NULL</code>, or may always return -1 to
-                          indicate a source is unseekable, but if
+                          indicate a stream is unseekable, but if
                           <code><a href="#op_seek_func">seek()</a></code> is
-                          implemented and succeeds on a particular source, then
+                          implemented and succeeds on a particular stream, then
                           <code><a href="#op_tell_func">tell()</a></code> must
                           also.
                          <code><a href="#op_close_func">close()</a></code> may
@@ -1373,11 +1378,11 @@ OP_WARN_UNUSED_RESULT OggOpusFile *op_test_url(const char *_url,
                          See op_open_callbacks() for a full list of failure
                           codes.
    \return A partially opened \c OggOpusFile, or <code>NULL</code> on error.
-           <tt>libopusfile</tt> does <em>not</em> take ownership of the source
+           <tt>libopusfile</tt> does <em>not</em> take ownership of the stream
             if the call fails.
-           The calling application is responsible for closing the source if
+           The calling application is responsible for closing the stream if
             this call returns an error.*/
-OP_WARN_UNUSED_RESULT OggOpusFile *op_test_callbacks(void *_source,
+OP_WARN_UNUSED_RESULT OggOpusFile *op_test_callbacks(void *_stream,
  const OpusFileCallbacks *_cb,const unsigned char *_initial_data,
  size_t _initial_bytes,int *_error) OP_ARG_NONNULL(2);
 
@@ -1434,7 +1439,7 @@ void op_free(OggOpusFile *_of);
    Their documention will indicate so explicitly.*/
 /*@{*/
 
-/**Returns whether or not the data source being read is seekable.
+/**Returns whether or not the stream being read is seekable.
    This is true if
    <ol>
    <li>The <code><a href="#op_seek_func">seek()</a></code> and
@@ -1455,9 +1460,9 @@ int op_seekable(const OggOpusFile *_of) OP_ARG_NONNULL(1);
     return 1.
    The actual number of links is not known until the stream is fully opened.
    \param _of The \c OggOpusFile from which to retrieve the link count.
-   \return For fully-open seekable sources, this returns the total number of
+   \return For fully-open seekable streams, this returns the total number of
             links in the whole stream, which will be at least 1.
-           For partially-open or unseekable sources, this always returns 1.*/
+           For partially-open or unseekable streams, this always returns 1.*/
 int op_link_count(const OggOpusFile *_of) OP_ARG_NONNULL(1);
 
 /**Get the serial number of the given link in a (possibly-chained) Ogg Opus
@@ -1471,7 +1476,7 @@ int op_link_count(const OggOpusFile *_of) OP_ARG_NONNULL(1);
    \return The serial number of the given link.
            If \a _li is greater than the total number of links, this returns
             the serial number of the last link.
-           If the source is not seekable, this always returns the serial number
+           If the stream is not seekable, this always returns the serial number
             of the current link.*/
 opus_uint32 op_serialno(const OggOpusFile *_of,int _li) OP_ARG_NONNULL(1);
 
@@ -1488,7 +1493,7 @@ opus_uint32 op_serialno(const OggOpusFile *_of,int _li) OP_ARG_NONNULL(1);
    \return The channel count of the given link.
            If \a _li is greater than the total number of links, this returns
             the channel count of the last link.
-           If the source is not seekable, this always returns the channel count
+           If the stream is not seekable, this always returns the channel count
             of the current link.*/
 int op_channel_count(const OggOpusFile *_of,int _li) OP_ARG_NONNULL(1);
 
@@ -1507,9 +1512,9 @@ int op_channel_count(const OggOpusFile *_of,int _li) OP_ARG_NONNULL(1);
             compressed size of link \a _li if it is non-negative, or a negative
             value on error.
            The compressed size of the entire stream may be smaller than that
-            of the underlying source if trailing garbage was detected in the
+            of the underlying stream if trailing garbage was detected in the
             file.
-   \retval #OP_EINVAL The source is not seekable (so we can't know the length),
+   \retval #OP_EINVAL The stream is not seekable (so we can't know the length),
                        \a _li wasn't less than the total number of links in
                        the stream, or the stream was only partially open.*/
 opus_int64 op_raw_total(const OggOpusFile *_of,int _li) OP_ARG_NONNULL(1);
@@ -1527,7 +1532,7 @@ opus_int64 op_raw_total(const OggOpusFile *_of,int _li) OP_ARG_NONNULL(1);
    \return The PCM length of the entire stream if \a _li is negative, the PCM
             length of link \a _li if it is non-negative, or a negative value on
             error.
-   \retval #OP_EINVAL The source is not seekable (so we can't know the length),
+   \retval #OP_EINVAL The stream is not seekable (so we can't know the length),
                        \a _li wasn't less than the total number of links in
                        the stream, or the stream was only partially open.*/
 ogg_int64_t op_pcm_total(const OggOpusFile *_of,int _li) OP_ARG_NONNULL(1);
@@ -1575,8 +1580,8 @@ const OpusTags *op_tags(const OggOpusFile *_of,int _li) OP_ARG_NONNULL(1);
    \param _of The \c OggOpusFile from which to retrieve the current link index.
    \return The index of the current link on success, or a negative value on
             failure.
-           For seekable streams, this is a number between 0 and the value
-            returned by op_link_count().
+           For seekable streams, this is a number between 0 (inclusive) and the
+            value returned by op_link_count() (exclusive).
            For unseekable streams, this value starts at 0 and increments by one
             each time a new link is encountered (even though op_link_count()
             always returns 1).
@@ -1640,10 +1645,10 @@ ogg_int64_t op_pcm_tell(const OggOpusFile *_of) OP_ARG_NONNULL(1);
 /*@{*/
 /**\name Functions for seeking in Opus streams
 
-   These functions let you seek in Opus streams, if the underlying source
+   These functions let you seek in Opus streams, if the underlying stream
     support it.
    Seeking is implemented for all built-in stream I/O routines, though some
-    individual sources may not be seekable (pipes, live HTTP streams, or HTTP
+    individual streams may not be seekable (pipes, live HTTP streams, or HTTP
     streams from a server that does not support <code>Range</code> requests).
 
    op_raw_seek() is the fastest: it is guaranteed to perform at most one
@@ -1670,6 +1675,8 @@ ogg_int64_t op_pcm_tell(const OggOpusFile *_of) OP_ARG_NONNULL(1);
     packets out of the tail of the link to which it seeks.
    \param _of          The \c OggOpusFile in which to seek.
    \param _byte_offset The byte position to seek to.
+                       This must be between 0 and #op_raw_total(\a _of,\c -1)
+                        (inclusive).
    \return 0 on success, or a negative error code on failure.
    \retval #OP_EREAD    The underlying seek operation failed.
    \retval #OP_EINVAL   The stream was only partially open, or the target was

+ 3 - 0
thirdparty/opus/opus_compare.c

@@ -363,6 +363,9 @@ int main(int _argc,const char **_argv){
     Ef*=Ef;
     err+=Ef*Ef;
   }
+  free(xb);
+  free(X);
+  free(Y);
   err=pow(err/nframes,1.0/16);
   Q=100*(1-0.5*log(1+err)/log(1.13));
   if(Q<0){

+ 84 - 33
thirdparty/opus/opus_decoder.c

@@ -78,6 +78,26 @@ struct OpusDecoder {
    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)
 {
@@ -104,7 +124,7 @@ int opus_decoder_init(OpusDecoder *st, opus_int32 Fs, 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;
@@ -217,6 +237,7 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data,
 
    int audiosize;
    int mode;
+   int bandwidth;
    int transition=0;
    int start_band;
    int redundancy=0;
@@ -253,10 +274,12 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data,
    {
       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)
       {
@@ -355,15 +378,15 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data,
       {
         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 */
@@ -427,10 +450,26 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data,
    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;
@@ -445,24 +484,13 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data,
       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;
@@ -471,21 +499,21 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data,
    /* 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);
@@ -500,7 +528,7 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data,
          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);
       }
    }
@@ -518,18 +546,18 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data,
 
    {
       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);
    }
@@ -605,6 +633,7 @@ int opus_decode_native(OpusDecoder *st, const unsigned char *data,
    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 */
@@ -740,6 +769,7 @@ int opus_decode_float(OpusDecoder *st, const unsigned char *data,
       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);
@@ -777,6 +807,7 @@ int opus_decode(OpusDecoder *st, const unsigned char *data,
       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);
@@ -864,7 +895,7 @@ int opus_decoder_ctl(OpusDecoder *st, int request, ...)
          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;
    }
@@ -891,7 +922,7 @@ int opus_decoder_ctl(OpusDecoder *st, int request, ...)
    break;
    case OPUS_GET_LAST_PACKET_DURATION_REQUEST:
    {
-      opus_uint32 *value = va_arg(ap, opus_uint32*);
+      opus_int32 *value = va_arg(ap, opus_int32*);
       if (!value)
       {
          goto bad_arg;
@@ -899,6 +930,26 @@ int opus_decoder_ctl(OpusDecoder *st, int request, ...)
       *value = st->last_packet_duration;
    }
    break;
+   case OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST:
+   {
+       opus_int32 value = va_arg(ap, opus_int32);
+       if(value<0 || value>1)
+       {
+          goto bad_arg;
+       }
+       ret = celt_decoder_ctl(celt_dec, OPUS_SET_PHASE_INVERSION_DISABLED(value));
+   }
+   break;
+   case OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST:
+   {
+       opus_int32 *value = va_arg(ap, opus_int32*);
+       if (!value)
+       {
+          goto bad_arg;
+       }
+       ret = celt_decoder_ctl(celt_dec, OPUS_GET_PHASE_INVERSION_DISABLED(value));
+   }
+   break;
    default:
       /*fprintf(stderr, "unknown opus_decoder_ctl() request: %d", request);*/
       ret = OPUS_UNIMPLEMENTED;

File diff suppressed because it is too large
+ 497 - 339
thirdparty/opus/opus_encoder.c


+ 51 - 39
thirdparty/opus/opus_multistream_decoder.c

@@ -37,15 +37,18 @@
 #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)
 {
@@ -143,15 +146,6 @@ OpusMSDecoder *opus_multistream_decoder_create(
    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)
 {
@@ -181,7 +175,7 @@ static int opus_multistream_packet_validate(const unsigned char *data,
    return samples;
 }
 
-static int opus_multistream_decode_native(
+int opus_multistream_decode_native(
       OpusMSDecoder *st,
       const unsigned char *data,
       opus_int32 len,
@@ -189,7 +183,8 @@ static int opus_multistream_decode_native(
       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;
@@ -201,8 +196,14 @@ static int opus_multistream_decode_native(
    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));
@@ -237,7 +238,8 @@ static int opus_multistream_decode_native(
    for (s=0;s<st->layout.nb_streams;s++)
    {
       OpusDecoder *dec;
-      int packet_offset, ret;
+      opus_int32 packet_offset;
+      int ret;
 
       dec = (OpusDecoder*)ptr;
       ptr += (s < st->layout.nb_coupled_streams) ? align(coupled_size) : align(mono_size);
@@ -265,7 +267,7 @@ static int opus_multistream_decode_native(
          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;
@@ -273,7 +275,7 @@ static int opus_multistream_decode_native(
          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 {
@@ -283,7 +285,7 @@ static int opus_multistream_decode_native(
          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;
          }
       }
@@ -294,7 +296,7 @@ static int opus_multistream_decode_native(
       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;
@@ -308,11 +310,13 @@ static void opus_copy_channel_out_float(
   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)
    {
@@ -337,11 +341,13 @@ static void opus_copy_channel_out_short(
   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)
    {
@@ -372,7 +378,7 @@ int opus_multistream_decode(
 )
 {
    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
@@ -380,7 +386,7 @@ int opus_multistream_decode_float(OpusMSDecoder *st, const unsigned char *data,
       opus_int32 len, float *pcm, int frame_size, int decode_fec)
 {
    return opus_multistream_decode_native(st, data, len,
-       pcm, opus_copy_channel_out_float, frame_size, decode_fec, 0);
+       pcm, opus_copy_channel_out_float, frame_size, decode_fec, 0, NULL);
 }
 #endif
 
@@ -390,32 +396,30 @@ int opus_multistream_decode(OpusMSDecoder *st, const unsigned char *data,
       opus_int32 len, opus_int16 *pcm, int frame_size, int decode_fec)
 {
    return opus_multistream_decode_native(st, data, len,
-       pcm, opus_copy_channel_out_short, frame_size, decode_fec, 1);
+       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));
@@ -425,6 +429,7 @@ int opus_multistream_decoder_ctl(OpusMSDecoder *st, int request, ...)
        case OPUS_GET_SAMPLE_RATE_REQUEST:
        case OPUS_GET_GAIN_REQUEST:
        case OPUS_GET_LAST_PACKET_DURATION_REQUEST:
+       case OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST:
        {
           OpusDecoder *dec;
           /* For int32* GET params, just query the first stream */
@@ -482,7 +487,7 @@ int opus_multistream_decoder_ctl(OpusMSDecoder *st, int request, ...)
           OpusDecoder **value;
           stream_id = va_arg(ap, opus_int32);
           if (stream_id<0 || stream_id >= st->layout.nb_streams)
-             ret = OPUS_BAD_ARG;
+             goto bad_arg;
           value = va_arg(ap, OpusDecoder**);
           if (!value)
           {
@@ -499,6 +504,7 @@ int opus_multistream_decoder_ctl(OpusMSDecoder *st, int request, ...)
        }
        break;
        case OPUS_SET_GAIN_REQUEST:
+       case OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST:
        {
           int s;
           /* This works for int32 params */
@@ -522,14 +528,20 @@ int opus_multistream_decoder_ctl(OpusMSDecoder *st, int request, ...)
           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)
 {

+ 164 - 187
thirdparty/opus/opus_multistream_encoder.c

@@ -61,38 +61,6 @@ static const VorbisLayout vorbis_mappings[8] = {
       {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;
-   float subframe_mem[3];
-   /* 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;
@@ -133,6 +101,29 @@ static opus_val32 *ms_get_window_mem(OpusMSEncoder *st)
    return (opus_val32*)(void*)ptr;
 }
 
+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 (nondiegetic_channels != 0 && nondiegetic_channels != 2)
+      return 0;
+
+   if (nb_streams)
+      *nb_streams = acn_channels + (nondiegetic_channels != 0);
+   if (nb_coupled_streams)
+      *nb_coupled_streams = nondiegetic_channels != 0;
+   return 1;
+}
+
 static int validate_encoder_layout(const ChannelLayout *layout)
 {
    int s;
@@ -240,6 +231,7 @@ void surround_analysis(const CELTMode *celt_mode, const void *pcm, opus_val16 *b
    int pos[8] = {0};
    int upsample;
    int frame_size;
+   int freq_size;
    opus_val16 channel_offset;
    opus_val32 bandE[21];
    opus_val16 maskLogE[3][21];
@@ -250,6 +242,7 @@ void surround_analysis(const CELTMode *celt_mode, const void *pcm, opus_val16 *b
 
    upsample = resampling_factor(rate);
    frame_size = len*upsample;
+   freq_size = IMIN(960, frame_size);
 
    /* LM = log2(frame_size / 120) */
    for (LM=0;LM<celt_mode->maxLM;LM++)
@@ -258,7 +251,7 @@ void surround_analysis(const CELTMode *celt_mode, const void *pcm, opus_val16 *b
 
    ALLOC(in, frame_size+overlap, opus_val32);
    ALLOC(x, len, opus_val16);
-   ALLOC(freq, frame_size, opus_val32);
+   ALLOC(freq, freq_size, opus_val32);
 
    channel_pos(channels, pos);
 
@@ -268,8 +261,11 @@ void surround_analysis(const CELTMode *celt_mode, const void *pcm, opus_val16 *b
 
    for (c=0;c<channels;c++)
    {
+      int frame;
+      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
       {
@@ -284,18 +280,26 @@ void surround_analysis(const CELTMode *celt_mode, const void *pcm, opus_val16 *b
          }
       }
 #endif
-      clt_mdct_forward(&celt_mode->mdct, in, freq, celt_mode->window,
-            overlap, celt_mode->maxLM-LM, 1, arch);
-      if (upsample != 1)
+      OPUS_CLEAR(bandE, 21);
+      for (frame=0;frame<nb_frames;frame++)
       {
-         int bound = len;
-         for (i=0;i<bound;i++)
-            freq[i] *= upsample;
-         for (;i<frame_size;i++)
-            freq[i] = 0;
-      }
+         opus_val32 tmpE[21];
+         clt_mdct_forward(&celt_mode->mdct, in+960*frame, freq, celt_mode->window,
+               overlap, celt_mode->maxLM-LM, 1, arch);
+         if (upsample != 1)
+         {
+            int bound = freq_size/upsample;
+            for (i=0;i<bound;i++)
+               freq[i] *= upsample;
+            for (;i<freq_size;i++)
+               freq[i] = 0;
+         }
 
-      compute_band_energies(celt_mode, freq, bandE, 21, 1, LM);
+         compute_band_energies(celt_mode, freq, tmpE, 21, 1, LM, arch);
+         /* If we have multiple frames, take the max energy. */
+         for (i=0;i<21;i++)
+            bandE[i] = MAX32(bandE[i], tmpE[i]);
+      }
       amp2Log2(celt_mode, 21, 21, bandE, bandLogE+21*c, 1);
       /* Apply spreading function with -6 dB/band going up and -12 dB/band going down. */
       for (i=1;i<21;i++)
@@ -408,12 +412,10 @@ opus_int32 opus_multistream_surround_encoder_get_size(int channels, int mapping_
    {
       nb_streams=channels;
       nb_coupled_streams=0;
-#ifdef ENABLE_EXPERIMENTAL_AMBISONICS
-   } else if (mapping_family==254)
+   } else if (mapping_family==2)
    {
-      nb_streams=channels;
-      nb_coupled_streams=0;
-#endif
+      if (!validate_ambisonics(channels, &nb_streams, &nb_coupled_streams))
+         return 0;
    } else
       return 0;
    size = opus_multistream_encoder_get_size(nb_streams, nb_coupled_streams);
@@ -448,7 +450,6 @@ static int opus_multistream_encoder_init_impl(
    st->layout.nb_channels = channels;
    st->layout.nb_streams = streams;
    st->layout.nb_coupled_streams = coupled_streams;
-   st->subframe_mem[0]=st->subframe_mem[1]=st->subframe_mem[2]=0;
    if (mapping_type != MAPPING_TYPE_SURROUND)
       st->lfe_stream = -1;
    st->bitrate_bps = OPUS_AUTO;
@@ -456,7 +457,13 @@ static int opus_multistream_encoder_init_impl(
    st->variable_duration = OPUS_FRAMESIZE_ARG;
    for (i=0;i<st->layout.nb_channels;i++)
       st->layout.mapping[i] = mapping[i];
-   if (!validate_layout(&st->layout) || !validate_encoder_layout(&st->layout))
+   if (!validate_layout(&st->layout))
+      return OPUS_BAD_ARG;
+   if (mapping_type == MAPPING_TYPE_SURROUND &&
+       !validate_encoder_layout(&st->layout))
+      return OPUS_BAD_ARG;
+   if (mapping_type == MAPPING_TYPE_AMBISONICS &&
+       !validate_ambisonics(st->layout.nb_channels, NULL, NULL))
       return OPUS_BAD_ARG;
    ptr = (char*)st + align(sizeof(OpusMSEncoder));
    coupled_size = opus_encoder_get_size(2);
@@ -549,25 +556,23 @@ int opus_multistream_surround_encoder_init(
       *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;
-      *streams=channels;
-      *coupled_streams=0;
-      for(i=0;i<channels;i++)
-         mapping[i] = i;
-#endif
+      if (!validate_ambisonics(channels, streams, coupled_streams))
+         return OPUS_BAD_ARG;
+      for(i = 0; i < (*streams - *coupled_streams); i++)
+         mapping[i] = i + (*coupled_streams * 2);
+      for(i = 0; i < *coupled_streams * 2; i++)
+         mapping[i + (*streams - *coupled_streams)] = i;
    } 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;
@@ -672,62 +677,62 @@ static void surround_rate_allocation(
    int lfe_offset;
    int coupled_ratio; /* Q8 */
    int lfe_ratio;     /* Q8 */
+   int nb_lfe;
+   int nb_uncoupled;
+   int nb_coupled;
+   int nb_normal;
+   opus_int32 channel_offset;
+   opus_int32 bitrate;
+   int total;
+
+   nb_lfe = (st->lfe_stream!=-1);
+   nb_coupled = st->layout.nb_coupled_streams;
+   nb_uncoupled = st->layout.nb_streams-nb_coupled-nb_lfe;
+   nb_normal = 2*nb_coupled + nb_uncoupled;
+
+   /* Give each non-LFE channel enough bits per channel for coding band energy. */
+   channel_offset = 40*IMAX(50, Fs/frame_size);
 
-   if (st->bitrate_bps > st->layout.nb_channels*40000)
-      stream_offset = 20000;
-   else
-      stream_offset = st->bitrate_bps/st->layout.nb_channels/2;
-   stream_offset += 60*(Fs/frame_size-50);
-   /* We start by giving each stream (coupled or uncoupled) the same bitrate.
-      This models the main saving of coupled channels over uncoupled. */
-   /* The LFE stream is an exception to the above and gets fewer bits. */
-   lfe_offset = 3500 + 60*(Fs/frame_size-50);
-   /* Coupled streams get twice the mono rate after the first 20 kb/s. */
-   coupled_ratio = 512;
-   /* Should depend on the bitrate, for now we assume LFE gets 1/8 the bits of mono */
-   lfe_ratio = 32;
-
-   /* Compute bitrate allocation between streams */
    if (st->bitrate_bps==OPUS_AUTO)
    {
-      channel_rate = Fs+60*Fs/frame_size;
+      bitrate = nb_normal*(channel_offset + Fs + 10000) + 8000*nb_lfe;
    } else if (st->bitrate_bps==OPUS_BITRATE_MAX)
    {
-      channel_rate = 300000;
+      bitrate = nb_normal*300000 + nb_lfe*128000;
    } else {
-      int nb_lfe;
-      int nb_uncoupled;
-      int nb_coupled;
-      int total;
-      nb_lfe = (st->lfe_stream!=-1);
-      nb_coupled = st->layout.nb_coupled_streams;
-      nb_uncoupled = st->layout.nb_streams-nb_coupled-nb_lfe;
-      total = (nb_uncoupled<<8)         /* mono */
-            + coupled_ratio*nb_coupled /* stereo */
-            + nb_lfe*lfe_ratio;
-      channel_rate = 256*(st->bitrate_bps-lfe_offset*nb_lfe-stream_offset*(nb_coupled+nb_uncoupled))/total;
+      bitrate = st->bitrate_bps;
    }
-#ifndef FIXED_POINT
-   if (st->variable_duration==OPUS_FRAMESIZE_VARIABLE && frame_size != Fs/50)
-   {
-      opus_int32 bonus;
-      bonus = 60*(Fs/frame_size-50);
-      channel_rate += bonus;
-   }
-#endif
+
+   /* Give LFE some basic stream_channel allocation but never exceed 1/20 of the
+      total rate for the non-energy part to avoid problems at really low rate. */
+   lfe_offset = IMIN(bitrate/20, 3000) + 15*IMAX(50, Fs/frame_size);
+
+   /* We give each stream (coupled or uncoupled) a starting bitrate.
+      This models the main saving of coupled channels over uncoupled. */
+   stream_offset = (bitrate - channel_offset*nb_normal - lfe_offset*nb_lfe)/nb_normal/2;
+   stream_offset = IMAX(0, IMIN(20000, stream_offset));
+
+   /* Coupled streams get twice the mono rate after the offset is allocated. */
+   coupled_ratio = 512;
+   /* Should depend on the bitrate, for now we assume LFE gets 1/8 the bits of mono */
+   lfe_ratio = 32;
+
+   total = (nb_uncoupled<<8)         /* mono */
+         + coupled_ratio*nb_coupled /* stereo */
+         + nb_lfe*lfe_ratio;
+   channel_rate = 256*(opus_int64)(bitrate - lfe_offset*nb_lfe - stream_offset*(nb_coupled+nb_uncoupled) - channel_offset*nb_normal)/total;
 
    for (i=0;i<st->layout.nb_streams;i++)
    {
       if (i<st->layout.nb_coupled_streams)
-         rate[i] = stream_offset+(channel_rate*coupled_ratio>>8);
+         rate[i] = 2*channel_offset + IMAX(0, stream_offset+(channel_rate*coupled_ratio>>8));
       else if (i!=st->lfe_stream)
-         rate[i] = stream_offset+channel_rate;
+         rate[i] = channel_offset + IMAX(0, stream_offset + channel_rate);
       else
-         rate[i] = lfe_offset+(channel_rate*lfe_ratio>>8);
+         rate[i] = IMAX(0, lfe_offset+(channel_rate*lfe_ratio>>8));
    }
 }
 
-#ifdef ENABLE_EXPERIMENTAL_AMBISONICS
 static void ambisonics_rate_allocation(
       OpusMSEncoder *st,
       opus_int32 *rate,
@@ -736,50 +741,31 @@ static void ambisonics_rate_allocation(
       )
 {
    int i;
-   int non_mono_rate;
-   int total_rate;
+   opus_int32 total_rate;
+   opus_int32 per_stream_rate;
 
-   /* The mono channel gets (rate_ratio_num / rate_ratio_den) times as many bits
-    * as all other channels */
-   const int rate_ratio_num = 4;
-   const int rate_ratio_den = 3;
-   const int num_channels = st->layout.nb_streams;
+   const int nb_channels = st->layout.nb_streams + st->layout.nb_coupled_streams;
 
    if (st->bitrate_bps==OPUS_AUTO)
    {
-      total_rate = num_channels * (20000 + st->layout.nb_streams*(Fs+60*Fs/frame_size));
+      total_rate = (st->layout.nb_coupled_streams + st->layout.nb_streams) *
+         (Fs+60*Fs/frame_size) + st->layout.nb_streams * (opus_int32)15000;
    } else if (st->bitrate_bps==OPUS_BITRATE_MAX)
    {
-      total_rate = num_channels * 320000;
-   } else {
-      total_rate = st->bitrate_bps;
-   }
-
-   /* Let y be the non-mono rate and let p, q be integers such that the mono
-    * channel rate is (p/q) * y.
-    * Also let T be the total bitrate to allocate. Then
-    *   (n - 1) y + (p/q) y = T
-    *   y = (T q) / (qn - q + p)
-    */
-   non_mono_rate =
-         total_rate * rate_ratio_den
-         / (rate_ratio_den*num_channels + rate_ratio_num - rate_ratio_den);
-
-#ifndef FIXED_POINT
-   if (st->variable_duration==OPUS_FRAMESIZE_VARIABLE && frame_size != Fs/50)
+      total_rate = nb_channels * 320000;
+   } else
    {
-      opus_int32 bonus = 60*(Fs/frame_size-50);
-      non_mono_rate += bonus;
+      total_rate = st->bitrate_bps;
    }
-#endif
 
-   rate[0] = total_rate - (num_channels - 1) * non_mono_rate;
-   for (i=1;i<st->layout.nb_streams;i++)
+   /* 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++)
    {
-      rate[i] = non_mono_rate;
+     rate[i] = per_stream_rate;
    }
 }
-#endif /* ENABLE_EXPERIMENTAL_AMBISONICS */
 
 static opus_int32 rate_allocation(
       OpusMSEncoder *st,
@@ -795,11 +781,9 @@ static opus_int32 rate_allocation(
    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);
    }
@@ -812,9 +796,9 @@ static opus_int32 rate_allocation(
    return rate_sum;
 }
 
-/* Max size in case the encoder decides to return three frames */
-#define MS_FRAME_TMP (3*1275+7)
-static int opus_multistream_encode_native
+/* Max size in case the encoder decides to return six frames (6 x 20 ms = 120 ms) */
+#define MS_FRAME_TMP (6*1275+12)
+int opus_multistream_encode_native
 (
     OpusMSEncoder *st,
     opus_copy_channel_in_func copy_channel_in,
@@ -824,7 +808,8 @@ static int opus_multistream_encode_native
     opus_int32 max_data_bytes,
     int lsb_depth,
     downmix_func downmix,
-    int float_api
+    int float_api,
+    void *user_data
 )
 {
    opus_int32 Fs;
@@ -859,32 +844,8 @@ static int opus_multistream_encode_native
    opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_VBR(&vbr));
    opus_encoder_ctl((OpusEncoder*)ptr, CELT_GET_MODE(&celt_mode));
 
-   {
-      opus_int32 delay_compensation;
-      int channels;
-
-      channels = st->layout.nb_streams + st->layout.nb_coupled_streams;
-      opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_LOOKAHEAD(&delay_compensation));
-      delay_compensation -= Fs/400;
-      frame_size = compute_frame_size(pcm, analysis_frame_size,
-            st->variable_duration, channels, Fs, st->bitrate_bps,
-            delay_compensation, downmix
-#ifndef DISABLE_FLOAT_API
-            , st->subframe_mem
-#endif
-            );
-   }
-
-   if (400*frame_size < Fs)
-   {
-      RESTORE_STACK;
-      return OPUS_BAD_ARG;
-   }
-   /* Validate frame_size before using it to allocate stack space.
-      This mirrors the checks in opus_encode[_float](). */
-   if (400*frame_size != Fs && 200*frame_size != Fs &&
-       100*frame_size != Fs &&  50*frame_size != Fs &&
-        25*frame_size != Fs &&  50*frame_size != 3*Fs)
+   frame_size = frame_size_select(analysis_frame_size, st->variable_duration, Fs);
+   if (frame_size <= 0)
    {
       RESTORE_STACK;
       return OPUS_BAD_ARG;
@@ -892,6 +853,9 @@ static int opus_multistream_encode_native
 
    /* Smallest packet the encoder can produce. */
    smallest_packet = st->layout.nb_streams*2-1;
+   /* 100 ms needs an extra byte per stream for the ToC. */
+   if (Fs/frame_size == 10)
+     smallest_packet += st->layout.nb_streams;
    if (max_data_bytes < smallest_packet)
    {
       RESTORE_STACK;
@@ -952,11 +916,9 @@ static int opus_multistream_encode_native
             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));
@@ -979,9 +941,9 @@ static int opus_multistream_encode_native
          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)
          {
@@ -997,7 +959,7 @@ static int opus_multistream_encode_native
          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)
          {
@@ -1013,6 +975,9 @@ static int opus_multistream_encode_native
       curr_max = max_data_bytes - tot_size;
       /* Reserve one byte for the last stream and two for the others */
       curr_max -= IMAX(0,2*(st->layout.nb_streams-s-1)-1);
+      /* For 100 ms, reserve an extra byte per stream for the ToC */
+      if (Fs/frame_size == 10)
+        curr_max -= st->layout.nb_streams-s-1;
       curr_max = IMIN(curr_max,MS_FRAME_TMP);
       /* Repacketizer will add one or two bytes for self-delimited frames */
       if (s != st->layout.nb_streams-1) curr_max -=  curr_max>253 ? 2 : 1;
@@ -1053,11 +1018,13 @@ static void opus_copy_channel_in_float(
   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)
@@ -1074,11 +1041,13 @@ static void opus_copy_channel_in_short(
   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)
@@ -1099,7 +1068,7 @@ 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);
 }
 
 #ifndef DISABLE_FLOAT_API
@@ -1112,7 +1081,7 @@ int opus_multistream_encode_float(
 )
 {
    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
 
@@ -1128,7 +1097,7 @@ int opus_multistream_encode_float
 )
 {
    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(
@@ -1140,19 +1109,17 @@ 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));
@@ -1161,9 +1128,11 @@ int opus_multistream_encoder_ctl(OpusMSEncoder *st, int request, ...)
    case OPUS_SET_BITRATE_REQUEST:
    {
       opus_int32 value = va_arg(ap, opus_int32);
-      if (value<0 && value!=OPUS_AUTO && value!=OPUS_BITRATE_MAX)
+      if (value != OPUS_AUTO && value != OPUS_BITRATE_MAX)
       {
-         goto bad_arg;
+         if (value <= 0)
+            goto bad_arg;
+         value = IMIN(300000*st->layout.nb_channels, IMAX(500*st->layout.nb_channels, value));
       }
       st->bitrate_bps = value;
    }
@@ -1206,6 +1175,7 @@ int opus_multistream_encoder_ctl(OpusMSEncoder *st, int request, ...)
    case OPUS_GET_INBAND_FEC_REQUEST:
    case OPUS_GET_FORCE_CHANNELS_REQUEST:
    case OPUS_GET_PREDICTION_DISABLED_REQUEST:
+   case OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST:
    {
       OpusEncoder *enc;
       /* For int32* GET params, just query the first stream */
@@ -1252,6 +1222,7 @@ int opus_multistream_encoder_ctl(OpusMSEncoder *st, int request, ...)
    case OPUS_SET_FORCE_MODE_REQUEST:
    case OPUS_SET_FORCE_CHANNELS_REQUEST:
    case OPUS_SET_PREDICTION_DISABLED_REQUEST:
+   case OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST:
    {
       int s;
       /* This works for int32 params */
@@ -1278,7 +1249,7 @@ int opus_multistream_encoder_ctl(OpusMSEncoder *st, int request, ...)
       OpusEncoder **value;
       stream_id = va_arg(ap, opus_int32);
       if (stream_id<0 || stream_id >= st->layout.nb_streams)
-         ret = OPUS_BAD_ARG;
+         goto bad_arg;
       value = va_arg(ap, OpusEncoder**);
       if (!value)
       {
@@ -1313,7 +1284,6 @@ int opus_multistream_encoder_ctl(OpusMSEncoder *st, int request, ...)
    case OPUS_RESET_STATE:
    {
       int s;
-      st->subframe_mem[0] = st->subframe_mem[1] = st->subframe_mem[2] = 0;
       if (st->mapping_type == MAPPING_TYPE_SURROUND)
       {
          OPUS_CLEAR(ms_get_preemph_mem(st), st->layout.nb_channels);
@@ -1337,14 +1307,21 @@ int opus_multistream_encoder_ctl(OpusMSEncoder *st, int request, ...)
       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);

+ 76 - 9
thirdparty/opus/opus_private.h

@@ -33,6 +33,7 @@
 #include "opus.h"
 #include "celt.h"
 
+#include <stdarg.h> /* va_list */
 #include <stddef.h> /* offsetof */
 
 struct OpusRepacketizer {
@@ -50,12 +51,59 @@ typedef struct ChannelLayout {
    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
@@ -87,19 +135,12 @@ int get_mono_channel(const ChannelLayout *layout, int stream_id, int prev);
 typedef void (*downmix_func)(const void *, opus_val32 *, int, int, int, int, int);
 void downmix_float(const void *_x, opus_val32 *sub, int subframe, int offset, int c1, int c2, int C);
 void downmix_int(const void *_x, opus_val32 *sub, int subframe, int offset, int c1, int c2, int C);
+int is_digital_silence(const opus_val16* pcm, int frame_size, int channels, int lsb_depth);
 
 int encode_size(int size, unsigned char *data);
 
 opus_int32 frame_size_select(opus_int32 frame_size, int variable_duration, opus_int32 Fs);
 
-opus_int32 compute_frame_size(const void *analysis_pcm, int frame_size,
-      int variable_duration, int C, opus_int32 Fs, int bitrate_bps,
-      int delay_compensation, downmix_func downmix
-#ifndef DISABLE_FLOAT_API
-      , float *subframe_mem
-#endif
-      );
-
 opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_size,
       unsigned char *data, opus_int32 out_data_bytes, int lsb_depth,
       const void *analysis_pcm, opus_int32 analysis_size, int c1, int c2,
@@ -131,4 +172,30 @@ opus_int32 opus_repacketizer_out_range_impl(OpusRepacketizer *rp, int begin, int
 
 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 */

+ 258 - 0
thirdparty/opus/opus_projection_decoder.c

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

+ 468 - 0
thirdparty/opus/opus_projection_encoder.c

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

+ 162 - 102
thirdparty/opus/opusfile.c

@@ -86,14 +86,15 @@ int op_test(OpusHead *_head,
     This is to prevent us spending a lot of time allocating memory and looking
      for Ogg pages in non-Ogg files.*/
   if(memcmp(_initial_data,"OggS",4)!=0)return OP_ENOTFORMAT;
+  if(OP_UNLIKELY(_initial_bytes>(size_t)LONG_MAX))return OP_EFAULT;
   ogg_sync_init(&oy);
-  data=ogg_sync_buffer(&oy,_initial_bytes);
+  data=ogg_sync_buffer(&oy,(long)_initial_bytes);
   if(data!=NULL){
     ogg_stream_state os;
     ogg_page         og;
     int              ret;
     memcpy(data,_initial_data,_initial_bytes);
-    ogg_sync_wrote(&oy,_initial_bytes);
+    ogg_sync_wrote(&oy,(long)_initial_bytes);
     ogg_stream_init(&os,-1);
     err=OP_FALSE;
     do{
@@ -147,7 +148,7 @@ static int op_get_data(OggOpusFile *_of,int _nbytes){
   int            nbytes;
   OP_ASSERT(_nbytes>0);
   buffer=(unsigned char *)ogg_sync_buffer(&_of->oy,_nbytes);
-  nbytes=(int)(*_of->callbacks.read)(_of->source,buffer,_nbytes);
+  nbytes=(int)(*_of->callbacks.read)(_of->stream,buffer,_nbytes);
   OP_ASSERT(nbytes<=_nbytes);
   if(OP_LIKELY(nbytes>0))ogg_sync_wrote(&_of->oy,nbytes);
   return nbytes;
@@ -157,7 +158,7 @@ static int op_get_data(OggOpusFile *_of,int _nbytes){
 static int op_seek_helper(OggOpusFile *_of,opus_int64 _offset){
   if(_offset==_of->offset)return 0;
   if(_of->callbacks.seek==NULL
-   ||(*_of->callbacks.seek)(_of->source,_offset,SEEK_SET)){
+   ||(*_of->callbacks.seek)(_of->stream,_offset,SEEK_SET)){
     return OP_EREAD;
   }
   _of->offset=_offset;
@@ -165,7 +166,7 @@ static int op_seek_helper(OggOpusFile *_of,opus_int64 _offset){
   return 0;
 }
 
-/*Get the current position indicator of the underlying source.
+/*Get the current position indicator of the underlying stream.
   This should be the same as the value reported by tell().*/
 static opus_int64 op_position(const OggOpusFile *_of){
   /*The current position indicator is _not_ simply offset.
@@ -369,7 +370,7 @@ static int op_get_prev_page_serial(OggOpusFile *_of,OpusSeekRecord *_sr,
       search_start=llret+1;
     }
     /*We started from the beginning of the stream and found nothing.
-      This should be impossible unless the contents of the source changed out
+      This should be impossible unless the contents of the stream changed out
        from under us after we read from it.*/
     if(OP_UNLIKELY(!begin)&&OP_UNLIKELY(_offset<0))return OP_EBADLINK;
     /*Bump up the chunk size.
@@ -455,7 +456,7 @@ static opus_int64 op_get_last_page(OggOpusFile *_of,ogg_int64_t *_gp,
       }
     }
     /*We started from at or before the beginning of the link and found nothing.
-      This should be impossible unless the contents of the source changed out
+      This should be impossible unless the contents of the stream changed out
        from under us after we read from it.*/
     if((OP_UNLIKELY(left_link)||OP_UNLIKELY(!begin))&&OP_UNLIKELY(_offset<0)){
       return OP_EBADLINK;
@@ -855,6 +856,7 @@ static int op_find_initial_pcm_offset(OggOpusFile *_of,
       /*Fail if the pre-skip is non-zero, since it's asking us to skip more
          samples than exist.*/
       if(_link->head.pre_skip>0)return OP_EBADTIMESTAMP;
+      _link->pcm_file_offset=0;
       /*Set pcm_end and end_offset so we can skip the call to
          op_find_final_pcm_offset().*/
       _link->pcm_start=_link->pcm_end=0;
@@ -866,7 +868,8 @@ static int op_find_initial_pcm_offset(OggOpusFile *_of,
       if(_link->head.pre_skip>0)return OP_EBADTIMESTAMP;
       /*Set pcm_end and end_offset so we can skip the call to
          op_find_final_pcm_offset().*/
-      _link->pcm_end=_link->pcm_start=0;
+      _link->pcm_file_offset=0;
+      _link->pcm_start=_link->pcm_end=0;
       _link->end_offset=_link->data_offset;
       /*Tell the caller we've got a buffered page for them.*/
       return 1;
@@ -951,6 +954,7 @@ static int op_find_initial_pcm_offset(OggOpusFile *_of,
   /*Update the packet count after end-trimming.*/
   _of->op_count=pi;
   _of->cur_discard_count=_link->head.pre_skip;
+  _link->pcm_file_offset=0;
   _of->prev_packet_gp=_link->pcm_start=pcm_start;
   _of->prev_page_offset=page_offset;
   return 0;
@@ -1271,6 +1275,7 @@ static int op_bisect_forward_serialno(OggOpusFile *_of,
        always starts with a seek.*/
     ret=op_find_initial_pcm_offset(_of,links+nlinks,NULL);
     if(OP_UNLIKELY(ret<0))return ret;
+    links[nlinks].pcm_file_offset=total_duration;
     _searched=_of->offset;
     /*Mark the current link count so it can be cleaned up on error.*/
     _of->nlinks=++nlinks;
@@ -1390,8 +1395,8 @@ static int op_open_seekable2_impl(OggOpusFile *_of){
   opus_int64     data_offset;
   int            ret;
   /*We can seek, so set out learning all about this file.*/
-  (*_of->callbacks.seek)(_of->source,0,SEEK_END);
-  _of->offset=_of->end=(*_of->callbacks.tell)(_of->source);
+  (*_of->callbacks.seek)(_of->stream,0,SEEK_END);
+  _of->offset=_of->end=(*_of->callbacks.tell)(_of->stream);
   if(OP_UNLIKELY(_of->end<0))return OP_EREAD;
   data_offset=_of->links[0].data_offset;
   if(OP_UNLIKELY(_of->end<data_offset))return OP_EBADLINK;
@@ -1436,7 +1441,7 @@ static int op_open_seekable2(OggOpusFile *_of){
   prev_page_offset=_of->prev_page_offset;
   start_offset=_of->offset;
   memcpy(op_start,_of->op,sizeof(*op_start)*start_op_count);
-  OP_ASSERT((*_of->callbacks.tell)(_of->source)==op_position(_of));
+  OP_ASSERT((*_of->callbacks.tell)(_of->stream)==op_position(_of));
   ogg_sync_init(&_of->oy);
   ogg_stream_init(&_of->os,-1);
   ret=op_open_seekable2_impl(_of);
@@ -1454,7 +1459,7 @@ static int op_open_seekable2(OggOpusFile *_of){
   _of->cur_discard_count=_of->links[0].head.pre_skip;
   if(OP_UNLIKELY(ret<0))return ret;
   /*And restore the position indicator.*/
-  ret=(*_of->callbacks.seek)(_of->source,op_position(_of),SEEK_SET);
+  ret=(*_of->callbacks.seek)(_of->stream,op_position(_of),SEEK_SET);
   return OP_UNLIKELY(ret<0)?OP_EREAD:0;
 }
 
@@ -1493,19 +1498,20 @@ static void op_clear(OggOpusFile *_of){
   _ogg_free(_of->serialnos);
   ogg_stream_clear(&_of->os);
   ogg_sync_clear(&_of->oy);
-  if(_of->callbacks.close!=NULL)(*_of->callbacks.close)(_of->source);
+  if(_of->callbacks.close!=NULL)(*_of->callbacks.close)(_of->stream);
 }
 
 static int op_open1(OggOpusFile *_of,
- void *_source,const OpusFileCallbacks *_cb,
+ void *_stream,const OpusFileCallbacks *_cb,
  const unsigned char *_initial_data,size_t _initial_bytes){
   ogg_page  og;
   ogg_page *pog;
   int       seekable;
   int       ret;
   memset(_of,0,sizeof(*_of));
+  if(OP_UNLIKELY(_initial_bytes>(size_t)LONG_MAX))return OP_EFAULT;
   _of->end=-1;
-  _of->source=_source;
+  _of->stream=_stream;
   *&_of->callbacks=*_cb;
   /*At a minimum, we need to be able to read data.*/
   if(OP_UNLIKELY(_of->callbacks.read==NULL))return OP_EREAD;
@@ -1520,18 +1526,18 @@ static int op_open1(OggOpusFile *_of,
      decoding entire files from RAM.*/
   if(_initial_bytes>0){
     char *buffer;
-    buffer=ogg_sync_buffer(&_of->oy,_initial_bytes);
+    buffer=ogg_sync_buffer(&_of->oy,(long)_initial_bytes);
     memcpy(buffer,_initial_data,_initial_bytes*sizeof(*buffer));
-    ogg_sync_wrote(&_of->oy,_initial_bytes);
+    ogg_sync_wrote(&_of->oy,(long)_initial_bytes);
   }
   /*Can we seek?
     Stevens suggests the seek test is portable.*/
-  seekable=_cb->seek!=NULL&&(*_cb->seek)(_source,0,SEEK_CUR)!=-1;
+  seekable=_cb->seek!=NULL&&(*_cb->seek)(_stream,0,SEEK_CUR)!=-1;
   /*If seek is implemented, tell must also be implemented.*/
   if(seekable){
     opus_int64 pos;
     if(OP_UNLIKELY(_of->callbacks.tell==NULL))return OP_EINVAL;
-    pos=(*_of->callbacks.tell)(_of->source);
+    pos=(*_of->callbacks.tell)(_of->stream);
     /*If the current position is not equal to the initial bytes consumed,
        absolute seeking will not work.*/
     if(OP_UNLIKELY(pos!=(opus_int64)_initial_bytes))return OP_EINVAL;
@@ -1590,14 +1596,14 @@ static int op_open2(OggOpusFile *_of){
   return ret;
 }
 
-OggOpusFile *op_test_callbacks(void *_source,const OpusFileCallbacks *_cb,
+OggOpusFile *op_test_callbacks(void *_stream,const OpusFileCallbacks *_cb,
  const unsigned char *_initial_data,size_t _initial_bytes,int *_error){
   OggOpusFile *of;
   int          ret;
   of=(OggOpusFile *)_ogg_malloc(sizeof(*of));
   ret=OP_EFAULT;
   if(OP_LIKELY(of!=NULL)){
-    ret=op_open1(of,_source,_cb,_initial_data,_initial_bytes);
+    ret=op_open1(of,_stream,_cb,_initial_data,_initial_bytes);
     if(OP_LIKELY(ret>=0)){
       if(_error!=NULL)*_error=0;
       return of;
@@ -1611,10 +1617,10 @@ OggOpusFile *op_test_callbacks(void *_source,const OpusFileCallbacks *_cb,
   return NULL;
 }
 
-OggOpusFile *op_open_callbacks(void *_source,const OpusFileCallbacks *_cb,
+OggOpusFile *op_open_callbacks(void *_stream,const OpusFileCallbacks *_cb,
  const unsigned char *_initial_data,size_t _initial_bytes,int *_error){
   OggOpusFile *of;
-  of=op_test_callbacks(_source,_cb,_initial_data,_initial_bytes,_error);
+  of=op_test_callbacks(_stream,_cb,_initial_data,_initial_bytes,_error);
   if(OP_LIKELY(of!=NULL)){
     int ret;
     ret=op_open2(of);
@@ -1627,15 +1633,15 @@ OggOpusFile *op_open_callbacks(void *_source,const OpusFileCallbacks *_cb,
 
 /*Convenience routine to clean up from failure for the open functions that
    create their own streams.*/
-static OggOpusFile *op_open_close_on_failure(void *_source,
+static OggOpusFile *op_open_close_on_failure(void *_stream,
  const OpusFileCallbacks *_cb,int *_error){
   OggOpusFile *of;
-  if(OP_UNLIKELY(_source==NULL)){
+  if(OP_UNLIKELY(_stream==NULL)){
     if(_error!=NULL)*_error=OP_EFAULT;
     return NULL;
   }
-  of=op_open_callbacks(_source,_cb,NULL,0,_error);
-  if(OP_UNLIKELY(of==NULL))(*_cb->close)(_source);
+  of=op_open_callbacks(_stream,_cb,NULL,0,_error);
+  if(OP_UNLIKELY(of==NULL))(*_cb->close)(_stream);
   return of;
 }
 
@@ -1653,15 +1659,15 @@ OggOpusFile *op_open_memory(const unsigned char *_data,size_t _size,
 
 /*Convenience routine to clean up from failure for the open functions that
    create their own streams.*/
-static OggOpusFile *op_test_close_on_failure(void *_source,
+static OggOpusFile *op_test_close_on_failure(void *_stream,
  const OpusFileCallbacks *_cb,int *_error){
   OggOpusFile *of;
-  if(OP_UNLIKELY(_source==NULL)){
+  if(OP_UNLIKELY(_stream==NULL)){
     if(_error!=NULL)*_error=OP_EFAULT;
     return NULL;
   }
-  of=op_test_callbacks(_source,_cb,NULL,0,_error);
-  if(OP_UNLIKELY(of==NULL))(*_cb->close)(_source);
+  of=op_test_callbacks(_stream,_cb,NULL,0,_error);
+  if(OP_UNLIKELY(of==NULL))(*_cb->close)(_stream);
   return of;
 }
 
@@ -1702,7 +1708,7 @@ int op_link_count(const OggOpusFile *_of){
   return _of->nlinks;
 }
 
-ogg_uint32_t op_serialno(const OggOpusFile *_of,int _li){
+opus_uint32 op_serialno(const OggOpusFile *_of,int _li){
   if(OP_UNLIKELY(_li>=_of->nlinks))_li=_of->nlinks-1;
   if(!_of->seekable)_li=0;
   return _of->links[_li<0?_of->cur_link:_li].serialno;
@@ -1718,13 +1724,14 @@ opus_int64 op_raw_total(const OggOpusFile *_of,int _li){
    ||OP_UNLIKELY(_li>=_of->nlinks)){
     return OP_EINVAL;
   }
-  if(_li<0)return _of->end-_of->links[0].offset;
+  if(_li<0)return _of->end;
   return (_li+1>=_of->nlinks?_of->end:_of->links[_li+1].offset)
-   -_of->links[_li].offset;
+   -(_li>0?_of->links[_li].offset:0);
 }
 
 ogg_int64_t op_pcm_total(const OggOpusFile *_of,int _li){
   OggOpusLink *links;
+  ogg_int64_t  pcm_total;
   ogg_int64_t  diff;
   int          nlinks;
   nlinks=_of->nlinks;
@@ -1737,20 +1744,14 @@ ogg_int64_t op_pcm_total(const OggOpusFile *_of,int _li){
   /*We verify that the granule position differences are larger than the
      pre-skip and that the total duration does not overflow during link
      enumeration, so we don't have to check here.*/
+  pcm_total=0;
   if(_li<0){
-    ogg_int64_t pcm_total;
-    int         li;
-    pcm_total=0;
-    for(li=0;li<nlinks;li++){
-      OP_ALWAYS_TRUE(!op_granpos_diff(&diff,
-       links[li].pcm_end,links[li].pcm_start));
-      pcm_total+=diff-links[li].head.pre_skip;
-    }
-    return pcm_total;
+    pcm_total=links[nlinks-1].pcm_file_offset;
+    _li=nlinks-1;
   }
   OP_ALWAYS_TRUE(!op_granpos_diff(&diff,
    links[_li].pcm_end,links[_li].pcm_start));
-  return diff-links[_li].head.pre_skip;
+  return pcm_total+diff-links[_li].head.pre_skip;
 }
 
 const OpusHead *op_head(const OggOpusFile *_of,int _li){
@@ -1820,6 +1821,34 @@ opus_int32 op_bitrate_instant(OggOpusFile *_of){
   return ret;
 }
 
+/*Given a serialno, find a link with a corresponding Opus stream, if it exists.
+  Return: The index of the link to which the page belongs, or a negative number
+           if it was not a desired Opus bitstream section.*/
+static int op_get_link_from_serialno(const OggOpusFile *_of,int _cur_link,
+ opus_int64 _page_offset,ogg_uint32_t _serialno){
+  const OggOpusLink *links;
+  int                nlinks;
+  int                li_lo;
+  int                li_hi;
+  OP_ASSERT(_of->seekable);
+  links=_of->links;
+  nlinks=_of->nlinks;
+  li_lo=0;
+  /*Start off by guessing we're just a multiplexed page in the current link.*/
+  li_hi=_cur_link+1<nlinks&&_page_offset<links[_cur_link+1].offset?
+   _cur_link+1:nlinks;
+  do{
+    if(_page_offset>=links[_cur_link].offset)li_lo=_cur_link;
+    else li_hi=_cur_link;
+    _cur_link=li_lo+(li_hi-li_lo>>1);
+  }
+  while(li_hi-li_lo>1);
+  /*We've identified the link that should contain this page.
+    Make sure it's a page we care about.*/
+  if(links[_cur_link].serialno!=_serialno)return OP_FALSE;
+  return _cur_link;
+}
+
 /*Fetch and process a page.
   This handles the case where we're at a bitstream boundary and dumps the
    decoding machine.
@@ -1876,19 +1905,28 @@ static int op_fetch_and_process_page(OggOpusFile *_of,
     if(OP_UNLIKELY(_of->ready_state<OP_STREAMSET)){
       if(seekable){
         ogg_uint32_t serialno;
-        int          nlinks;
-        int          li;
         serialno=ogg_page_serialno(&og);
-        /*Match the serialno to bitstream section.
-          We use this rather than offset positions to avoid problems near
-           logical bitstream boundaries.*/
-        nlinks=_of->nlinks;
-        for(li=0;li<nlinks&&links[li].serialno!=serialno;li++);
-        /*Not a desired Opus bitstream section.
-          Keep trying.*/
-        if(li>=nlinks)continue;
+        /*Match the serialno to bitstream section.*/
+        OP_ASSERT(cur_link>=0&&cur_link<_of->nlinks);
+        if(links[cur_link].serialno!=serialno){
+          /*It wasn't a page from the current link.
+            Is it from the next one?*/
+          if(OP_LIKELY(cur_link+1<_of->nlinks&&links[cur_link+1].serialno==
+           serialno)){
+            cur_link++;
+          }
+          else{
+            int new_link;
+            new_link=
+             op_get_link_from_serialno(_of,cur_link,_page_offset,serialno);
+            /*Not a desired Opus bitstream section.
+              Keep trying.*/
+            if(new_link<0)continue;
+            cur_link=new_link;
+          }
+        }
         cur_serialno=serialno;
-        _of->cur_link=cur_link=li;
+        _of->cur_link=cur_link;
         ogg_stream_reset_serialno(&_of->os,serialno);
         _of->ready_state=OP_STREAMSET;
         /*If we're at the start of this link, initialize the granule position
@@ -1942,13 +1980,32 @@ static int op_fetch_and_process_page(OggOpusFile *_of,
       opus_int32 total_duration;
       int        durations[255];
       int        op_count;
+      int        report_hole;
+      report_hole=0;
       total_duration=op_collect_audio_packets(_of,durations);
       if(OP_UNLIKELY(total_duration<0)){
-        /*Drain the packets from the page anyway.*/
+        /*libogg reported a hole (a gap in the page sequence numbers).
+          Drain the packets from the page anyway.
+          If we don't, they'll still be there when we fetch the next page.
+          Then, when we go to pull out packets, we might get more than 255,
+           which would overrun our packet buffer.*/
         total_duration=op_collect_audio_packets(_of,durations);
         OP_ASSERT(total_duration>=0);
-        /*Report holes to the caller.*/
-        if(!_ignore_holes)return OP_HOLE;
+        if(!_ignore_holes){
+          /*Report the hole to the caller after we finish timestamping the
+             packets.*/
+          report_hole=1;
+          /*We had lost or damaged pages, so reset our granule position
+             tracking.
+            This makes holes behave the same as a small raw seek.
+            If the next page is the EOS page, we'll discard it (because we
+             can't perform end trimming properly), and we'll always discard at
+             least 80 ms of audio (to allow decoder state to re-converge).
+            We could try to fill in the gap with PLC by looking at timestamps
+             in the non-EOS case, but that's complicated and error prone and we
+             can't rely on the timestamps being valid.*/
+          _of->prev_packet_gp=-1;
+        }
       }
       op_count=_of->op_count;
       /*If we found at least one audio data packet, compute per-packet granule
@@ -1975,6 +2032,7 @@ static int op_fetch_and_process_page(OggOpusFile *_of,
               Proceed to the next link, rather than risk playing back some
                samples that shouldn't have been played.*/
             _of->op_count=0;
+            if(report_hole)return OP_HOLE;
             continue;
           }
           /*By default discard 80 ms of data after a seek, unless we seek
@@ -2020,7 +2078,11 @@ static int op_fetch_and_process_page(OggOpusFile *_of,
          &&OP_LIKELY(diff<total_duration)){
           cur_packet_gp=prev_packet_gp;
           for(pi=0;pi<op_count;pi++){
-            diff=durations[pi]-diff;
+            /*Check for overflow.*/
+            if(diff<0&&OP_UNLIKELY(OP_INT64_MAX+diff<durations[pi])){
+              diff=durations[pi]+1;
+            }
+            else diff=durations[pi]-diff;
             /*If we have samples to trim...*/
             if(diff>0){
               /*If we trimmed the entire packet, stop (the spec says encoders
@@ -2076,10 +2138,11 @@ static int op_fetch_and_process_page(OggOpusFile *_of,
         }
         _of->prev_packet_gp=prev_packet_gp;
         _of->prev_page_offset=_page_offset;
-        _of->op_count=pi;
-        /*If end-trimming didn't trim all the packets, we're done.*/
-        if(OP_LIKELY(pi>0))return 0;
+        _of->op_count=op_count=pi;
       }
+      if(report_hole)return OP_HOLE;
+      /*If end-trimming didn't trim all the packets, we're done.*/
+      if(op_count>0)return 0;
     }
   }
 }
@@ -2117,35 +2180,41 @@ static ogg_int64_t op_get_granulepos(const OggOpusFile *_of,
  ogg_int64_t _pcm_offset,int *_li){
   const OggOpusLink *links;
   ogg_int64_t        duration;
+  ogg_int64_t        pcm_start;
+  opus_int32         pre_skip;
   int                nlinks;
-  int                li;
+  int                li_lo;
+  int                li_hi;
   OP_ASSERT(_pcm_offset>=0);
   nlinks=_of->nlinks;
   links=_of->links;
-  for(li=0;OP_LIKELY(li<nlinks);li++){
-    ogg_int64_t pcm_start;
-    opus_int32  pre_skip;
-    pcm_start=links[li].pcm_start;
-    pre_skip=links[li].head.pre_skip;
-    OP_ALWAYS_TRUE(!op_granpos_diff(&duration,links[li].pcm_end,pcm_start));
-    duration-=pre_skip;
-    if(_pcm_offset<duration){
-      _pcm_offset+=pre_skip;
-      if(OP_UNLIKELY(pcm_start>OP_INT64_MAX-_pcm_offset)){
-        /*Adding this amount to the granule position would overflow the positive
-           half of its 64-bit range.
-          Since signed overflow is undefined in C, do it in a way the compiler
-           isn't allowed to screw up.*/
-        _pcm_offset-=OP_INT64_MAX-pcm_start+1;
-        pcm_start=OP_INT64_MIN;
-      }
-      pcm_start+=_pcm_offset;
-      *_li=li;
-      return pcm_start;
-    }
-    _pcm_offset-=duration;
-  }
-  return -1;
+  li_lo=0;
+  li_hi=nlinks;
+  do{
+    int li;
+    li=li_lo+(li_hi-li_lo>>1);
+    if(links[li].pcm_file_offset<=_pcm_offset)li_lo=li;
+    else li_hi=li;
+  }
+  while(li_hi-li_lo>1);
+  _pcm_offset-=links[li_lo].pcm_file_offset;
+  pcm_start=links[li_lo].pcm_start;
+  pre_skip=links[li_lo].head.pre_skip;
+  OP_ALWAYS_TRUE(!op_granpos_diff(&duration,links[li_lo].pcm_end,pcm_start));
+  duration-=pre_skip;
+  if(_pcm_offset>=duration)return -1;
+  _pcm_offset+=pre_skip;
+  if(OP_UNLIKELY(pcm_start>OP_INT64_MAX-_pcm_offset)){
+    /*Adding this amount to the granule position would overflow the positive
+       half of its 64-bit range.
+      Since signed overflow is undefined in C, do it in a way the compiler
+       isn't allowed to screw up.*/
+    _pcm_offset-=OP_INT64_MAX-pcm_start+1;
+    pcm_start=OP_INT64_MIN;
+  }
+  pcm_start+=_pcm_offset;
+  *_li=li_lo;
+  return pcm_start;
 }
 
 /*A small helper to determine if an Ogg page contains data that continues onto
@@ -2532,15 +2601,14 @@ int op_pcm_seek(OggOpusFile *_of,ogg_int64_t _pcm_offset){
     ogg_int64_t gp;
     gp=_of->prev_packet_gp;
     if(OP_LIKELY(gp!=-1)){
-      int nbuffered;
+      ogg_int64_t discard_count;
+      int         nbuffered;
       nbuffered=OP_MAX(_of->od_buffer_size-_of->od_buffer_pos,0);
       OP_ALWAYS_TRUE(!op_granpos_add(&gp,gp,-nbuffered));
       /*We do _not_ add cur_discard_count to gp.
         Otherwise the total amount to discard could grow without bound, and it
          would be better just to do a full seek.*/
-      if(OP_LIKELY(!op_granpos_diff(&diff,gp,pcm_start))){
-        ogg_int64_t discard_count;
-        discard_count=_pcm_offset-diff;
+      if(OP_LIKELY(!op_granpos_diff(&discard_count,target_gp,gp))){
         /*We use a threshold of 90 ms instead of 80, since 80 ms is the
            _minimum_ we would have discarded after a full seek.
           Assuming 20 ms frames (the default), we'd discard 90 ms on average.*/
@@ -2606,22 +2674,14 @@ static ogg_int64_t op_get_pcm_offset(const OggOpusFile *_of,
  ogg_int64_t _gp,int _li){
   const OggOpusLink *links;
   ogg_int64_t        pcm_offset;
-  ogg_int64_t        delta;
-  int                li;
   links=_of->links;
-  pcm_offset=0;
-  OP_ASSERT(_li<_of->nlinks);
-  for(li=0;li<_li;li++){
-    OP_ALWAYS_TRUE(!op_granpos_diff(&delta,
-     links[li].pcm_end,links[li].pcm_start));
-    delta-=links[li].head.pre_skip;
-    pcm_offset+=delta;
-  }
-  OP_ASSERT(_li>=0);
+  OP_ASSERT(_li>=0&&_li<_of->nlinks);
+  pcm_offset=links[_li].pcm_file_offset;
   if(_of->seekable&&OP_UNLIKELY(op_granpos_cmp(_gp,links[_li].pcm_end)>0)){
     _gp=links[_li].pcm_end;
   }
   if(OP_LIKELY(op_granpos_cmp(_gp,links[_li].pcm_start)>0)){
+    ogg_int64_t delta;
     if(OP_UNLIKELY(op_granpos_diff(&delta,_gp,links[_li].pcm_start)<0)){
       /*This means an unseekable stream claimed to have a page from more than
          2 billion days after we joined.*/

+ 2 - 1
thirdparty/opus/repacketizer.c

@@ -213,7 +213,8 @@ opus_int32 opus_repacketizer_out_range_impl(OpusRepacketizer *rp, int begin, int
    {
       /* 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];
    }

+ 4 - 4
thirdparty/opus/silk/A2NLSF.c

@@ -40,7 +40,7 @@ POSSIBILITY OF SUCH DAMAGE.
 
 /* Number of binary divisions, when not in low complexity mode */
 #define BIN_DIV_STEPS_A2NLSF_FIX      3 /* must be no higher than 16 - log2( LSF_COS_TAB_SZ_FIX ) */
-#define MAX_ITERATIONS_A2NLSF_FIX    30
+#define MAX_ITERATIONS_A2NLSF_FIX    16
 
 /* Helper function for A2NLSF(..)                    */
 /* Transforms polynomials from cos(n*f) to cos(f)^n  */
@@ -130,7 +130,7 @@ void silk_A2NLSF(
     const opus_int              d                   /* I    Filter order (must be even)                                 */
 )
 {
-    opus_int      i, k, m, dd, root_ix, ffrac;
+    opus_int   i, k, m, dd, root_ix, ffrac;
     opus_int32 xlo, xhi, xmid;
     opus_int32 ylo, yhi, ymid, thr;
     opus_int32 nom, den;
@@ -239,13 +239,13 @@ void silk_A2NLSF(
                     /* Set NLSFs to white spectrum and exit */
                     NLSF[ 0 ] = (opus_int16)silk_DIV32_16( 1 << 15, d + 1 );
                     for( k = 1; k < d; k++ ) {
-                        NLSF[ k ] = (opus_int16)silk_SMULBB( k + 1, NLSF[ 0 ] );
+                        NLSF[ k ] = (opus_int16)silk_ADD16( NLSF[ k-1 ], NLSF[ 0 ] );
                     }
                     return;
                 }
 
                 /* Error: Apply progressively more bandwidth expansion and run again */
-                silk_bwexpander_32( a_Q16, d, 65536 - silk_SMULBB( 10 + i, i ) ); /* 10_Q16 = 0.00015*/
+                silk_bwexpander_32( a_Q16, d, 65536 - silk_LSHIFT( 1, i ) );
 
                 silk_A2NLSF_init( a_Q16, P, Q, dd );
                 p = P;                            /* Pointer to polynomial */

+ 2 - 1
thirdparty/opus/silk/API.h

@@ -80,7 +80,8 @@ opus_int silk_Encode(                                   /* O    Returns error co
     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        */
 );
 
 /****************************************/

+ 6 - 6
thirdparty/opus/silk/CNG.c

@@ -138,16 +138,16 @@ void silk_CNG(
             gain_Q16 = silk_LSHIFT32( silk_SQRT_APPROX( gain_Q16 ), 8 );
         }
         gain_Q10 = silk_RSHIFT( gain_Q16, 6 );
-        
+
         silk_CNG_exc( CNG_sig_Q14 + MAX_LPC_ORDER, psCNG->CNG_exc_buf_Q14, length, &psCNG->rand_seed );
 
         /* Convert CNG NLSF to filter representation */
-        silk_NLSF2A( A_Q12, psCNG->CNG_smth_NLSF_Q15, psDec->LPC_order );
+        silk_NLSF2A( A_Q12, psCNG->CNG_smth_NLSF_Q15, psDec->LPC_order, psDec->arch );
 
         /* 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 ] );
@@ -170,11 +170,11 @@ void silk_CNG(
             }
 
             /* Update states */
-            CNG_sig_Q14[ MAX_LPC_ORDER + i ] = silk_ADD_LSHIFT( CNG_sig_Q14[ MAX_LPC_ORDER + i ], LPC_pred_Q10, 4 );
-            
+            CNG_sig_Q14[ MAX_LPC_ORDER + i ] = silk_ADD_SAT32( CNG_sig_Q14[ MAX_LPC_ORDER + i ], silk_LSHIFT_SAT32( LPC_pred_Q10, 4 ) );
+
             /* Scale with Gain and add to input signal */
             frame[ i ] = (opus_int16)silk_ADD_SAT16( frame[ i ], silk_SAT16( silk_RSHIFT_ROUND( silk_SMULWW( CNG_sig_Q14[ MAX_LPC_ORDER + i ], gain_Q10 ), 8 ) ) );
-            
+
         }
         silk_memcpy( psCNG->CNG_synth_state, &CNG_sig_Q14[ length ], MAX_LPC_ORDER * sizeof( opus_int32 ) );
     } else {

+ 14 - 11
thirdparty/opus/silk/LPC_analysis_filter.c

@@ -39,6 +39,13 @@ POSSIBILITY OF SUCH DAMAGE.
 /* first d output samples are set to zero  */
 /*******************************************/
 
+/* OPT: Using celt_fir() for this function should be faster, but it may cause
+   integer overflows in intermediate values (not final results), which the
+   current implementation silences by casting to unsigned. Enabling
+   this should be safe in pretty much all cases, even though it is not technically
+   C89-compliant. */
+#define USE_CELT_FIR 0
+
 void silk_LPC_analysis_filter(
     opus_int16                  *out,               /* O    Output signal                                               */
     const opus_int16            *in,                /* I    Input signal                                                */
@@ -49,8 +56,7 @@ void silk_LPC_analysis_filter(
 )
 {
     opus_int   j;
-#ifdef FIXED_POINT
-    opus_int16 mem[SILK_MAX_ORDER_LPC];
+#if defined(FIXED_POINT) && USE_CELT_FIR
     opus_int16 num[SILK_MAX_ORDER_LPC];
 #else
     int ix;
@@ -58,19 +64,16 @@ void silk_LPC_analysis_filter(
     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 );
 
-#ifdef FIXED_POINT
-    silk_assert( d <= SILK_MAX_ORDER_LPC );
+#if defined(FIXED_POINT) && USE_CELT_FIR
+    celt_assert( d <= SILK_MAX_ORDER_LPC );
     for ( j = 0; j < d; j++ ) {
         num[ j ] = -B[ j ];
     }
-    for (j=0;j<d;j++) {
-        mem[ j ] = in[ d - j - 1 ];
-    }
-    celt_fir( in + d, num, out + d, len - d, d, mem, arch );
+    celt_fir( in + d, num, out + d, len - d, d, arch );
     for ( j = 0; j < d; j++ ) {
         out[ j ] = 0;
     }

+ 81 - 0
thirdparty/opus/silk/LPC_fit.c

@@ -0,0 +1,81 @@
+/***********************************************************************
+Copyright (c) 2013, Koen Vos. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+- Neither the name of Internet Society, IETF or IETF Trust, nor the
+names of specific contributors, may be used to endorse or promote
+products derived from this software without specific prior written
+permission.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "SigProc_FIX.h"
+
+/* Convert int32 coefficients to int16 coefs and make sure there's no wrap-around */
+void silk_LPC_fit(
+    opus_int16                  *a_QOUT,            /* O    Output signal                                               */
+    opus_int32                    *a_QIN,             /* I/O  Input signal                                                */
+    const opus_int              QOUT,               /* I    Input Q domain                                              */
+    const opus_int              QIN,                /* I    Input Q domain                                              */
+    const opus_int              d                   /* I    Filter order                                                */
+)
+{
+    opus_int    i, k, idx = 0;
+    opus_int32    maxabs, absval, chirp_Q16;
+
+    /* Limit the maximum absolute value of the prediction coefficients, so that they'll fit in int16 */
+    for( i = 0; i < 10; i++ ) {
+        /* Find maximum absolute value and its index */
+        maxabs = 0;
+        for( k = 0; k < d; k++ ) {
+            absval = silk_abs( a_QIN[k] );
+            if( absval > maxabs ) {
+                maxabs = absval;
+                idx    = k;
+            }
+        }
+        maxabs = silk_RSHIFT_ROUND( maxabs, QIN - QOUT );
+
+        if( maxabs > silk_int16_MAX ) {
+            /* Reduce magnitude of prediction coefficients */
+            maxabs = silk_min( maxabs, 163838 );  /* ( silk_int32_MAX >> 14 ) + silk_int16_MAX = 163838 */
+            chirp_Q16 = SILK_FIX_CONST( 0.999, 16 ) - silk_DIV32( silk_LSHIFT( maxabs - silk_int16_MAX, 14 ),
+                                        silk_RSHIFT32( silk_MUL( maxabs, idx + 1), 2 ) );
+            silk_bwexpander_32( a_QIN, d, chirp_Q16 );
+        } else {
+            break;
+        }
+    }
+
+    if( i == 10 ) {
+        /* Reached the last iteration, clip the coefficients */
+        for( k = 0; k < d; k++ ) {
+            a_QOUT[ k ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( a_QIN[ k ], QIN - QOUT ) );
+            a_QIN[ k ] = silk_LSHIFT( (opus_int32)a_QOUT[ k ], QIN - QOUT );
+        }
+    } else {
+        for( k = 0; k < d; k++ ) {
+            a_QOUT[ k ] = (opus_int16)silk_RSHIFT_ROUND( a_QIN[ k ], QIN - QOUT );
+        }
+    }
+}

+ 42 - 55
thirdparty/opus/silk/LPC_inv_pred_gain.c

@@ -30,6 +30,7 @@ POSSIBILITY OF SUCH DAMAGE.
 #endif
 
 #include "SigProc_FIX.h"
+#include "define.h"
 
 #define QA                          24
 #define A_LIMIT                     SILK_FIX_CONST( 0.99975, QA )
@@ -38,117 +39,103 @@ POSSIBILITY OF SUCH DAMAGE.
 
 /* Compute inverse of LPC prediction gain, and                          */
 /* test if LPC coefficients are stable (all poles within unit circle)   */
-static opus_int32 LPC_inverse_pred_gain_QA(                 /* O   Returns inverse prediction gain in energy domain, Q30    */
-    opus_int32           A_QA[ 2 ][ SILK_MAX_ORDER_LPC ],   /* I   Prediction coefficients                                  */
+static opus_int32 LPC_inverse_pred_gain_QA_c(               /* O   Returns inverse prediction gain in energy domain, Q30    */
+    opus_int32           A_QA[ SILK_MAX_ORDER_LPC ],        /* I   Prediction coefficients                                  */
     const opus_int       order                              /* I   Prediction order                                         */
 )
 {
     opus_int   k, n, mult2Q;
-    opus_int32 invGain_Q30, rc_Q31, rc_mult1_Q30, rc_mult2, tmp_QA;
-    opus_int32 *Aold_QA, *Anew_QA;
+    opus_int32 invGain_Q30, rc_Q31, rc_mult1_Q30, rc_mult2, tmp1, tmp2;
 
-    Anew_QA = A_QA[ order & 1 ];
-
-    invGain_Q30 = (opus_int32)1 << 30;
+    invGain_Q30 = SILK_FIX_CONST( 1, 30 );
     for( k = order - 1; k > 0; k-- ) {
         /* Check for stability */
-        if( ( Anew_QA[ k ] > A_LIMIT ) || ( Anew_QA[ k ] < -A_LIMIT ) ) {
+        if( ( A_QA[ k ] > A_LIMIT ) || ( A_QA[ k ] < -A_LIMIT ) ) {
             return 0;
         }
 
         /* Set RC equal to negated AR coef */
-        rc_Q31 = -silk_LSHIFT( Anew_QA[ k ], 31 - QA );
+        rc_Q31 = -silk_LSHIFT( A_QA[ k ], 31 - QA );
 
         /* rc_mult1_Q30 range: [ 1 : 2^30 ] */
-        rc_mult1_Q30 = ( (opus_int32)1 << 30 ) - silk_SMMUL( rc_Q31, rc_Q31 );
+        rc_mult1_Q30 = silk_SUB32( SILK_FIX_CONST( 1, 30 ), silk_SMMUL( rc_Q31, rc_Q31 ) );
         silk_assert( rc_mult1_Q30 > ( 1 << 15 ) );                   /* reduce A_LIMIT if fails */
         silk_assert( rc_mult1_Q30 <= ( 1 << 30 ) );
 
-        /* rc_mult2 range: [ 2^30 : silk_int32_MAX ] */
-        mult2Q = 32 - silk_CLZ32( silk_abs( rc_mult1_Q30 ) );
-        rc_mult2 = silk_INVERSE32_varQ( rc_mult1_Q30, mult2Q + 30 );
-
         /* Update inverse gain */
         /* invGain_Q30 range: [ 0 : 2^30 ] */
         invGain_Q30 = silk_LSHIFT( silk_SMMUL( invGain_Q30, rc_mult1_Q30 ), 2 );
         silk_assert( invGain_Q30 >= 0           );
         silk_assert( invGain_Q30 <= ( 1 << 30 ) );
+        if( invGain_Q30 < SILK_FIX_CONST( 1.0f / MAX_PREDICTION_POWER_GAIN, 30 ) ) {
+            return 0;
+        }
 
-        /* Swap pointers */
-        Aold_QA = Anew_QA;
-        Anew_QA = A_QA[ k & 1 ];
+        /* rc_mult2 range: [ 2^30 : silk_int32_MAX ] */
+        mult2Q = 32 - silk_CLZ32( silk_abs( rc_mult1_Q30 ) );
+        rc_mult2 = silk_INVERSE32_varQ( rc_mult1_Q30, mult2Q + 30 );
 
         /* Update AR coefficient */
-        for( n = 0; n < k; n++ ) {
-            tmp_QA = Aold_QA[ n ] - MUL32_FRAC_Q( Aold_QA[ k - n - 1 ], rc_Q31, 31 );
-            Anew_QA[ n ] = MUL32_FRAC_Q( tmp_QA, rc_mult2 , mult2Q );
+        for( n = 0; n < (k + 1) >> 1; n++ ) {
+            opus_int64 tmp64;
+            tmp1 = A_QA[ n ];
+            tmp2 = A_QA[ k - n - 1 ];
+            tmp64 = silk_RSHIFT_ROUND64( silk_SMULL( silk_SUB_SAT32(tmp1,
+                  MUL32_FRAC_Q( tmp2, rc_Q31, 31 ) ), rc_mult2 ), mult2Q);
+            if( tmp64 > silk_int32_MAX || tmp64 < silk_int32_MIN ) {
+               return 0;
+            }
+            A_QA[ n ] = ( opus_int32 )tmp64;
+            tmp64 = silk_RSHIFT_ROUND64( silk_SMULL( silk_SUB_SAT32(tmp2,
+                  MUL32_FRAC_Q( tmp1, rc_Q31, 31 ) ), rc_mult2), mult2Q);
+            if( tmp64 > silk_int32_MAX || tmp64 < silk_int32_MIN ) {
+               return 0;
+            }
+            A_QA[ k - n - 1 ] = ( opus_int32 )tmp64;
         }
     }
 
     /* Check for stability */
-    if( ( Anew_QA[ 0 ] > A_LIMIT ) || ( Anew_QA[ 0 ] < -A_LIMIT ) ) {
+    if( ( A_QA[ k ] > A_LIMIT ) || ( A_QA[ k ] < -A_LIMIT ) ) {
         return 0;
     }
 
     /* Set RC equal to negated AR coef */
-    rc_Q31 = -silk_LSHIFT( Anew_QA[ 0 ], 31 - QA );
+    rc_Q31 = -silk_LSHIFT( A_QA[ 0 ], 31 - QA );
 
     /* Range: [ 1 : 2^30 ] */
-    rc_mult1_Q30 = ( (opus_int32)1 << 30 ) - silk_SMMUL( rc_Q31, rc_Q31 );
+    rc_mult1_Q30 = silk_SUB32( SILK_FIX_CONST( 1, 30 ), silk_SMMUL( rc_Q31, rc_Q31 ) );
 
     /* Update inverse gain */
     /* Range: [ 0 : 2^30 ] */
     invGain_Q30 = silk_LSHIFT( silk_SMMUL( invGain_Q30, rc_mult1_Q30 ), 2 );
-    silk_assert( invGain_Q30 >= 0     );
-    silk_assert( invGain_Q30 <= 1<<30 );
+    silk_assert( invGain_Q30 >= 0           );
+    silk_assert( invGain_Q30 <= ( 1 << 30 ) );
+    if( invGain_Q30 < SILK_FIX_CONST( 1.0f / MAX_PREDICTION_POWER_GAIN, 30 ) ) {
+        return 0;
+    }
 
     return invGain_Q30;
 }
 
 /* For input in Q12 domain */
-opus_int32 silk_LPC_inverse_pred_gain(              /* O   Returns inverse prediction gain in energy domain, Q30        */
+opus_int32 silk_LPC_inverse_pred_gain_c(            /* O   Returns inverse prediction gain in energy domain, Q30        */
     const opus_int16            *A_Q12,             /* I   Prediction coefficients, Q12 [order]                         */
     const opus_int              order               /* I   Prediction order                                             */
 )
 {
     opus_int   k;
-    opus_int32 Atmp_QA[ 2 ][ SILK_MAX_ORDER_LPC ];
-    opus_int32 *Anew_QA;
+    opus_int32 Atmp_QA[ SILK_MAX_ORDER_LPC ];
     opus_int32 DC_resp = 0;
 
-    Anew_QA = Atmp_QA[ order & 1 ];
-
     /* Increase Q domain of the AR coefficients */
     for( k = 0; k < order; k++ ) {
         DC_resp += (opus_int32)A_Q12[ k ];
-        Anew_QA[ k ] = silk_LSHIFT32( (opus_int32)A_Q12[ k ], QA - 12 );
+        Atmp_QA[ k ] = silk_LSHIFT32( (opus_int32)A_Q12[ k ], QA - 12 );
     }
     /* If the DC is unstable, we don't even need to do the full calculations */
     if( DC_resp >= 4096 ) {
         return 0;
     }
-    return LPC_inverse_pred_gain_QA( Atmp_QA, order );
+    return LPC_inverse_pred_gain_QA_c( Atmp_QA, order );
 }
-
-#ifdef FIXED_POINT
-
-/* For input in Q24 domain */
-opus_int32 silk_LPC_inverse_pred_gain_Q24(          /* O    Returns inverse prediction gain in energy domain, Q30       */
-    const opus_int32            *A_Q24,             /* I    Prediction coefficients [order]                             */
-    const opus_int              order               /* I    Prediction order                                            */
-)
-{
-    opus_int   k;
-    opus_int32 Atmp_QA[ 2 ][ SILK_MAX_ORDER_LPC ];
-    opus_int32 *Anew_QA;
-
-    Anew_QA = Atmp_QA[ order & 1 ];
-
-    /* Increase Q domain of the AR coefficients */
-    for( k = 0; k < order; k++ ) {
-        Anew_QA[ k ] = silk_RSHIFT32( A_Q24[ k ], 24 - QA );
-    }
-
-    return LPC_inverse_pred_gain_QA( Atmp_QA, order );
-}
-#endif

+ 1 - 1
thirdparty/opus/silk/LP_variable_cutoff.c

@@ -130,6 +130,6 @@ void silk_LP_variable_cutoff(
 
         /* ARMA low-pass filtering */
         silk_assert( TRANSITION_NB == 3 && TRANSITION_NA == 2 );
-        silk_biquad_alt( frame, B_Q28, A_Q28, psLP->In_LP_State, frame, frame_length, 1);
+        silk_biquad_alt_stride1( frame, B_Q28, A_Q28, psLP->In_LP_State, frame, frame_length);
     }
 }

+ 1 - 9
thirdparty/opus/silk/MacroCount.h

@@ -319,14 +319,6 @@ static OPUS_INLINE opus_int32 silk_ADD_POS_SAT32(opus_int64 a, opus_int64 b){
     return(tmp);
 }
 
-#undef silk_ADD_POS_SAT64
-static OPUS_INLINE opus_int64 silk_ADD_POS_SAT64(opus_int64 a, opus_int64 b){
-    opus_int64 tmp;
-    ops_count += 1;
-    tmp = ((((a)+(b)) & 0x8000000000000000LL) ? silk_int64_MAX : ((a)+(b)));
-    return(tmp);
-}
-
 #undef    silk_LSHIFT8
 static OPUS_INLINE opus_int8 silk_LSHIFT8(opus_int8 a, opus_int32 shift){
     opus_int8 ret;
@@ -699,7 +691,7 @@ return(ret);
 
 
 #undef silk_LIMIT_32
-static OPUS_INLINE opus_int silk_LIMIT_32(opus_int32 a, opus_int32 limit1, opus_int32 limit2)
+static OPUS_INLINE opus_int32 silk_LIMIT_32(opus_int32 a, opus_int32 limit1, opus_int32 limit2)
 {
     opus_int32 ret;
     ops_count += 6;

+ 1 - 2
thirdparty/opus/silk/MacroDebug.h

@@ -539,8 +539,7 @@ static OPUS_INLINE opus_int32 silk_DIV32_16_(opus_int32 a32, opus_int32 b32, cha
    no checking needed for silk_POS_SAT32
    no checking needed for silk_ADD_POS_SAT8
    no checking needed for silk_ADD_POS_SAT16
-   no checking needed for silk_ADD_POS_SAT32
-   no checking needed for silk_ADD_POS_SAT64 */
+   no checking needed for silk_ADD_POS_SAT32 */
 
 #undef silk_LSHIFT8
 #define silk_LSHIFT8(a,b) silk_LSHIFT8_((a), (b), __FILE__, __LINE__)

+ 11 - 48
thirdparty/opus/silk/NLSF2A.c

@@ -66,7 +66,8 @@ static OPUS_INLINE void silk_NLSF2A_find_poly(
 void silk_NLSF2A(
     opus_int16                  *a_Q12,             /* O    monic whitening filter coefficients in Q12,  [ d ]          */
     const opus_int16            *NLSF,              /* I    normalized line spectral frequencies in Q15, [ d ]          */
-    const opus_int              d                   /* I    filter order (should be even)                               */
+    const opus_int              d,                  /* I    filter order (should be even)                               */
+    int                         arch                /* I    Run-time architecture                                       */
 )
 {
     /* This ordering was found to maximize quality. It improves numerical accuracy of
@@ -83,15 +84,14 @@ void silk_NLSF2A(
     opus_int32 P[ SILK_MAX_ORDER_LPC / 2 + 1 ], Q[ SILK_MAX_ORDER_LPC / 2 + 1 ];
     opus_int32 Ptmp, Qtmp, f_int, f_frac, cos_val, delta;
     opus_int32 a32_QA1[ SILK_MAX_ORDER_LPC ];
-    opus_int32 maxabs, absval, idx=0, sc_Q16;
 
     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;
     for( k = 0; k < d; k++ ) {
-        silk_assert(NLSF[k] >= 0 );
+        silk_assert( NLSF[k] >= 0 );
 
         /* f_int on a scale 0-127 (rounded down) */
         f_int = silk_RSHIFT( NLSF[k], 15 - 7 );
@@ -126,52 +126,15 @@ void silk_NLSF2A(
         a32_QA1[ d-k-1 ] =  Qtmp - Ptmp;        /* QA+1 */
     }
 
-    /* Limit the maximum absolute value of the prediction coefficients, so that they'll fit in int16 */
-    for( i = 0; i < 10; i++ ) {
-        /* Find maximum absolute value and its index */
-        maxabs = 0;
-        for( k = 0; k < d; k++ ) {
-            absval = silk_abs( a32_QA1[k] );
-            if( absval > maxabs ) {
-                maxabs = absval;
-                idx    = k;
-            }
-        }
-        maxabs = silk_RSHIFT_ROUND( maxabs, QA + 1 - 12 );                                          /* QA+1 -> Q12 */
-
-        if( maxabs > silk_int16_MAX ) {
-            /* Reduce magnitude of prediction coefficients */
-            maxabs = silk_min( maxabs, 163838 );  /* ( silk_int32_MAX >> 14 ) + silk_int16_MAX = 163838 */
-            sc_Q16 = SILK_FIX_CONST( 0.999, 16 ) - silk_DIV32( silk_LSHIFT( maxabs - silk_int16_MAX, 14 ),
-                                        silk_RSHIFT32( silk_MUL( maxabs, idx + 1), 2 ) );
-            silk_bwexpander_32( a32_QA1, d, sc_Q16 );
-        } else {
-            break;
-        }
-    }
+    /* Convert int32 coefficients to Q12 int16 coefs */
+    silk_LPC_fit( a_Q12, a32_QA1, 12, QA + 1, d );
 
-    if( i == 10 ) {
-        /* Reached the last iteration, clip the coefficients */
+    for( i = 0; silk_LPC_inverse_pred_gain( a_Q12, d, arch ) == 0 && i < MAX_LPC_STABILIZE_ITERATIONS; i++ ) {
+        /* Prediction coefficients are (too close to) unstable; apply bandwidth expansion   */
+        /* on the unscaled coefficients, convert to Q12 and measure again                   */
+        silk_bwexpander_32( a32_QA1, d, 65536 - silk_LSHIFT( 2, i ) );
         for( k = 0; k < d; k++ ) {
-            a_Q12[ k ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( a32_QA1[ k ], QA + 1 - 12 ) );  /* QA+1 -> Q12 */
-            a32_QA1[ k ] = silk_LSHIFT( (opus_int32)a_Q12[ k ], QA + 1 - 12 );
-        }
-    } else {
-        for( k = 0; k < d; k++ ) {
-            a_Q12[ k ] = (opus_int16)silk_RSHIFT_ROUND( a32_QA1[ k ], QA + 1 - 12 );                /* QA+1 -> Q12 */
-        }
-    }
-
-    for( i = 0; i < MAX_LPC_STABILIZE_ITERATIONS; i++ ) {
-        if( silk_LPC_inverse_pred_gain( a_Q12, d ) < SILK_FIX_CONST( 1.0 / MAX_PREDICTION_POWER_GAIN, 30 ) ) {
-            /* Prediction coefficients are (too close to) unstable; apply bandwidth expansion   */
-            /* on the unscaled coefficients, convert to Q12 and measure again                   */
-            silk_bwexpander_32( a32_QA1, d, 65536 - silk_LSHIFT( 2, i ) );
-            for( k = 0; k < d; k++ ) {
-                a_Q12[ k ] = (opus_int16)silk_RSHIFT_ROUND( a32_QA1[ k ], QA + 1 - 12 );            /* QA+1 -> Q12 */
-            }
-        } else {
-            break;
+            a_Q12[ k ] = (opus_int16)silk_RSHIFT_ROUND( a32_QA1[ k ], QA + 1 - 12 );            /* QA+1 -> Q12 */
         }
     }
 }

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