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 | 0 | { |
41 | 0 | int c; |
42 | 0 | int i; |
43 | 0 | float *x; |
44 | 0 | int all_within_neg1pos1; |
45 | |
|
46 | 0 | 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 | 0 | all_within_neg1pos1 = opus_limit2_checkwithin1(_x, N*C, arch); |
67 | |
|
68 | 0 | for (c=0;c<C;c++) |
69 | 0 | { |
70 | 0 | float a; |
71 | 0 | float x0; |
72 | 0 | int curr; |
73 | |
|
74 | 0 | x = _x+c; |
75 | 0 | a = declip_mem[c]; |
76 | | /* Continue applying the non-linearity from the previous frame to avoid |
77 | | any discontinuity. */ |
78 | 0 | for (i=0;i<N;i++) |
79 | 0 | { |
80 | 0 | if (x[i*C]*a>=0) |
81 | 0 | break; |
82 | 0 | x[i*C] = x[i*C]+a*x[i*C]*x[i*C]; |
83 | 0 | } |
84 | |
|
85 | 0 | curr=0; |
86 | 0 | x0 = x[0]; |
87 | 0 | while(1) |
88 | 0 | { |
89 | 0 | int start, end; |
90 | 0 | float maxval; |
91 | 0 | int special=0; |
92 | 0 | int peak_pos; |
93 | | /* Detection for early exit can be skipped if hinted by `all_within_neg1pos1` */ |
94 | 0 | if (all_within_neg1pos1) |
95 | 0 | { |
96 | 0 | i = N; |
97 | 0 | } else { |
98 | 0 | for (i=curr;i<N;i++) |
99 | 0 | { |
100 | 0 | if (x[i*C]>1 || x[i*C]<-1) |
101 | 0 | break; |
102 | 0 | } |
103 | 0 | } |
104 | 0 | if (i==N) |
105 | 0 | { |
106 | 0 | a=0; |
107 | 0 | break; |
108 | 0 | } |
109 | 0 | peak_pos = i; |
110 | 0 | start=end=i; |
111 | 0 | maxval=ABS16(x[i*C]); |
112 | | /* Look for first zero crossing before clipping */ |
113 | 0 | while (start>0 && x[i*C]*x[(start-1)*C]>=0) |
114 | 0 | start--; |
115 | | /* Look for first zero crossing after clipping */ |
116 | 0 | while (end<N && x[i*C]*x[end*C]>=0) |
117 | 0 | { |
118 | | /* Look for other peaks until the next zero-crossing. */ |
119 | 0 | if (ABS16(x[end*C])>maxval) |
120 | 0 | { |
121 | 0 | maxval = ABS16(x[end*C]); |
122 | 0 | peak_pos = end; |
123 | 0 | } |
124 | 0 | end++; |
125 | 0 | } |
126 | | /* Detect the special case where we clip before the first zero crossing */ |
127 | 0 | special = (start==0 && x[i*C]*x[0]>=0); |
128 | | |
129 | | /* Compute a such that maxval + a*maxval^2 = 1 */ |
130 | 0 | 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 | 0 | a += a*2.4e-7f; |
135 | 0 | if (x[i*C]>0) |
136 | 0 | a = -a; |
137 | | /* Apply soft clipping */ |
138 | 0 | for (i=start;i<end;i++) |
139 | 0 | x[i*C] = x[i*C]+a*x[i*C]*x[i*C]; |
140 | |
|
141 | 0 | if (special && peak_pos>=2) |
142 | 0 | { |
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 | 0 | float delta; |
146 | 0 | float offset = x0-x[0]; |
147 | 0 | delta = offset / peak_pos; |
148 | 0 | for (i=curr;i<peak_pos;i++) |
149 | 0 | { |
150 | 0 | offset -= delta; |
151 | 0 | x[i*C] += offset; |
152 | 0 | x[i*C] = MAX16(-1.f, MIN16(1.f, x[i*C])); |
153 | 0 | } |
154 | 0 | } |
155 | 0 | curr = end; |
156 | 0 | if (curr==N) |
157 | 0 | break; |
158 | 0 | } |
159 | 0 | declip_mem[c] = a; |
160 | 0 | } |
161 | 0 | } |
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 | 1.34k | { |
172 | 1.34k | if (size < 252) |
173 | 1.22k | { |
174 | 1.22k | data[0] = size; |
175 | 1.22k | return 1; |
176 | 1.22k | } else { |
177 | 123 | data[0] = 252+(size&0x3); |
178 | 123 | data[1] = (size-(int)data[0])>>2; |
179 | 123 | return 2; |
180 | 123 | } |
181 | 1.34k | } |
182 | | |
183 | | static int parse_size(const unsigned char *data, opus_int32 len, opus_int16 *size) |
184 | 2.30k | { |
185 | 2.30k | if (len<1) |
186 | 379 | { |
187 | 379 | *size = -1; |
188 | 379 | return -1; |
189 | 1.92k | } else if (data[0]<252) |
190 | 1.39k | { |
191 | 1.39k | *size = data[0]; |
192 | 1.39k | return 1; |
193 | 1.39k | } else if (len<2) |
194 | 134 | { |
195 | 134 | *size = -1; |
196 | 134 | return -1; |
197 | 393 | } else { |
198 | 393 | *size = 4*data[1] + data[0]; |
199 | 393 | return 2; |
200 | 393 | } |
201 | 2.30k | } |
202 | | |
203 | | int opus_packet_get_samples_per_frame(const unsigned char *data, |
204 | | opus_int32 Fs) |
205 | 7.67k | { |
206 | 7.67k | int audiosize; |
207 | 7.67k | if (data[0]&0x80) |
208 | 5.19k | { |
209 | 5.19k | audiosize = ((data[0]>>3)&0x3); |
210 | 5.19k | audiosize = (Fs<<audiosize)/400; |
211 | 5.19k | } else if ((data[0]&0x60) == 0x60) |
212 | 873 | { |
213 | 873 | audiosize = (data[0]&0x08) ? Fs/50 : Fs/100; |
214 | 1.60k | } else { |
215 | 1.60k | audiosize = ((data[0]>>3)&0x3); |
216 | 1.60k | if (audiosize == 3) |
217 | 406 | audiosize = Fs*60/1000; |
218 | 1.19k | else |
219 | 1.19k | audiosize = (Fs<<audiosize)/100; |
220 | 1.60k | } |
221 | 7.67k | return audiosize; |
222 | 7.67k | } |
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 | 4.84k | { |
230 | 4.84k | int i, bytes; |
231 | 4.84k | int count; |
232 | 4.84k | int cbr; |
233 | 4.84k | unsigned char ch, toc; |
234 | 4.84k | int framesize; |
235 | 4.84k | opus_int32 last_size; |
236 | 4.84k | opus_int32 pad = 0; |
237 | 4.84k | const unsigned char *data0 = data; |
238 | | |
239 | | /* Make sure we return NULL/0 on error. */ |
240 | 4.84k | if (padding != NULL) |
241 | 4.84k | { |
242 | 4.84k | *padding = NULL; |
243 | 4.84k | *padding_len = 0; |
244 | 4.84k | } |
245 | | |
246 | 4.84k | if (size==NULL || len<0) |
247 | 0 | return OPUS_BAD_ARG; |
248 | 4.84k | if (len==0) |
249 | 0 | return OPUS_INVALID_PACKET; |
250 | | |
251 | 4.84k | framesize = opus_packet_get_samples_per_frame(data, 48000); |
252 | | |
253 | 4.84k | cbr = 0; |
254 | 4.84k | toc = *data++; |
255 | 4.84k | len--; |
256 | 4.84k | last_size = len; |
257 | 4.84k | switch (toc&0x3) |
258 | 4.84k | { |
259 | | /* One frame */ |
260 | 326 | case 0: |
261 | 326 | count=1; |
262 | 326 | break; |
263 | | /* Two CBR frames */ |
264 | 300 | case 1: |
265 | 300 | count=2; |
266 | 300 | cbr = 1; |
267 | 300 | if (!self_delimited) |
268 | 300 | { |
269 | 300 | if (len&0x1) |
270 | 73 | return OPUS_INVALID_PACKET; |
271 | 227 | last_size = len/2; |
272 | | /* If last_size doesn't fit in size[0], we'll catch it later */ |
273 | 227 | size[0] = (opus_int16)last_size; |
274 | 227 | } |
275 | 227 | break; |
276 | | /* Two VBR frames */ |
277 | 716 | case 2: |
278 | 716 | count = 2; |
279 | 716 | bytes = parse_size(data, len, size); |
280 | 716 | len -= bytes; |
281 | 716 | if (size[0]<0 || size[0] > len) |
282 | 522 | return OPUS_INVALID_PACKET; |
283 | 194 | data += bytes; |
284 | 194 | last_size = len-size[0]; |
285 | 194 | break; |
286 | | /* Multiple CBR/VBR frames (from 0 to 120 ms) */ |
287 | 3.50k | default: /*case 3:*/ |
288 | 3.50k | if (len<1) |
289 | 0 | return OPUS_INVALID_PACKET; |
290 | | /* Number of frames encoded in bits 0 to 5 */ |
291 | 3.50k | ch = *data++; |
292 | 3.50k | count = ch&0x3F; |
293 | 3.50k | if (count <= 0 || framesize*(opus_int32)count > 5760) |
294 | 0 | return OPUS_INVALID_PACKET; |
295 | 3.50k | len--; |
296 | | /* Padding flag is bit 6 */ |
297 | 3.50k | if (ch&0x40) |
298 | 2.00k | { |
299 | 2.00k | int p; |
300 | 3.11k | do { |
301 | 3.11k | int tmp; |
302 | 3.11k | if (len<=0) |
303 | 200 | return OPUS_INVALID_PACKET; |
304 | 2.91k | p = *data++; |
305 | 2.91k | len--; |
306 | 2.91k | tmp = p==255 ? 254: p; |
307 | 2.91k | len -= tmp; |
308 | 2.91k | pad += tmp; |
309 | 2.91k | } while (p==255); |
310 | 2.00k | } |
311 | 3.30k | if (len<0) |
312 | 88 | return OPUS_INVALID_PACKET; |
313 | | /* VBR flag is bit 7 */ |
314 | 3.21k | cbr = !(ch&0x80); |
315 | 3.21k | if (!cbr) |
316 | 1.02k | { |
317 | | /* VBR case */ |
318 | 1.02k | last_size = len; |
319 | 2.29k | for (i=0;i<count-1;i++) |
320 | 1.58k | { |
321 | 1.58k | bytes = parse_size(data, len, size+i); |
322 | 1.58k | len -= bytes; |
323 | 1.58k | if (size[i]<0 || size[i] > len) |
324 | 317 | return OPUS_INVALID_PACKET; |
325 | 1.27k | data += bytes; |
326 | 1.27k | last_size -= bytes+size[i]; |
327 | 1.27k | } |
328 | 708 | if (last_size<0) |
329 | 96 | return OPUS_INVALID_PACKET; |
330 | 2.18k | } else if (!self_delimited) |
331 | 2.18k | { |
332 | | /* CBR case */ |
333 | 2.18k | last_size = len/count; |
334 | 2.18k | if (last_size*count!=len) |
335 | 118 | return OPUS_INVALID_PACKET; |
336 | 21.9k | for (i=0;i<count-1;i++) |
337 | 19.8k | size[i] = (opus_int16)last_size; |
338 | 2.07k | } |
339 | 2.68k | break; |
340 | 4.84k | } |
341 | | /* Self-delimited framing has an extra size for the last frame. */ |
342 | 3.43k | if (self_delimited) |
343 | 0 | { |
344 | 0 | bytes = parse_size(data, len, size+count-1); |
345 | 0 | len -= bytes; |
346 | 0 | if (size[count-1]<0 || size[count-1] > len) |
347 | 0 | return OPUS_INVALID_PACKET; |
348 | 0 | data += bytes; |
349 | | /* For CBR packets, apply the size to all the frames. */ |
350 | 0 | if (cbr) |
351 | 0 | { |
352 | 0 | if (size[count-1]*count > len) |
353 | 0 | return OPUS_INVALID_PACKET; |
354 | 0 | for (i=0;i<count-1;i++) |
355 | 0 | size[i] = size[count-1]; |
356 | 0 | } else if (bytes+size[count-1] > last_size) |
357 | 0 | return OPUS_INVALID_PACKET; |
358 | 0 | } else |
359 | 3.43k | { |
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 | 3.43k | if (last_size > 1275) |
364 | 79 | return OPUS_INVALID_PACKET; |
365 | 3.35k | size[count-1] = (opus_int16)last_size; |
366 | 3.35k | } |
367 | | |
368 | 3.35k | if (payload_offset) |
369 | 0 | *payload_offset = (int)(data-data0); |
370 | | |
371 | 27.2k | for (i=0;i<count;i++) |
372 | 23.8k | { |
373 | 23.8k | if (frames) |
374 | 23.8k | frames[i] = data; |
375 | 23.8k | data += size[i]; |
376 | 23.8k | } |
377 | | |
378 | 3.35k | if (padding != NULL) |
379 | 3.35k | { |
380 | 3.35k | *padding = data; |
381 | 3.35k | *padding_len = pad; |
382 | 3.35k | } |
383 | 3.35k | if (packet_offset) |
384 | 0 | *packet_offset = pad+(opus_int32)(data-data0); |
385 | | |
386 | 3.35k | if (out_toc) |
387 | 3.35k | *out_toc = toc; |
388 | | |
389 | 3.35k | return count; |
390 | 3.43k | } |
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 | } |