annotate src/opus-1.3/src/opus.c @ 81:7029a4916348

Merge build update
author Chris Cannam
date Thu, 31 Oct 2019 13:36:58 +0000
parents 7aeed7906520
children
rev   line source
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