Coverage Report

Created: 2026-07-25 07:52

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/opus/src/opus.c
Line
Count
Source
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
197k
{
41
197k
   int c;
42
197k
   int i;
43
197k
   float *x;
44
197k
   int all_within_neg1pos1;
45
46
197k
   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
197k
   all_within_neg1pos1 = opus_limit2_checkwithin1(_x, N*C, arch);
67
68
556k
   for (c=0;c<C;c++)
69
359k
   {
70
359k
      float a;
71
359k
      float x0;
72
359k
      int curr;
73
74
359k
      x = _x+c;
75
359k
      a = declip_mem[c];
76
      /* Continue applying the non-linearity from the previous frame to avoid
77
         any discontinuity. */
78
653k
      for (i=0;i<N;i++)
79
653k
      {
80
653k
         if (x[i*C]*a>=0)
81
358k
            break;
82
294k
         x[i*C] = x[i*C]+a*x[i*C]*x[i*C];
83
294k
      }
84
85
359k
      curr=0;
86
359k
      x0 = x[0];
87
546k
      while(1)
88
546k
      {
89
546k
         int start, end;
90
546k
         float maxval;
91
546k
         int special=0;
92
546k
         int peak_pos;
93
         /* Detection for early exit can be skipped if hinted by `all_within_neg1pos1` */
94
546k
         if (all_within_neg1pos1)
95
0
         {
96
0
            i = N;
97
546k
         } else {
98
433M
            for (i=curr;i<N;i++)
99
432M
            {
100
432M
               if (x[i*C]>1 || x[i*C]<-1)
101
191k
                  break;
102
432M
            }
103
546k
         }
104
546k
         if (i==N)
105
354k
         {
106
354k
            a=0;
107
354k
            break;
108
354k
         }
109
191k
         peak_pos = i;
110
191k
         start=end=i;
111
191k
         maxval=ABS16(x[i*C]);
112
         /* Look for first zero crossing before clipping */
113
847k
         while (start>0 && x[i*C]*x[(start-1)*C]>=0)
114
655k
            start--;
115
         /* Look for first zero crossing after clipping */
116
3.96M
         while (end<N && x[i*C]*x[end*C]>=0)
117
3.77M
         {
118
            /* Look for other peaks until the next zero-crossing. */
119
3.77M
            if (ABS16(x[end*C])>maxval)
120
272k
            {
121
272k
               maxval = ABS16(x[end*C]);
122
272k
               peak_pos = end;
123
272k
            }
124
3.77M
            end++;
125
3.77M
         }
126
         /* Detect the special case where we clip before the first zero crossing */
127
191k
         special = (start==0 && x[i*C]*x[0]>=0);
128
129
         /* Compute a such that maxval + a*maxval^2 = 1 */
130
191k
         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
191k
         a += a*2.4e-7f;
135
191k
         if (x[i*C]>0)
136
94.8k
            a = -a;
137
         /* Apply soft clipping */
138
4.62M
         for (i=start;i<end;i++)
139
4.43M
            x[i*C] = x[i*C]+a*x[i*C]*x[i*C];
140
141
191k
         if (special && peak_pos>=2)
142
1.41k
         {
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
1.41k
            float delta;
146
1.41k
            float offset = x0-x[0];
147
1.41k
            delta = offset / peak_pos;
148
222k
            for (i=curr;i<peak_pos;i++)
149
221k
            {
150
221k
               offset -= delta;
151
221k
               x[i*C] += offset;
152
221k
               x[i*C] = MAX16(-1.f, MIN16(1.f, x[i*C]));
153
221k
            }
154
1.41k
         }
155
191k
         curr = end;
156
191k
         if (curr==N)
157
4.44k
            break;
158
191k
      }
159
359k
      declip_mem[c] = a;
160
359k
   }
161
197k
}
162
163
OPUS_EXPORT void opus_pcm_soft_clip(float *_x, int N, int C, float *declip_mem)
164
0
{
165
0
   opus_pcm_soft_clip_impl(_x, N, C, declip_mem, 0);
166
0
}
167
168
#endif
169
170
int encode_size(int size, unsigned char *data)
171
0
{
172
0
   if (size < 252)
173
0
   {
174
0
      data[0] = size;
175
0
      return 1;
176
0
   } else {
177
0
      data[0] = 252+(size&0x3);
178
0
      data[1] = (size-(int)data[0])>>2;
179
0
      return 2;
180
0
   }
181
0
}
182
183
static int parse_size(const unsigned char *data, opus_int32 len, opus_int16 *size)
184
190k
{
185
190k
   if (len<1)
186
6.66k
   {
187
6.66k
      *size = -1;
188
6.66k
      return -1;
189
184k
   } else if (data[0]<252)
190
181k
   {
191
181k
      *size = data[0];
192
181k
      return 1;
193
181k
   } else if (len<2)
194
917
   {
195
917
      *size = -1;
196
917
      return -1;
197
1.97k
   } else {
198
1.97k
      *size = 4*data[1] + data[0];
199
1.97k
      return 2;
200
1.97k
   }
201
190k
}
202
203
int opus_packet_get_samples_per_frame(const unsigned char *data,
204
      opus_int32 Fs)
205
852k
{
206
852k
   int audiosize;
207
852k
   if (data[0]&0x80)
208
121k
   {
209
121k
      audiosize = ((data[0]>>3)&0x3);
210
121k
      audiosize = (Fs<<audiosize)/400;
211
731k
   } else if ((data[0]&0x60) == 0x60)
212
61.5k
   {
213
61.5k
      audiosize = (data[0]&0x08) ? Fs/50 : Fs/100;
214
670k
   } else {
215
670k
      audiosize = ((data[0]>>3)&0x3);
216
670k
      if (audiosize == 3)
217
23.2k
         audiosize = Fs*60/1000;
218
646k
      else
219
646k
         audiosize = (Fs<<audiosize)/100;
220
670k
   }
221
852k
   return audiosize;
222
852k
}
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
443k
{
230
443k
   int i, bytes;
231
443k
   int count;
232
443k
   int cbr;
233
443k
   unsigned char ch, toc;
234
443k
   int framesize;
235
443k
   opus_int32 last_size;
236
443k
   opus_int32 pad = 0;
237
443k
   const unsigned char *data0 = data;
238
239
   /* Make sure we return NULL/0 on error. */
240
443k
   if (padding != NULL)
241
197k
   {
242
197k
      *padding = NULL;
243
197k
      *padding_len = 0;
244
197k
   }
245
246
443k
   if (size==NULL || len<0)
247
0
      return OPUS_BAD_ARG;
248
443k
   if (len==0)
249
0
      return OPUS_INVALID_PACKET;
250
251
443k
   framesize = opus_packet_get_samples_per_frame(data, 48000);
252
253
443k
   cbr = 0;
254
443k
   toc = *data++;
255
443k
   len--;
256
443k
   last_size = len;
257
443k
   switch (toc&0x3)
258
443k
   {
259
   /* One frame */
260
184k
   case 0:
261
184k
      count=1;
262
184k
      break;
263
   /* Two CBR frames */
264
159k
   case 1:
265
159k
      count=2;
266
159k
      cbr = 1;
267
159k
      if (!self_delimited)
268
155k
      {
269
155k
         if (len&0x1)
270
1.97k
            return OPUS_INVALID_PACKET;
271
153k
         last_size = len/2;
272
         /* If last_size doesn't fit in size[0], we'll catch it later */
273
153k
         size[0] = (opus_int16)last_size;
274
153k
      }
275
157k
      break;
276
   /* Two VBR frames */
277
157k
   case 2:
278
49.6k
      count = 2;
279
49.6k
      bytes = parse_size(data, len, size);
280
49.6k
      len -= bytes;
281
49.6k
      if (size[0]<0 || size[0] > len)
282
9.94k
         return OPUS_INVALID_PACKET;
283
39.6k
      data += bytes;
284
39.6k
      last_size = len-size[0];
285
39.6k
      break;
286
   /* Multiple CBR/VBR frames (from 0 to 120 ms) */
287
49.9k
   default: /*case 3:*/
288
49.9k
      if (len<1)
289
6.41k
         return OPUS_INVALID_PACKET;
290
      /* Number of frames encoded in bits 0 to 5 */
291
43.4k
      ch = *data++;
292
43.4k
      count = ch&0x3F;
293
43.4k
      if (count <= 0 || framesize*(opus_int32)count > 5760)
294
9.00k
         return OPUS_INVALID_PACKET;
295
34.4k
      len--;
296
      /* Padding flag is bit 6 */
297
34.4k
      if (ch&0x40)
298
5.88k
      {
299
5.88k
         int p;
300
6.72k
         do {
301
6.72k
            int tmp;
302
6.72k
            if (len<=0)
303
447
               return OPUS_INVALID_PACKET;
304
6.27k
            p = *data++;
305
6.27k
            len--;
306
6.27k
            tmp = p==255 ? 254: p;
307
6.27k
            len -= tmp;
308
6.27k
            pad += tmp;
309
6.27k
         } while (p==255);
310
5.88k
      }
311
34.0k
      if (len<0)
312
765
         return OPUS_INVALID_PACKET;
313
      /* VBR flag is bit 7 */
314
33.2k
      cbr = !(ch&0x80);
315
33.2k
      if (!cbr)
316
26.2k
      {
317
         /* VBR case */
318
26.2k
         last_size = len;
319
142k
         for (i=0;i<count-1;i++)
320
117k
         {
321
117k
            bytes = parse_size(data, len, size+i);
322
117k
            len -= bytes;
323
117k
            if (size[i]<0 || size[i] > len)
324
1.34k
               return OPUS_INVALID_PACKET;
325
116k
            data += bytes;
326
116k
            last_size -= bytes+size[i];
327
116k
         }
328
24.9k
         if (last_size<0)
329
284
            return OPUS_INVALID_PACKET;
330
24.9k
      } else if (!self_delimited)
331
6.13k
      {
332
         /* CBR case */
333
6.13k
         last_size = len/count;
334
6.13k
         if (last_size*count!=len)
335
890
            return OPUS_INVALID_PACKET;
336
63.3k
         for (i=0;i<count-1;i++)
337
58.1k
            size[i] = (opus_int16)last_size;
338
5.24k
      }
339
30.7k
      break;
340
443k
   }
341
   /* Self-delimited framing has an extra size for the last frame. */
342
412k
   if (self_delimited)
343
23.3k
   {
344
23.3k
      bytes = parse_size(data, len, size+count-1);
345
23.3k
      len -= bytes;
346
23.3k
      if (size[count-1]<0 || size[count-1] > len)
347
2.03k
         return OPUS_INVALID_PACKET;
348
21.3k
      data += bytes;
349
      /* For CBR packets, apply the size to all the frames. */
350
21.3k
      if (cbr)
351
4.67k
      {
352
4.67k
         if (size[count-1]*count > len)
353
409
            return OPUS_INVALID_PACKET;
354
9.05k
         for (i=0;i<count-1;i++)
355
4.78k
            size[i] = size[count-1];
356
16.6k
      } else if (bytes+size[count-1] > last_size)
357
233
         return OPUS_INVALID_PACKET;
358
21.3k
   } else
359
389k
   {
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
389k
      if (last_size > 1275)
364
307
         return OPUS_INVALID_PACKET;
365
388k
      size[count-1] = (opus_int16)last_size;
366
388k
   }
367
368
409k
   if (payload_offset)
369
197k
      *payload_offset = (int)(data-data0);
370
371
1.18M
   for (i=0;i<count;i++)
372
771k
   {
373
771k
      if (frames)
374
0
         frames[i] = data;
375
771k
      data += size[i];
376
771k
   }
377
378
409k
   if (padding != NULL)
379
197k
   {
380
197k
      *padding = data;
381
197k
      *padding_len = pad;
382
197k
   }
383
409k
   if (packet_offset)
384
409k
      *packet_offset = pad+(opus_int32)(data-data0);
385
386
409k
   if (out_toc)
387
409k
      *out_toc = toc;
388
389
409k
   return count;
390
412k
}
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
0
{
396
0
   return opus_packet_parse_impl(data, len, 0, out_toc,
397
0
                                 frames, size, payload_offset, NULL, NULL, NULL);
398
0
}