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