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 | } |