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