Browse Source

opus: Update to upstream libopus 1.1.3

Rémi Verschelde 8 years ago
parent
commit
9845bdde8d

+ 2 - 2
thirdparty/README.md

@@ -141,7 +141,7 @@ changes are marked with `// -- GODOT --` comments.
 ## openssl
 ## openssl
 
 
 - Upstream: https://www.openssl.org
 - Upstream: https://www.openssl.org
-- Version: 1.2.0h
+- Version: 1.0.2h
 - License: OpenSSL license / BSD-like
 - License: OpenSSL license / BSD-like
 
 
 Files extracted from the upstream source:
 Files extracted from the upstream source:
@@ -152,7 +152,7 @@ TODO.
 ## opus
 ## opus
 
 
 - Upstream: https://opus-codec.org
 - Upstream: https://opus-codec.org
-- Version: 1.1.2 (opus) and 0.7 (opusfile)
+- Version: 1.1.3 (opus) and 0.7 (opusfile)
 - License: BSD-3-Clause
 - License: BSD-3-Clause
 
 
 Files extracted from upstream source:
 Files extracted from upstream source:

+ 28 - 12
thirdparty/opus/COPYING

@@ -1,4 +1,7 @@
-Copyright (c) 1994-2013 Xiph.Org Foundation and contributors
+Copyright 2001-2011 Xiph.Org, Skype Limited, Octasic,
+                    Jean-Marc Valin, Timothy B. Terriberry,
+                    CSIRO, Gregory Maxwell, Mark Borgerding,
+                    Erik de Castro Lopo
 
 
 Redistribution and use in source and binary forms, with or without
 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions
 modification, are permitted provided that the following conditions
@@ -11,18 +14,31 @@ notice, this list of conditions and the following disclaimer.
 notice, this list of conditions and the following disclaimer in the
 notice, this list of conditions and the following disclaimer in the
 documentation and/or other materials provided with the distribution.
 documentation and/or other materials provided with the distribution.
 
 
-- Neither the name of the Xiph.Org Foundation nor the names of its
-contributors may be used to endorse or promote products derived from
-this software without specific prior written permission.
+- 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
 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION
-OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+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.
+
+Opus is subject to the royalty-free patent licenses which are
+specified at:
+
+Xiph.Org Foundation:
+https://datatracker.ietf.org/ipr/1524/
+
+Microsoft Corporation:
+https://datatracker.ietf.org/ipr/1914/
+
+Broadcom Corporation:
+https://datatracker.ietf.org/ipr/1526/

+ 5 - 8
thirdparty/opus/analysis.c

@@ -540,17 +540,14 @@ static void tonality_analysis(TonalityAnalysisState *tonal, const CELTMode *celt
        /* Instantaneous probability of speech and music, with beta pre-applied. */
        /* Instantaneous probability of speech and music, with beta pre-applied. */
        float speech0;
        float speech0;
        float music0;
        float music0;
+       float p, q;
 
 
        /* One transition every 3 minutes of active audio */
        /* One transition every 3 minutes of active audio */
        tau = .00005f*frame_probs[1];
        tau = .00005f*frame_probs[1];
-       beta = .05f;
-       if (1) {
-          /* Adapt beta based on how "unexpected" the new prob is */
-          float p, q;
-          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));
-       }
+       /* 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
        /* p0 and p1 are the probabilities of speech and music at this frame
           using only information from previous frame and applying the
           using only information from previous frame and applying the
           state transition model */
           state transition model */

+ 7 - 1
thirdparty/opus/opus.c

@@ -104,6 +104,10 @@ OPUS_EXPORT void opus_pcm_soft_clip(float *_x, int N, int C, float *declip_mem)
 
 
          /* Compute a such that maxval + a*maxval^2 = 1 */
          /* Compute a such that maxval + a*maxval^2 = 1 */
          a=(maxval-1)/(maxval*maxval);
          a=(maxval-1)/(maxval*maxval);
+         /* Slightly boost "a" by 2^-22. This is just enough to ensure -ffast-math
+            does not cause output values larger than +/-1, but small enough not
+            to matter even for 24-bit output.  */
+         a += a*2.4e-7;
          if (x[i*C]>0)
          if (x[i*C]>0)
             a = -a;
             a = -a;
          /* Apply soft clipping */
          /* Apply soft clipping */
@@ -201,8 +205,10 @@ int opus_packet_parse_impl(const unsigned char *data, opus_int32 len,
    opus_int32 pad = 0;
    opus_int32 pad = 0;
    const unsigned char *data0 = data;
    const unsigned char *data0 = data;
 
 
-   if (size==NULL)
+   if (size==NULL || len<0)
       return OPUS_BAD_ARG;
       return OPUS_BAD_ARG;
+   if (len==0)
+      return OPUS_INVALID_PACKET;
 
 
    framesize = opus_packet_get_samples_per_frame(data, 48000);
    framesize = opus_packet_get_samples_per_frame(data, 48000);
 
 

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

@@ -142,7 +142,7 @@ extern "C" {
   *
   *
   * opus_encode() and opus_encode_float() return the number of bytes actually written to the packet.
   * opus_encode() and opus_encode_float() return the number of bytes actually written to the packet.
   * The return value <b>can be negative</b>, which indicates that an error has occurred. If the return value
   * The return value <b>can be negative</b>, which indicates that an error has occurred. If the return value
-  * is 1 byte, then the packet does not need to be transmitted (DTX).
+  * is 2 bytes or less, then the packet does not need to be transmitted (DTX).
   *
   *
   * Once the encoder state if no longer needed, it can be destroyed with
   * Once the encoder state if no longer needed, it can be destroyed with
   *
   *

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

@@ -65,7 +65,7 @@ extern "C" {
 
 
 #ifndef OPUS_EXPORT
 #ifndef OPUS_EXPORT
 # if defined(WIN32)
 # if defined(WIN32)
-#  ifdef OPUS_BUILD
+#  if defined(OPUS_BUILD) && defined(DLL_EXPORT)
 #   define OPUS_EXPORT __declspec(dllexport)
 #   define OPUS_EXPORT __declspec(dllexport)
 #  else
 #  else
 #   define OPUS_EXPORT
 #   define OPUS_EXPORT

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

@@ -110,10 +110,10 @@ extern "C" {
   * packets produced by the encoder. Some basic information, such as packet
   * packets produced by the encoder. Some basic information, such as packet
   * duration, can be computed without any special negotiation.
   * duration, can be computed without any special negotiation.
   *
   *
-  * The format for multistream Opus packets is defined in the
-  * <a href="https://tools.ietf.org/html/draft-ietf-codec-oggopus">Ogg
-  * encapsulation specification</a> and is based on the self-delimited Opus
-  * framing described in Appendix B of <a href="https://tools.ietf.org/html/rfc6716">RFC 6716</a>.
+  * The format for multistream Opus packets is defined in
+  * <a href="https://tools.ietf.org/html/rfc7845">RFC 7845</a>
+  * and is based on the self-delimited Opus framing described in Appendix B of
+  * <a href="https://tools.ietf.org/html/rfc6716">RFC 6716</a>.
   * Normal Opus packets are just a degenerate case of multistream Opus packets,
   * Normal Opus packets are just a degenerate case of multistream Opus packets,
   * and can be encoded or decoded with the multistream API by setting
   * and can be encoded or decoded with the multistream API by setting
   * <code>streams</code> to <code>1</code> when initializing the encoder or
   * <code>streams</code> to <code>1</code> when initializing the encoder or

+ 30 - 21
thirdparty/opus/opus_encoder.c

@@ -860,9 +860,6 @@ opus_int32 compute_frame_size(const void *analysis_pcm, int frame_size,
 
 
 opus_val16 compute_stereo_width(const opus_val16 *pcm, int frame_size, opus_int32 Fs, StereoWidthState *mem)
 opus_val16 compute_stereo_width(const opus_val16 *pcm, int frame_size, opus_int32 Fs, StereoWidthState *mem)
 {
 {
-   opus_val16 corr;
-   opus_val16 ldiff;
-   opus_val16 width;
    opus_val32 xx, xy, yy;
    opus_val32 xx, xy, yy;
    opus_val16 sqrt_xx, sqrt_yy;
    opus_val16 sqrt_xx, sqrt_yy;
    opus_val16 qrrt_xx, qrrt_yy;
    opus_val16 qrrt_xx, qrrt_yy;
@@ -871,9 +868,12 @@ opus_val16 compute_stereo_width(const opus_val16 *pcm, int frame_size, opus_int3
    opus_val16 short_alpha;
    opus_val16 short_alpha;
 
 
    frame_rate = Fs/frame_size;
    frame_rate = Fs/frame_size;
-   short_alpha = Q15ONE - 25*Q15ONE/IMAX(50,frame_rate);
+   short_alpha = Q15ONE - MULT16_16(25, Q15ONE)/IMAX(50,frame_rate);
    xx=xy=yy=0;
    xx=xy=yy=0;
-   for (i=0;i<frame_size;i+=4)
+   /* Unroll by 4. The frame size is always a multiple of 4 *except* for
+      2.5 ms frames at 12 kHz. Since this setting is very rare (and very
+      stupid), we just discard the last two samples. */
+   for (i=0;i<frame_size-3;i+=4)
    {
    {
       opus_val32 pxx=0;
       opus_val32 pxx=0;
       opus_val32 pxy=0;
       opus_val32 pxy=0;
@@ -912,6 +912,9 @@ opus_val16 compute_stereo_width(const opus_val16 *pcm, int frame_size, opus_int3
    mem->YY = MAX32(0, mem->YY);
    mem->YY = MAX32(0, mem->YY);
    if (MAX32(mem->XX, mem->YY)>QCONST16(8e-4f, 18))
    if (MAX32(mem->XX, mem->YY)>QCONST16(8e-4f, 18))
    {
    {
+      opus_val16 corr;
+      opus_val16 ldiff;
+      opus_val16 width;
       sqrt_xx = celt_sqrt(mem->XX);
       sqrt_xx = celt_sqrt(mem->XX);
       sqrt_yy = celt_sqrt(mem->YY);
       sqrt_yy = celt_sqrt(mem->YY);
       qrrt_xx = celt_sqrt(sqrt_xx);
       qrrt_xx = celt_sqrt(sqrt_xx);
@@ -920,19 +923,15 @@ opus_val16 compute_stereo_width(const opus_val16 *pcm, int frame_size, opus_int3
       mem->XY = MIN32(mem->XY, sqrt_xx*sqrt_yy);
       mem->XY = MIN32(mem->XY, sqrt_xx*sqrt_yy);
       corr = SHR32(frac_div32(mem->XY,EPSILON+MULT16_16(sqrt_xx,sqrt_yy)),16);
       corr = SHR32(frac_div32(mem->XY,EPSILON+MULT16_16(sqrt_xx,sqrt_yy)),16);
       /* Approximate loudness difference */
       /* Approximate loudness difference */
-      ldiff = Q15ONE*ABS16(qrrt_xx-qrrt_yy)/(EPSILON+qrrt_xx+qrrt_yy);
+      ldiff = MULT16_16(Q15ONE, ABS16(qrrt_xx-qrrt_yy))/(EPSILON+qrrt_xx+qrrt_yy);
       width = MULT16_16_Q15(celt_sqrt(QCONST32(1.f,30)-MULT16_16(corr,corr)), ldiff);
       width = MULT16_16_Q15(celt_sqrt(QCONST32(1.f,30)-MULT16_16(corr,corr)), ldiff);
       /* Smoothing over one second */
       /* Smoothing over one second */
       mem->smoothed_width += (width-mem->smoothed_width)/frame_rate;
       mem->smoothed_width += (width-mem->smoothed_width)/frame_rate;
       /* Peak follower */
       /* Peak follower */
       mem->max_follower = MAX16(mem->max_follower-QCONST16(.02f,15)/frame_rate, mem->smoothed_width);
       mem->max_follower = MAX16(mem->max_follower-QCONST16(.02f,15)/frame_rate, mem->smoothed_width);
-   } else {
-      width = 0;
-      corr=Q15ONE;
-      ldiff=0;
    }
    }
    /*printf("%f %f %f %f %f ", corr/(float)Q15ONE, ldiff/(float)Q15ONE, width/(float)Q15ONE, mem->smoothed_width/(float)Q15ONE, mem->max_follower/(float)Q15ONE);*/
    /*printf("%f %f %f %f %f ", corr/(float)Q15ONE, ldiff/(float)Q15ONE, width/(float)Q15ONE, mem->smoothed_width/(float)Q15ONE, mem->max_follower/(float)Q15ONE);*/
-   return EXTRACT16(MIN32(Q15ONE,20*mem->max_follower));
+   return EXTRACT16(MIN32(Q15ONE, MULT16_16(20, mem->max_follower)));
 }
 }
 
 
 opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_size,
 opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_size,
@@ -1050,6 +1049,16 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_
     st->bitrate_bps = user_bitrate_to_bitrate(st, frame_size, max_data_bytes);
     st->bitrate_bps = user_bitrate_to_bitrate(st, frame_size, max_data_bytes);
 
 
     frame_rate = st->Fs/frame_size;
     frame_rate = st->Fs/frame_size;
+    if (!st->use_vbr)
+    {
+       int cbrBytes;
+       /* Multiply by 3 to make sure the division is exact. */
+       int frame_rate3 = 3*st->Fs/frame_size;
+       /* We need to make sure that "int" values always fit in 16 bits. */
+       cbrBytes = IMIN( (3*st->bitrate_bps/8 + frame_rate3/2)/frame_rate3, max_data_bytes);
+       st->bitrate_bps = cbrBytes*(opus_int32)frame_rate3*8/3;
+       max_data_bytes = cbrBytes;
+    }
     if (max_data_bytes<3 || st->bitrate_bps < 3*frame_rate*8
     if (max_data_bytes<3 || st->bitrate_bps < 3*frame_rate*8
        || (frame_rate<50 && (max_data_bytes*frame_rate<300 || st->bitrate_bps < 2400)))
        || (frame_rate<50 && (max_data_bytes*frame_rate<300 || st->bitrate_bps < 2400)))
     {
     {
@@ -1066,18 +1075,18 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_
           bw=OPUS_BANDWIDTH_WIDEBAND;
           bw=OPUS_BANDWIDTH_WIDEBAND;
        else if (tocmode==MODE_CELT_ONLY&&bw==OPUS_BANDWIDTH_MEDIUMBAND)
        else if (tocmode==MODE_CELT_ONLY&&bw==OPUS_BANDWIDTH_MEDIUMBAND)
           bw=OPUS_BANDWIDTH_NARROWBAND;
           bw=OPUS_BANDWIDTH_NARROWBAND;
-       else if (bw<=OPUS_BANDWIDTH_SUPERWIDEBAND)
+       else if (tocmode==MODE_HYBRID&&bw<=OPUS_BANDWIDTH_SUPERWIDEBAND)
           bw=OPUS_BANDWIDTH_SUPERWIDEBAND;
           bw=OPUS_BANDWIDTH_SUPERWIDEBAND;
        data[0] = gen_toc(tocmode, frame_rate, bw, st->stream_channels);
        data[0] = gen_toc(tocmode, frame_rate, bw, st->stream_channels);
+       ret = 1;
+       if (!st->use_vbr)
+       {
+          ret = opus_packet_pad(data, ret, max_data_bytes);
+          if (ret == OPUS_OK)
+             ret = max_data_bytes;
+       }
        RESTORE_STACK;
        RESTORE_STACK;
-       return 1;
-    }
-    if (!st->use_vbr)
-    {
-       int cbrBytes;
-       cbrBytes = IMIN( (st->bitrate_bps + 4*frame_rate)/(8*frame_rate) , max_data_bytes);
-       st->bitrate_bps = cbrBytes * (8*frame_rate);
-       max_data_bytes = cbrBytes;
+       return ret;
     }
     }
     max_rate = frame_rate*max_data_bytes*8;
     max_rate = frame_rate*max_data_bytes*8;
 
 
@@ -1513,7 +1522,7 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_
                celt_rate = total_bitRate - st->silk_mode.bitRate;
                celt_rate = total_bitRate - st->silk_mode.bitRate;
                HB_gain_ref = (curr_bandwidth == OPUS_BANDWIDTH_SUPERWIDEBAND) ? 3000 : 3600;
                HB_gain_ref = (curr_bandwidth == OPUS_BANDWIDTH_SUPERWIDEBAND) ? 3000 : 3600;
                HB_gain = SHL32((opus_val32)celt_rate, 9) / SHR32((opus_val32)celt_rate + st->stream_channels * HB_gain_ref, 6);
                HB_gain = SHL32((opus_val32)celt_rate, 9) / SHR32((opus_val32)celt_rate + st->stream_channels * HB_gain_ref, 6);
-               HB_gain = HB_gain < Q15ONE*6/7 ? HB_gain + Q15ONE/7 : Q15ONE;
+               HB_gain = HB_gain < (opus_val32)Q15ONE*6/7 ? HB_gain + Q15ONE/7 : Q15ONE;
             }
             }
         } else {
         } else {
             /* SILK gets all bits */
             /* SILK gets all bits */

+ 157 - 26
thirdparty/opus/opus_multistream_encoder.c

@@ -70,13 +70,22 @@ typedef void (*opus_copy_channel_in_func)(
   int frame_size
   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 {
 struct OpusMSEncoder {
    ChannelLayout layout;
    ChannelLayout layout;
    int arch;
    int arch;
    int lfe_stream;
    int lfe_stream;
    int application;
    int application;
    int variable_duration;
    int variable_duration;
-   int surround;
+   MappingType mapping_type;
    opus_int32 bitrate_bps;
    opus_int32 bitrate_bps;
    float subframe_mem[3];
    float subframe_mem[3];
    /* Encoder states go here */
    /* Encoder states go here */
@@ -242,6 +251,7 @@ void surround_analysis(const CELTMode *celt_mode, const void *pcm, opus_val16 *b
    upsample = resampling_factor(rate);
    upsample = resampling_factor(rate);
    frame_size = len*upsample;
    frame_size = len*upsample;
 
 
+   /* LM = log2(frame_size / 120) */
    for (LM=0;LM<celt_mode->maxLM;LM++)
    for (LM=0;LM<celt_mode->maxLM;LM++)
       if (celt_mode->shortMdctSize<<LM==frame_size)
       if (celt_mode->shortMdctSize<<LM==frame_size)
          break;
          break;
@@ -398,6 +408,12 @@ opus_int32 opus_multistream_surround_encoder_get_size(int channels, int mapping_
    {
    {
       nb_streams=channels;
       nb_streams=channels;
       nb_coupled_streams=0;
       nb_coupled_streams=0;
+#ifdef ENABLE_EXPERIMENTAL_AMBISONICS
+   } else if (mapping_family==254)
+   {
+      nb_streams=channels;
+      nb_coupled_streams=0;
+#endif
    } else
    } else
       return 0;
       return 0;
    size = opus_multistream_encoder_get_size(nb_streams, nb_coupled_streams);
    size = opus_multistream_encoder_get_size(nb_streams, nb_coupled_streams);
@@ -408,7 +424,6 @@ opus_int32 opus_multistream_surround_encoder_get_size(int channels, int mapping_
    return size;
    return size;
 }
 }
 
 
-
 static int opus_multistream_encoder_init_impl(
 static int opus_multistream_encoder_init_impl(
       OpusMSEncoder *st,
       OpusMSEncoder *st,
       opus_int32 Fs,
       opus_int32 Fs,
@@ -417,7 +432,7 @@ static int opus_multistream_encoder_init_impl(
       int coupled_streams,
       int coupled_streams,
       const unsigned char *mapping,
       const unsigned char *mapping,
       int application,
       int application,
-      int surround
+      MappingType mapping_type
 )
 )
 {
 {
    int coupled_size;
    int coupled_size;
@@ -434,7 +449,7 @@ static int opus_multistream_encoder_init_impl(
    st->layout.nb_streams = streams;
    st->layout.nb_streams = streams;
    st->layout.nb_coupled_streams = coupled_streams;
    st->layout.nb_coupled_streams = coupled_streams;
    st->subframe_mem[0]=st->subframe_mem[1]=st->subframe_mem[2]=0;
    st->subframe_mem[0]=st->subframe_mem[1]=st->subframe_mem[2]=0;
-   if (!surround)
+   if (mapping_type != MAPPING_TYPE_SURROUND)
       st->lfe_stream = -1;
       st->lfe_stream = -1;
    st->bitrate_bps = OPUS_AUTO;
    st->bitrate_bps = OPUS_AUTO;
    st->application = application;
    st->application = application;
@@ -463,12 +478,12 @@ static int opus_multistream_encoder_init_impl(
       if(ret!=OPUS_OK)return ret;
       if(ret!=OPUS_OK)return ret;
       ptr += align(mono_size);
       ptr += align(mono_size);
    }
    }
-   if (surround)
+   if (mapping_type == MAPPING_TYPE_SURROUND)
    {
    {
       OPUS_CLEAR(ms_get_preemph_mem(st), channels);
       OPUS_CLEAR(ms_get_preemph_mem(st), channels);
       OPUS_CLEAR(ms_get_window_mem(st), channels*120);
       OPUS_CLEAR(ms_get_window_mem(st), channels*120);
    }
    }
-   st->surround = surround;
+   st->mapping_type = mapping_type;
    return OPUS_OK;
    return OPUS_OK;
 }
 }
 
 
@@ -482,7 +497,9 @@ int opus_multistream_encoder_init(
       int application
       int application
 )
 )
 {
 {
-   return opus_multistream_encoder_init_impl(st, Fs, channels, streams, coupled_streams, mapping, application, 0);
+   return opus_multistream_encoder_init_impl(st, Fs, channels, streams,
+                                             coupled_streams, mapping,
+                                             application, MAPPING_TYPE_NONE);
 }
 }
 
 
 int opus_multistream_surround_encoder_init(
 int opus_multistream_surround_encoder_init(
@@ -496,6 +513,8 @@ int opus_multistream_surround_encoder_init(
       int application
       int application
 )
 )
 {
 {
+   MappingType mapping_type;
+
    if ((channels>255) || (channels<1))
    if ((channels>255) || (channels<1))
       return OPUS_BAD_ARG;
       return OPUS_BAD_ARG;
    st->lfe_stream = -1;
    st->lfe_stream = -1;
@@ -530,10 +549,32 @@ int opus_multistream_surround_encoder_init(
       *coupled_streams=0;
       *coupled_streams=0;
       for(i=0;i<channels;i++)
       for(i=0;i<channels;i++)
          mapping[i] = i;
          mapping[i] = i;
+#ifdef ENABLE_EXPERIMENTAL_AMBISONICS
+   } else if (mapping_family==254)
+   {
+      int i;
+      *streams=channels;
+      *coupled_streams=0;
+      for(i=0;i<channels;i++)
+         mapping[i] = i;
+#endif
    } else
    } else
       return OPUS_UNIMPLEMENTED;
       return OPUS_UNIMPLEMENTED;
-   return opus_multistream_encoder_init_impl(st, Fs, channels, *streams, *coupled_streams,
-         mapping, application, channels>2&&mapping_family==1);
+
+   if (channels>2 && mapping_family==1) {
+      mapping_type = MAPPING_TYPE_SURROUND;
+#ifdef ENABLE_EXPERIMENTAL_AMBISONICS
+   } else if (mapping_family==254)
+   {
+      mapping_type = MAPPING_TYPE_AMBISONICS;
+#endif
+   } else
+   {
+      mapping_type = MAPPING_TYPE_NONE;
+   }
+   return opus_multistream_encoder_init_impl(st, Fs, channels, *streams,
+                                             *coupled_streams, mapping,
+                                             application, mapping_type);
 }
 }
 
 
 OpusMSEncoder *opus_multistream_encoder_create(
 OpusMSEncoder *opus_multistream_encoder_create(
@@ -618,24 +659,19 @@ OpusMSEncoder *opus_multistream_surround_encoder_create(
    return st;
    return st;
 }
 }
 
 
-static opus_int32 surround_rate_allocation(
+static void surround_rate_allocation(
       OpusMSEncoder *st,
       OpusMSEncoder *st,
       opus_int32 *rate,
       opus_int32 *rate,
-      int frame_size
+      int frame_size,
+      opus_int32 Fs
       )
       )
 {
 {
    int i;
    int i;
    opus_int32 channel_rate;
    opus_int32 channel_rate;
-   opus_int32 Fs;
-   char *ptr;
    int stream_offset;
    int stream_offset;
    int lfe_offset;
    int lfe_offset;
    int coupled_ratio; /* Q8 */
    int coupled_ratio; /* Q8 */
    int lfe_ratio;     /* Q8 */
    int lfe_ratio;     /* Q8 */
-   opus_int32 rate_sum=0;
-
-   ptr = (char*)st + align(sizeof(OpusMSEncoder));
-   opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_SAMPLE_RATE(&Fs));
 
 
    if (st->bitrate_bps > st->layout.nb_channels*40000)
    if (st->bitrate_bps > st->layout.nb_channels*40000)
       stream_offset = 20000;
       stream_offset = 20000;
@@ -688,6 +724,88 @@ static opus_int32 surround_rate_allocation(
          rate[i] = stream_offset+channel_rate;
          rate[i] = stream_offset+channel_rate;
       else
       else
          rate[i] = lfe_offset+(channel_rate*lfe_ratio>>8);
          rate[i] = lfe_offset+(channel_rate*lfe_ratio>>8);
+   }
+}
+
+#ifdef ENABLE_EXPERIMENTAL_AMBISONICS
+static void ambisonics_rate_allocation(
+      OpusMSEncoder *st,
+      opus_int32 *rate,
+      int frame_size,
+      opus_int32 Fs
+      )
+{
+   int i;
+   int non_mono_rate;
+   int total_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;
+
+   if (st->bitrate_bps==OPUS_AUTO)
+   {
+      total_rate = num_channels * (20000 + st->layout.nb_streams*(Fs+60*Fs/frame_size));
+   } 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)
+   {
+      opus_int32 bonus = 60*(Fs/frame_size-50);
+      non_mono_rate += bonus;
+   }
+#endif
+
+   rate[0] = total_rate - (num_channels - 1) * non_mono_rate;
+   for (i=1;i<st->layout.nb_streams;i++)
+   {
+      rate[i] = non_mono_rate;
+   }
+}
+#endif /* ENABLE_EXPERIMENTAL_AMBISONICS */
+
+static opus_int32 rate_allocation(
+      OpusMSEncoder *st,
+      opus_int32 *rate,
+      int frame_size
+      )
+{
+   int i;
+   opus_int32 rate_sum=0;
+   opus_int32 Fs;
+   char *ptr;
+
+   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);
+   }
+
+   for (i=0;i<st->layout.nb_streams;i++)
+   {
       rate[i] = IMAX(rate[i], 500);
       rate[i] = IMAX(rate[i], 500);
       rate_sum += rate[i];
       rate_sum += rate[i];
    }
    }
@@ -730,7 +848,7 @@ static int opus_multistream_encode_native
    opus_int32 smallest_packet;
    opus_int32 smallest_packet;
    ALLOC_STACK;
    ALLOC_STACK;
 
 
-   if (st->surround)
+   if (st->mapping_type == MAPPING_TYPE_SURROUND)
    {
    {
       preemph_mem = ms_get_preemph_mem(st);
       preemph_mem = ms_get_preemph_mem(st);
       mem = ms_get_window_mem(st);
       mem = ms_get_window_mem(st);
@@ -784,13 +902,13 @@ static int opus_multistream_encode_native
    mono_size = opus_encoder_get_size(1);
    mono_size = opus_encoder_get_size(1);
 
 
    ALLOC(bandSMR, 21*st->layout.nb_channels, opus_val16);
    ALLOC(bandSMR, 21*st->layout.nb_channels, opus_val16);
-   if (st->surround)
+   if (st->mapping_type == MAPPING_TYPE_SURROUND)
    {
    {
       surround_analysis(celt_mode, pcm, bandSMR, mem, preemph_mem, frame_size, 120, st->layout.nb_channels, Fs, copy_channel_in, st->arch);
       surround_analysis(celt_mode, pcm, bandSMR, mem, preemph_mem, frame_size, 120, st->layout.nb_channels, Fs, copy_channel_in, st->arch);
    }
    }
 
 
    /* Compute bitrate allocation between streams (this could be a lot better) */
    /* Compute bitrate allocation between streams (this could be a lot better) */
-   rate_sum = surround_rate_allocation(st, bitrates, frame_size);
+   rate_sum = rate_allocation(st, bitrates, frame_size);
 
 
    if (!vbr)
    if (!vbr)
    {
    {
@@ -813,7 +931,7 @@ static int opus_multistream_encode_native
       else
       else
          ptr += align(mono_size);
          ptr += align(mono_size);
       opus_encoder_ctl(enc, OPUS_SET_BITRATE(bitrates[s]));
       opus_encoder_ctl(enc, OPUS_SET_BITRATE(bitrates[s]));
-      if (st->surround)
+      if (st->mapping_type == MAPPING_TYPE_SURROUND)
       {
       {
          opus_int32 equiv_rate;
          opus_int32 equiv_rate;
          equiv_rate = st->bitrate_bps;
          equiv_rate = st->bitrate_bps;
@@ -834,6 +952,11 @@ static int opus_multistream_encode_native
             opus_encoder_ctl(enc, OPUS_SET_FORCE_CHANNELS(2));
             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));
    ptr = (char*)st + align(sizeof(OpusMSEncoder));
@@ -845,6 +968,7 @@ static int opus_multistream_encode_native
       int len;
       int len;
       int curr_max;
       int curr_max;
       int c1, c2;
       int c1, c2;
+      int ret;
 
 
       opus_repacketizer_init(&rp);
       opus_repacketizer_init(&rp);
       enc = (OpusEncoder*)ptr;
       enc = (OpusEncoder*)ptr;
@@ -859,7 +983,7 @@ static int opus_multistream_encode_native
          (*copy_channel_in)(buf+1, 2,
          (*copy_channel_in)(buf+1, 2,
             pcm, st->layout.nb_channels, right, frame_size);
             pcm, st->layout.nb_channels, right, frame_size);
          ptr += align(coupled_size);
          ptr += align(coupled_size);
-         if (st->surround)
+         if (st->mapping_type == MAPPING_TYPE_SURROUND)
          {
          {
             for (i=0;i<21;i++)
             for (i=0;i<21;i++)
             {
             {
@@ -875,7 +999,7 @@ static int opus_multistream_encode_native
          (*copy_channel_in)(buf, 1,
          (*copy_channel_in)(buf, 1,
             pcm, st->layout.nb_channels, chan, frame_size);
             pcm, st->layout.nb_channels, chan, frame_size);
          ptr += align(mono_size);
          ptr += align(mono_size);
-         if (st->surround)
+         if (st->mapping_type == MAPPING_TYPE_SURROUND)
          {
          {
             for (i=0;i<21;i++)
             for (i=0;i<21;i++)
                bandLogE[i] = bandSMR[21*chan+i];
                bandLogE[i] = bandSMR[21*chan+i];
@@ -883,7 +1007,7 @@ static int opus_multistream_encode_native
          c1 = chan;
          c1 = chan;
          c2 = -1;
          c2 = -1;
       }
       }
-      if (st->surround)
+      if (st->mapping_type == MAPPING_TYPE_SURROUND)
          opus_encoder_ctl(enc, OPUS_SET_ENERGY_MASK(bandLogE));
          opus_encoder_ctl(enc, OPUS_SET_ENERGY_MASK(bandLogE));
       /* number of bytes left (+Toc) */
       /* number of bytes left (+Toc) */
       curr_max = max_data_bytes - tot_size;
       curr_max = max_data_bytes - tot_size;
@@ -904,7 +1028,14 @@ static int opus_multistream_encode_native
       /* We need to use the repacketizer to add the self-delimiting lengths
       /* We need to use the repacketizer to add the self-delimiting lengths
          while taking into account the fact that the encoder can now return
          while taking into account the fact that the encoder can now return
          more than one frame at a time (e.g. 60 ms CELT-only) */
          more than one frame at a time (e.g. 60 ms CELT-only) */
-      opus_repacketizer_cat(&rp, tmp_data, len);
+      ret = opus_repacketizer_cat(&rp, tmp_data, len);
+      /* If the opus_repacketizer_cat() fails, then something's seriously wrong
+         with the encoder. */
+      if (ret != OPUS_OK)
+      {
+         RESTORE_STACK;
+         return OPUS_INTERNAL_ERROR;
+      }
       len = opus_repacketizer_out_range_impl(&rp, 0, opus_repacketizer_get_nb_frames(&rp),
       len = opus_repacketizer_out_range_impl(&rp, 0, opus_repacketizer_get_nb_frames(&rp),
             data, max_data_bytes-tot_size, s != st->layout.nb_streams-1, !vbr && s == st->layout.nb_streams-1);
             data, max_data_bytes-tot_size, s != st->layout.nb_streams-1, !vbr && s == st->layout.nb_streams-1);
       data += len;
       data += len;
@@ -1183,7 +1314,7 @@ int opus_multistream_encoder_ctl(OpusMSEncoder *st, int request, ...)
    {
    {
       int s;
       int s;
       st->subframe_mem[0] = st->subframe_mem[1] = st->subframe_mem[2] = 0;
       st->subframe_mem[0] = st->subframe_mem[1] = st->subframe_mem[2] = 0;
-      if (st->surround)
+      if (st->mapping_type == MAPPING_TYPE_SURROUND)
       {
       {
          OPUS_CLEAR(ms_get_preemph_mem(st), st->layout.nb_channels);
          OPUS_CLEAR(ms_get_preemph_mem(st), st->layout.nb_channels);
          OPUS_CLEAR(ms_get_window_mem(st), st->layout.nb_channels*120);
          OPUS_CLEAR(ms_get_window_mem(st), st->layout.nb_channels*120);

+ 3 - 1
thirdparty/opus/repacketizer.c

@@ -249,7 +249,9 @@ int opus_packet_pad(unsigned char *data, opus_int32 len, opus_int32 new_len)
    opus_repacketizer_init(&rp);
    opus_repacketizer_init(&rp);
    /* Moving payload to the end of the packet so we can do in-place padding */
    /* Moving payload to the end of the packet so we can do in-place padding */
    OPUS_MOVE(data+new_len-len, data, len);
    OPUS_MOVE(data+new_len-len, data, len);
-   opus_repacketizer_cat(&rp, data+new_len-len, len);
+   ret = opus_repacketizer_cat(&rp, data+new_len-len, len);
+   if (ret != OPUS_OK)
+      return ret;
    ret = opus_repacketizer_out_range_impl(&rp, 0, rp.nb_frames, data, new_len, 0, 1);
    ret = opus_repacketizer_out_range_impl(&rp, 0, rp.nb_frames, data, new_len, 0, 1);
    if (ret > 0)
    if (ret > 0)
       return OPUS_OK;
       return OPUS_OK;