tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

opus.c (11274B)


      1 /* Copyright (c) 2011 Xiph.Org Foundation, Skype Limited
      2   Copyright (c) 2024 Arm Limited
      3   Written by Jean-Marc Valin and Koen Vos */
      4 /*
      5   Redistribution and use in source and binary forms, with or without
      6   modification, are permitted provided that the following conditions
      7   are met:
      8 
      9   - Redistributions of source code must retain the above copyright
     10   notice, this list of conditions and the following disclaimer.
     11 
     12   - Redistributions in binary form must reproduce the above copyright
     13   notice, this list of conditions and the following disclaimer in the
     14   documentation and/or other materials provided with the distribution.
     15 
     16   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     17   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     18   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     19   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
     20   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     21   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     22   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     23   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
     24   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
     25   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
     26   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27 */
     28 
     29 #ifdef HAVE_CONFIG_H
     30 #include "config.h"
     31 #endif
     32 
     33 #include "opus.h"
     34 #include "mathops.h"
     35 #include "opus_private.h"
     36 
     37 #ifndef DISABLE_FLOAT_API
     38 
     39 void opus_pcm_soft_clip_impl(float *_x, int N, int C, float *declip_mem, int arch)
     40 {
     41   int c;
     42   int i;
     43   float *x;
     44   int all_within_neg1pos1;
     45 
     46   if (C<1 || N<1 || !_x || !declip_mem) return;
     47 
     48   /* Clamp everything within the range [-2, +2] which is the domain of the soft
     49      clipping non-linearity. Outside the defined range the derivative will be zero,
     50      therefore there is no discontinuity introduced here. The implementation
     51      might provide a hint if all input samples are within the [-1, +1] range.
     52 
     53   `opus_limit2_checkwithin1()`:
     54      - Clamps all samples within the valid range [-2, +2].
     55      - Generic C implementation:
     56         * Does not attempt early detection whether samples are within hinted range.
     57         * Always returns 0.
     58      - Architecture specific implementation:
     59         * Uses SIMD instructions to efficiently detect if all samples are
     60           within the hinted range [-1, +1].
     61         * Returns 1 if no samples exceed the hinted range, 0 otherwise.
     62 
     63   `all_within_neg1pos1`:
     64      - Optimization hint to skip per-sample out-of-bound checks.
     65        If true, the check can be skipped. */
     66   all_within_neg1pos1 = opus_limit2_checkwithin1(_x, N*C, arch);
     67 
     68   for (c=0;c<C;c++)
     69   {
     70      float a;
     71      float x0;
     72      int curr;
     73 
     74      x = _x+c;
     75      a = declip_mem[c];
     76      /* Continue applying the non-linearity from the previous frame to avoid
     77         any discontinuity. */
     78      for (i=0;i<N;i++)
     79      {
     80         if (x[i*C]*a>=0)
     81            break;
     82         x[i*C] = x[i*C]+a*x[i*C]*x[i*C];
     83      }
     84 
     85      curr=0;
     86      x0 = x[0];
     87      while(1)
     88      {
     89         int start, end;
     90         float maxval;
     91         int special=0;
     92         int peak_pos;
     93         /* Detection for early exit can be skipped if hinted by `all_within_neg1pos1` */
     94         if (all_within_neg1pos1)
     95         {
     96            i = N;
     97         } else {
     98            for (i=curr;i<N;i++)
     99            {
    100               if (x[i*C]>1 || x[i*C]<-1)
    101                  break;
    102            }
    103         }
    104         if (i==N)
    105         {
    106            a=0;
    107            break;
    108         }
    109         peak_pos = i;
    110         start=end=i;
    111         maxval=ABS16(x[i*C]);
    112         /* Look for first zero crossing before clipping */
    113         while (start>0 && x[i*C]*x[(start-1)*C]>=0)
    114            start--;
    115         /* Look for first zero crossing after clipping */
    116         while (end<N && x[i*C]*x[end*C]>=0)
    117         {
    118            /* Look for other peaks until the next zero-crossing. */
    119            if (ABS16(x[end*C])>maxval)
    120            {
    121               maxval = ABS16(x[end*C]);
    122               peak_pos = end;
    123            }
    124            end++;
    125         }
    126         /* Detect the special case where we clip before the first zero crossing */
    127         special = (start==0 && x[i*C]*x[0]>=0);
    128 
    129         /* Compute a such that maxval + a*maxval^2 = 1 */
    130         a=(maxval-1)/(maxval*maxval);
    131         /* Slightly boost "a" by 2^-22. This is just enough to ensure -ffast-math
    132            does not cause output values larger than +/-1, but small enough not
    133            to matter even for 24-bit output.  */
    134         a += a*2.4e-7f;
    135         if (x[i*C]>0)
    136            a = -a;
    137         /* Apply soft clipping */
    138         for (i=start;i<end;i++)
    139            x[i*C] = x[i*C]+a*x[i*C]*x[i*C];
    140 
    141         if (special && peak_pos>=2)
    142         {
    143            /* Add a linear ramp from the first sample to the signal peak.
    144               This avoids a discontinuity at the beginning of the frame. */
    145            float delta;
    146            float offset = x0-x[0];
    147            delta = offset / peak_pos;
    148            for (i=curr;i<peak_pos;i++)
    149            {
    150               offset -= delta;
    151               x[i*C] += offset;
    152               x[i*C] = MAX16(-1.f, MIN16(1.f, x[i*C]));
    153            }
    154         }
    155         curr = end;
    156         if (curr==N)
    157            break;
    158      }
    159      declip_mem[c] = a;
    160   }
    161 }
    162 
    163 OPUS_EXPORT void opus_pcm_soft_clip(float *_x, int N, int C, float *declip_mem)
    164 {
    165   opus_pcm_soft_clip_impl(_x, N, C, declip_mem, 0);
    166 }
    167 
    168 #endif
    169 
    170 int encode_size(int size, unsigned char *data)
    171 {
    172   if (size < 252)
    173   {
    174      data[0] = size;
    175      return 1;
    176   } else {
    177      data[0] = 252+(size&0x3);
    178      data[1] = (size-(int)data[0])>>2;
    179      return 2;
    180   }
    181 }
    182 
    183 static int parse_size(const unsigned char *data, opus_int32 len, opus_int16 *size)
    184 {
    185   if (len<1)
    186   {
    187      *size = -1;
    188      return -1;
    189   } else if (data[0]<252)
    190   {
    191      *size = data[0];
    192      return 1;
    193   } else if (len<2)
    194   {
    195      *size = -1;
    196      return -1;
    197   } else {
    198      *size = 4*data[1] + data[0];
    199      return 2;
    200   }
    201 }
    202 
    203 int opus_packet_get_samples_per_frame(const unsigned char *data,
    204      opus_int32 Fs)
    205 {
    206   int audiosize;
    207   if (data[0]&0x80)
    208   {
    209      audiosize = ((data[0]>>3)&0x3);
    210      audiosize = (Fs<<audiosize)/400;
    211   } else if ((data[0]&0x60) == 0x60)
    212   {
    213      audiosize = (data[0]&0x08) ? Fs/50 : Fs/100;
    214   } else {
    215      audiosize = ((data[0]>>3)&0x3);
    216      if (audiosize == 3)
    217         audiosize = Fs*60/1000;
    218      else
    219         audiosize = (Fs<<audiosize)/100;
    220   }
    221   return audiosize;
    222 }
    223 
    224 int opus_packet_parse_impl(const unsigned char *data, opus_int32 len,
    225      int self_delimited, unsigned char *out_toc,
    226      const unsigned char *frames[48], opus_int16 size[48],
    227      int *payload_offset, opus_int32 *packet_offset,
    228      const unsigned char **padding, opus_int32 *padding_len)
    229 {
    230   int i, bytes;
    231   int count;
    232   int cbr;
    233   unsigned char ch, toc;
    234   int framesize;
    235   opus_int32 last_size;
    236   opus_int32 pad = 0;
    237   const unsigned char *data0 = data;
    238 
    239   /* Make sure we return NULL/0 on error. */
    240   if (padding != NULL)
    241   {
    242      *padding = NULL;
    243      *padding_len = 0;
    244   }
    245 
    246   if (size==NULL || len<0)
    247      return OPUS_BAD_ARG;
    248   if (len==0)
    249      return OPUS_INVALID_PACKET;
    250 
    251   framesize = opus_packet_get_samples_per_frame(data, 48000);
    252 
    253   cbr = 0;
    254   toc = *data++;
    255   len--;
    256   last_size = len;
    257   switch (toc&0x3)
    258   {
    259   /* One frame */
    260   case 0:
    261      count=1;
    262      break;
    263   /* Two CBR frames */
    264   case 1:
    265      count=2;
    266      cbr = 1;
    267      if (!self_delimited)
    268      {
    269         if (len&0x1)
    270            return OPUS_INVALID_PACKET;
    271         last_size = len/2;
    272         /* If last_size doesn't fit in size[0], we'll catch it later */
    273         size[0] = (opus_int16)last_size;
    274      }
    275      break;
    276   /* Two VBR frames */
    277   case 2:
    278      count = 2;
    279      bytes = parse_size(data, len, size);
    280      len -= bytes;
    281      if (size[0]<0 || size[0] > len)
    282         return OPUS_INVALID_PACKET;
    283      data += bytes;
    284      last_size = len-size[0];
    285      break;
    286   /* Multiple CBR/VBR frames (from 0 to 120 ms) */
    287   default: /*case 3:*/
    288      if (len<1)
    289         return OPUS_INVALID_PACKET;
    290      /* Number of frames encoded in bits 0 to 5 */
    291      ch = *data++;
    292      count = ch&0x3F;
    293      if (count <= 0 || framesize*(opus_int32)count > 5760)
    294         return OPUS_INVALID_PACKET;
    295      len--;
    296      /* Padding flag is bit 6 */
    297      if (ch&0x40)
    298      {
    299         int p;
    300         do {
    301            int tmp;
    302            if (len<=0)
    303               return OPUS_INVALID_PACKET;
    304            p = *data++;
    305            len--;
    306            tmp = p==255 ? 254: p;
    307            len -= tmp;
    308            pad += tmp;
    309         } while (p==255);
    310      }
    311      if (len<0)
    312         return OPUS_INVALID_PACKET;
    313      /* VBR flag is bit 7 */
    314      cbr = !(ch&0x80);
    315      if (!cbr)
    316      {
    317         /* VBR case */
    318         last_size = len;
    319         for (i=0;i<count-1;i++)
    320         {
    321            bytes = parse_size(data, len, size+i);
    322            len -= bytes;
    323            if (size[i]<0 || size[i] > len)
    324               return OPUS_INVALID_PACKET;
    325            data += bytes;
    326            last_size -= bytes+size[i];
    327         }
    328         if (last_size<0)
    329            return OPUS_INVALID_PACKET;
    330      } else if (!self_delimited)
    331      {
    332         /* CBR case */
    333         last_size = len/count;
    334         if (last_size*count!=len)
    335            return OPUS_INVALID_PACKET;
    336         for (i=0;i<count-1;i++)
    337            size[i] = (opus_int16)last_size;
    338      }
    339      break;
    340   }
    341   /* Self-delimited framing has an extra size for the last frame. */
    342   if (self_delimited)
    343   {
    344      bytes = parse_size(data, len, size+count-1);
    345      len -= bytes;
    346      if (size[count-1]<0 || size[count-1] > len)
    347         return OPUS_INVALID_PACKET;
    348      data += bytes;
    349      /* For CBR packets, apply the size to all the frames. */
    350      if (cbr)
    351      {
    352         if (size[count-1]*count > len)
    353            return OPUS_INVALID_PACKET;
    354         for (i=0;i<count-1;i++)
    355            size[i] = size[count-1];
    356      } else if (bytes+size[count-1] > last_size)
    357         return OPUS_INVALID_PACKET;
    358   } else
    359   {
    360      /* Because it's not encoded explicitly, it's possible the size of the
    361         last packet (or all the packets, for the CBR case) is larger than
    362         1275. Reject them here.*/
    363      if (last_size > 1275)
    364         return OPUS_INVALID_PACKET;
    365      size[count-1] = (opus_int16)last_size;
    366   }
    367 
    368   if (payload_offset)
    369      *payload_offset = (int)(data-data0);
    370 
    371   for (i=0;i<count;i++)
    372   {
    373      if (frames)
    374         frames[i] = data;
    375      data += size[i];
    376   }
    377 
    378   if (padding != NULL)
    379   {
    380      *padding = data;
    381      *padding_len = pad;
    382   }
    383   if (packet_offset)
    384      *packet_offset = pad+(opus_int32)(data-data0);
    385 
    386   if (out_toc)
    387      *out_toc = toc;
    388 
    389   return count;
    390 }
    391 
    392 int opus_packet_parse(const unsigned char *data, opus_int32 len,
    393      unsigned char *out_toc, const unsigned char *frames[48],
    394      opus_int16 size[48], int *payload_offset)
    395 {
    396   return opus_packet_parse_impl(data, len, 0, out_toc,
    397                                 frames, size, payload_offset, NULL, NULL, NULL);
    398 }