blob: 9c0eb9c72858d5a8f4dc4da6b9f31eb2caebc41e [file] [log] [blame]
tlegrand@google.com3c3902f2013-12-09 08:35:25 +00001/* Copyright (c) 2011-2013 Xiph.Org Foundation
sergeyu@chromium.org885f2ff2012-10-17 22:31:52 +00002 Written by Gregory Maxwell */
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 <stdio.h>
33#include <stdlib.h>
34#include <limits.h>
35#include <stdint.h>
36#include <math.h>
37#include <string.h>
38#include <time.h>
39#if (!defined WIN32 && !defined _WIN32) || defined(__MINGW32__)
40#include <unistd.h>
sergeyu@chromium.org6b6bee22013-02-28 21:17:26 +000041#else
42#include <process.h>
43#define getpid _getpid
sergeyu@chromium.org885f2ff2012-10-17 22:31:52 +000044#endif
45#include "opus.h"
46#include "test_opus_common.h"
47
48#define MAX_PACKET (1500)
49#define MAX_FRAME_SAMP (5760)
sergeyu@chromium.org885f2ff2012-10-17 22:31:52 +000050
51int test_decoder_code0(int no_fuzz)
52{
53 static const opus_int32 fsv[5]={48000,24000,16000,12000,8000};
54 int err,skip,plen;
55 int out_samples,fec;
56 int t;
57 opus_int32 i;
58 OpusDecoder *dec[5*2];
59 opus_int32 decsize;
60 OpusDecoder *decbak;
61 opus_uint32 dec_final_range1,dec_final_range2,dec_final_acc;
62 unsigned char *packet;
63 unsigned char modes[4096];
64 short *outbuf_int;
65 short *outbuf;
66
67 dec_final_range1=dec_final_range2=2;
68
69 packet=malloc(sizeof(unsigned char)*MAX_PACKET);
70 if(packet==NULL)test_failed();
71
72 outbuf_int=malloc(sizeof(short)*(MAX_FRAME_SAMP+16)*2);
73 for(i=0;i<(MAX_FRAME_SAMP+16)*2;i++)outbuf_int[i]=32749;
74 outbuf=&outbuf_int[8*2];
75
76 fprintf(stdout," Starting %d decoders...\n",5*2);
77 for(t=0;t<5*2;t++)
78 {
79 int fs=fsv[t>>1];
80 int c=(t&1)+1;
81 err=OPUS_INTERNAL_ERROR;
82 dec[t] = opus_decoder_create(fs, c, &err);
83 if(err!=OPUS_OK || dec[t]==NULL)test_failed();
84 fprintf(stdout," opus_decoder_create(%5d,%d) OK. Copy ",fs,c);
85 {
86 OpusDecoder *dec2;
87 /*The opus state structures contain no pointers and can be freely copied*/
88 dec2=(OpusDecoder *)malloc(opus_decoder_get_size(c));
89 if(dec2==NULL)test_failed();
90 memcpy(dec2,dec[t],opus_decoder_get_size(c));
91 memset(dec[t],255,opus_decoder_get_size(c));
92 opus_decoder_destroy(dec[t]);
93 printf("OK.\n");
94 dec[t]=dec2;
95 }
96 }
97
98 decsize=opus_decoder_get_size(1);
99 decbak=(OpusDecoder *)malloc(decsize);
100 if(decbak==NULL)test_failed();
101
102 for(t=0;t<5*2;t++)
103 {
104 int factor=48000/fsv[t>>1];
105 for(fec=0;fec<2;fec++)
106 {
sergeyu@chromium.org6b6bee22013-02-28 21:17:26 +0000107 int dur;
sergeyu@chromium.org885f2ff2012-10-17 22:31:52 +0000108 /*Test PLC on a fresh decoder*/
sergeyu@chromium.org6b6bee22013-02-28 21:17:26 +0000109 out_samples = opus_decode(dec[t], 0, 0, outbuf, 120/factor, fec);
sergeyu@chromium.org885f2ff2012-10-17 22:31:52 +0000110 if(out_samples!=120/factor)test_failed();
sergeyu@chromium.org6b6bee22013-02-28 21:17:26 +0000111 if(opus_decoder_ctl(dec[t], OPUS_GET_LAST_PACKET_DURATION(&dur))!=OPUS_OK)test_failed();
112 if(dur!=120/factor)test_failed();
sergeyu@chromium.org885f2ff2012-10-17 22:31:52 +0000113
tlegrand@chromium.orge3ea0492013-10-23 09:13:50 +0000114 /*Test on a size which isn't a multiple of 2.5ms*/
115 out_samples = opus_decode(dec[t], 0, 0, outbuf, 120/factor+2, fec);
116 if(out_samples!=OPUS_BAD_ARG)test_failed();
117
sergeyu@chromium.org885f2ff2012-10-17 22:31:52 +0000118 /*Test null pointer input*/
sergeyu@chromium.org6b6bee22013-02-28 21:17:26 +0000119 out_samples = opus_decode(dec[t], 0, -1, outbuf, 120/factor, fec);
sergeyu@chromium.org885f2ff2012-10-17 22:31:52 +0000120 if(out_samples!=120/factor)test_failed();
sergeyu@chromium.org6b6bee22013-02-28 21:17:26 +0000121 out_samples = opus_decode(dec[t], 0, 1, outbuf, 120/factor, fec);
sergeyu@chromium.org885f2ff2012-10-17 22:31:52 +0000122 if(out_samples!=120/factor)test_failed();
sergeyu@chromium.org6b6bee22013-02-28 21:17:26 +0000123 out_samples = opus_decode(dec[t], 0, 10, outbuf, 120/factor, fec);
sergeyu@chromium.org885f2ff2012-10-17 22:31:52 +0000124 if(out_samples!=120/factor)test_failed();
sergeyu@chromium.org6b6bee22013-02-28 21:17:26 +0000125 out_samples = opus_decode(dec[t], 0, fast_rand(), outbuf, 120/factor, fec);
sergeyu@chromium.org885f2ff2012-10-17 22:31:52 +0000126 if(out_samples!=120/factor)test_failed();
sergeyu@chromium.org6b6bee22013-02-28 21:17:26 +0000127 if(opus_decoder_ctl(dec[t], OPUS_GET_LAST_PACKET_DURATION(&dur))!=OPUS_OK)test_failed();
128 if(dur!=120/factor)test_failed();
sergeyu@chromium.org885f2ff2012-10-17 22:31:52 +0000129
130 /*Zero lengths*/
sergeyu@chromium.org6b6bee22013-02-28 21:17:26 +0000131 out_samples = opus_decode(dec[t], packet, 0, outbuf, 120/factor, fec);
sergeyu@chromium.org885f2ff2012-10-17 22:31:52 +0000132 if(out_samples!=120/factor)test_failed();
133
134 /*Zero buffer*/
135 outbuf[0]=32749;
136 out_samples = opus_decode(dec[t], packet, 0, outbuf, 0, fec);
137 if(out_samples>0)test_failed();
138 out_samples = opus_decode(dec[t], packet, 0, 0, 0, fec);
139 if(out_samples>0)test_failed();
140 if(outbuf[0]!=32749)test_failed();
141
142 /*Invalid lengths*/
143 out_samples = opus_decode(dec[t], packet, -1, outbuf, MAX_FRAME_SAMP, fec);
144 if(out_samples>=0)test_failed();
145 out_samples = opus_decode(dec[t], packet, INT_MIN, outbuf, MAX_FRAME_SAMP, fec);
146 if(out_samples>=0)test_failed();
147 out_samples = opus_decode(dec[t], packet, -1, outbuf, -1, fec);
148 if(out_samples>=0)test_failed();
149
150 /*Crazy FEC values*/
151 out_samples = opus_decode(dec[t], packet, 1, outbuf, MAX_FRAME_SAMP, fec?-1:2);
152 if(out_samples>=0)test_failed();
153
154 /*Reset the decoder*/
155 if(opus_decoder_ctl(dec[t], OPUS_RESET_STATE)!=OPUS_OK)test_failed();
156 }
157 }
158 fprintf(stdout," dec[all] initial frame PLC OK.\n");
159
160 /*Count code 0 tests*/
161 for(i=0;i<64;i++)
162 {
sergeyu@chromium.org6b6bee22013-02-28 21:17:26 +0000163 int dur;
sergeyu@chromium.org885f2ff2012-10-17 22:31:52 +0000164 int j,expected[5*2];
165 packet[0]=i<<2;
166 packet[1]=255;
167 packet[2]=255;
168 err=opus_packet_get_nb_channels(packet);
169 if(err!=(i&1)+1)test_failed();
170
171 for(t=0;t<5*2;t++){
172 expected[t]=opus_decoder_get_nb_samples(dec[t],packet,1);
173 if(expected[t]>2880)test_failed();
174 }
175
176 for(j=0;j<256;j++)
177 {
178 packet[1]=j;
179 for(t=0;t<5*2;t++)
180 {
181 out_samples = opus_decode(dec[t], packet, 3, outbuf, MAX_FRAME_SAMP, 0);
182 if(out_samples!=expected[t])test_failed();
sergeyu@chromium.org6b6bee22013-02-28 21:17:26 +0000183 if(opus_decoder_ctl(dec[t], OPUS_GET_LAST_PACKET_DURATION(&dur))!=OPUS_OK)test_failed();
184 if(dur!=out_samples)test_failed();
sergeyu@chromium.org885f2ff2012-10-17 22:31:52 +0000185 opus_decoder_ctl(dec[t], OPUS_GET_FINAL_RANGE(&dec_final_range1));
186 if(t==0)dec_final_range2=dec_final_range1;
187 else if(dec_final_range1!=dec_final_range2)test_failed();
188 }
189 }
190
191 for(t=0;t<5*2;t++){
192 int factor=48000/fsv[t>>1];
193 /* The PLC is run for 6 frames in order to get better PLC coverage. */
194 for(j=0;j<6;j++)
195 {
sergeyu@chromium.org6b6bee22013-02-28 21:17:26 +0000196 out_samples = opus_decode(dec[t], 0, 0, outbuf, expected[t], 0);
sergeyu@chromium.org885f2ff2012-10-17 22:31:52 +0000197 if(out_samples!=expected[t])test_failed();
sergeyu@chromium.org6b6bee22013-02-28 21:17:26 +0000198 if(opus_decoder_ctl(dec[t], OPUS_GET_LAST_PACKET_DURATION(&dur))!=OPUS_OK)test_failed();
199 if(dur!=out_samples)test_failed();
sergeyu@chromium.org885f2ff2012-10-17 22:31:52 +0000200 }
201 /* Run the PLC once at 2.5ms, as a simulation of someone trying to
202 do small drift corrections. */
203 if(expected[t]!=120/factor)
204 {
205 out_samples = opus_decode(dec[t], 0, 0, outbuf, 120/factor, 0);
206 if(out_samples!=120/factor)test_failed();
sergeyu@chromium.org6b6bee22013-02-28 21:17:26 +0000207 if(opus_decoder_ctl(dec[t], OPUS_GET_LAST_PACKET_DURATION(&dur))!=OPUS_OK)test_failed();
208 if(dur!=out_samples)test_failed();
sergeyu@chromium.org885f2ff2012-10-17 22:31:52 +0000209 }
210 out_samples = opus_decode(dec[t], packet, 2, outbuf, expected[t]-1, 0);
211 if(out_samples>0)test_failed();
212 }
213 }
214 fprintf(stdout," dec[all] all 2-byte prefix for length 3 and PLC, all modes (64) OK.\n");
215
216 if(no_fuzz)
217 {
218 fprintf(stdout," Skipping many tests which fuzz the decoder as requested.\n");
219 free(decbak);
220 for(t=0;t<5*2;t++)opus_decoder_destroy(dec[t]);
221 printf(" Decoders stopped.\n");
222
223 err=0;
224 for(i=0;i<8*2;i++)err|=outbuf_int[i]!=32749;
225 for(i=MAX_FRAME_SAMP*2;i<(MAX_FRAME_SAMP+8)*2;i++)err|=outbuf[i]!=32749;
226 if(err)test_failed();
227
228 free(outbuf_int);
229 free(packet);
230 return 0;
231 }
232
233 {
234 /*We only test a subset of the modes here simply because the longer
235 durations end up taking a long time.*/
236 static const int cmodes[4]={16,20,24,28};
tlegrand@chromium.orge3ea0492013-10-23 09:13:50 +0000237 static const opus_uint32 cres[4]={116290185,2172123586u,2172123586u,2172123586u};
238 static const opus_uint32 lres[3]={3285687739u,1481572662,694350475};
sergeyu@chromium.org885f2ff2012-10-17 22:31:52 +0000239 static const int lmodes[3]={0,4,8};
240 int mode=fast_rand()%4;
241
242 packet[0]=cmodes[mode]<<3;
243 dec_final_acc=0;
244 t=fast_rand()%10;
245
246 for(i=0;i<65536;i++)
247 {
248 int factor=48000/fsv[t>>1];
249 packet[1]=i>>8;
250 packet[2]=i&255;
251 packet[3]=255;
252 out_samples = opus_decode(dec[t], packet, 4, outbuf, MAX_FRAME_SAMP, 0);
253 if(out_samples!=120/factor)test_failed();
254 opus_decoder_ctl(dec[t], OPUS_GET_FINAL_RANGE(&dec_final_range1));
255 dec_final_acc+=dec_final_range1;
256 }
257 if(dec_final_acc!=cres[mode])test_failed();
258 fprintf(stdout," dec[%3d] all 3-byte prefix for length 4, mode %2d OK.\n",t,cmodes[mode]);
259
260 mode=fast_rand()%3;
261 packet[0]=lmodes[mode]<<3;
262 dec_final_acc=0;
263 t=fast_rand()%10;
264 for(i=0;i<65536;i++)
265 {
266 int factor=48000/fsv[t>>1];
267 packet[1]=i>>8;
268 packet[2]=i&255;
269 packet[3]=255;
270 out_samples = opus_decode(dec[t], packet, 4, outbuf, MAX_FRAME_SAMP, 0);
271 if(out_samples!=480/factor)test_failed();
272 opus_decoder_ctl(dec[t], OPUS_GET_FINAL_RANGE(&dec_final_range1));
273 dec_final_acc+=dec_final_range1;
274 }
275 if(dec_final_acc!=lres[mode])test_failed();
276 fprintf(stdout," dec[%3d] all 3-byte prefix for length 4, mode %2d OK.\n",t,lmodes[mode]);
277 }
278
279 skip=fast_rand()%7;
280 for(i=0;i<64;i++)
281 {
282 int j,expected[5*2];
283 packet[0]=i<<2;
284 for(t=0;t<5*2;t++)expected[t]=opus_decoder_get_nb_samples(dec[t],packet,1);
285 for(j=2+skip;j<1275;j+=4)
286 {
287 int jj;
288 for(jj=0;jj<j;jj++)packet[jj+1]=fast_rand()&255;
289 for(t=0;t<5*2;t++)
290 {
291 out_samples = opus_decode(dec[t], packet, j+1, outbuf, MAX_FRAME_SAMP, 0);
292 if(out_samples!=expected[t])test_failed();
293 opus_decoder_ctl(dec[t], OPUS_GET_FINAL_RANGE(&dec_final_range1));
294 if(t==0)dec_final_range2=dec_final_range1;
295 else if(dec_final_range1!=dec_final_range2)test_failed();
296 }
297 }
298 }
299 fprintf(stdout," dec[all] random packets, all modes (64), every 8th size from from %d bytes to maximum OK.\n",2+skip);
300
301 debruijn2(64,modes);
302 plen=(fast_rand()%18+3)*8+skip+3;
303 for(i=0;i<4096;i++)
304 {
305 int j,expected[5*2];
306 packet[0]=modes[i]<<2;
307 for(t=0;t<5*2;t++)expected[t]=opus_decoder_get_nb_samples(dec[t],packet,plen);
308 for(j=0;j<plen;j++)packet[j+1]=(fast_rand()|fast_rand())&255;
309 memcpy(decbak,dec[0],decsize);
sergeyu@chromium.org6b6bee22013-02-28 21:17:26 +0000310 if(opus_decode(decbak, packet, plen+1, outbuf, expected[0], 1)!=expected[0])test_failed();
sergeyu@chromium.org885f2ff2012-10-17 22:31:52 +0000311 memcpy(decbak,dec[0],decsize);
312 if(opus_decode(decbak, 0, 0, outbuf, MAX_FRAME_SAMP, 1)<20)test_failed();
313 memcpy(decbak,dec[0],decsize);
314 if(opus_decode(decbak, 0, 0, outbuf, MAX_FRAME_SAMP, 0)<20)test_failed();
315 for(t=0;t<5*2;t++)
316 {
sergeyu@chromium.org6b6bee22013-02-28 21:17:26 +0000317 int dur;
sergeyu@chromium.org885f2ff2012-10-17 22:31:52 +0000318 out_samples = opus_decode(dec[t], packet, plen+1, outbuf, MAX_FRAME_SAMP, 0);
319 if(out_samples!=expected[t])test_failed();
320 if(t==0)dec_final_range2=dec_final_range1;
321 else if(dec_final_range1!=dec_final_range2)test_failed();
sergeyu@chromium.org6b6bee22013-02-28 21:17:26 +0000322 if(opus_decoder_ctl(dec[t], OPUS_GET_LAST_PACKET_DURATION(&dur))!=OPUS_OK)test_failed();
323 if(dur!=out_samples)test_failed();
sergeyu@chromium.org885f2ff2012-10-17 22:31:52 +0000324 }
325 }
326 fprintf(stdout," dec[all] random packets, all mode pairs (4096), %d bytes/frame OK.\n",plen+1);
327
328 plen=(fast_rand()%18+3)*8+skip+3;
329 t=rand()&3;
330 for(i=0;i<4096;i++)
331 {
332 int count,j,expected;
333 packet[0]=modes[i]<<2;
334 expected=opus_decoder_get_nb_samples(dec[t],packet,plen);
335 for(count=0;count<10;count++)
336 {
337 for(j=0;j<plen;j++)packet[j+1]=(fast_rand()|fast_rand())&255;
338 out_samples = opus_decode(dec[t], packet, plen+1, outbuf, MAX_FRAME_SAMP, 0);
339 if(out_samples!=expected)test_failed();
340 }
341 }
342 fprintf(stdout," dec[%3d] random packets, all mode pairs (4096)*10, %d bytes/frame OK.\n",t,plen+1);
343
344 {
345 int tmodes[1]={25<<2};
346 opus_uint32 tseeds[1]={140441};
347 int tlen[1]={157};
348 opus_int32 tret[1]={480};
349 t=fast_rand()&1;
350 for(i=0;i<1;i++)
351 {
352 int j;
353 packet[0]=tmodes[i];
354 Rw=Rz=tseeds[i];
355 for(j=1;j<tlen[i];j++)packet[j]=fast_rand()&255;
356 out_samples=opus_decode(dec[t], packet, tlen[i], outbuf, MAX_FRAME_SAMP, 0);
357 if(out_samples!=tret[i])test_failed();
358 }
359 fprintf(stdout," dec[%3d] pre-selected random packets OK.\n",t);
360 }
361
362 free(decbak);
363 for(t=0;t<5*2;t++)opus_decoder_destroy(dec[t]);
364 printf(" Decoders stopped.\n");
365
366 err=0;
367 for(i=0;i<8*2;i++)err|=outbuf_int[i]!=32749;
368 for(i=MAX_FRAME_SAMP*2;i<(MAX_FRAME_SAMP+8)*2;i++)err|=outbuf[i]!=32749;
369 if(err)test_failed();
370
371 free(outbuf_int);
372 free(packet);
373 return 0;
374}
375
tlegrand@google.com3c3902f2013-12-09 08:35:25 +0000376#ifndef DISABLE_FLOAT_API
377void test_soft_clip(void)
378{
379 int i,j;
380 float x[1024];
381 float s[8] = {0, 0, 0, 0, 0, 0, 0, 0};
382 fprintf(stdout," Testing opus_pcm_soft_clip... ");
383 for(i=0;i<1024;i++)
384 {
385 for (j=0;j<1024;j++)
386 {
387 x[j]=(i&255)*(1/32.f)-4.f;
388 }
389 opus_pcm_soft_clip(&x[i],1024-i,1,s);
390 for (j=i;j<1024;j++)
391 {
392 if(x[i]>1.f)test_failed();
393 if(x[i]<-1.f)test_failed();
394 }
395 }
396 for(i=1;i<9;i++)
397 {
398 for (j=0;j<1024;j++)
399 {
400 x[j]=(i&255)*(1/32.f)-4.f;
401 }
402 opus_pcm_soft_clip(x,1024/i,i,s);
403 for (j=0;j<(1024/i)*i;j++)
404 {
405 if(x[i]>1.f)test_failed();
406 if(x[i]<-1.f)test_failed();
407 }
408 }
409 opus_pcm_soft_clip(x,0,1,s);
410 opus_pcm_soft_clip(x,1,0,s);
411 opus_pcm_soft_clip(x,1,1,0);
412 opus_pcm_soft_clip(x,1,-1,s);
413 opus_pcm_soft_clip(x,-1,1,s);
414 opus_pcm_soft_clip(0,1,1,s);
415 printf("OK.\n");
416}
417#endif
418
sergeyu@chromium.org885f2ff2012-10-17 22:31:52 +0000419int main(int _argc, char **_argv)
420{
421 const char * oversion;
422 const char * env_seed;
423 int env_used;
424
425 if(_argc>2)
426 {
427 fprintf(stderr,"Usage: %s [<seed>]\n",_argv[0]);
428 return 1;
429 }
430
431 env_used=0;
432 env_seed=getenv("SEED");
433 if(_argc>1)iseed=atoi(_argv[1]);
434 else if(env_seed)
435 {
436 iseed=atoi(env_seed);
437 env_used=1;
438 }
439 else iseed=(opus_uint32)time(NULL)^((getpid()&65535)<<16);
440 Rw=Rz=iseed;
441
442 oversion=opus_get_version_string();
443 if(!oversion)test_failed();
444 fprintf(stderr,"Testing %s decoder. Random seed: %u (%.4X)\n", oversion, iseed, fast_rand() % 65535);
445 if(env_used)fprintf(stderr," Random seed set from the environment (SEED=%s).\n", env_seed);
446
447 /*Setting TEST_OPUS_NOFUZZ tells the tool not to send garbage data
448 into the decoders. This is helpful because garbage data
449 may cause the decoders to clip, which angers CLANG IOC.*/
450 test_decoder_code0(getenv("TEST_OPUS_NOFUZZ")!=NULL);
tlegrand@google.com3c3902f2013-12-09 08:35:25 +0000451#ifndef DISABLE_FLOAT_API
452 test_soft_clip();
453#endif
sergeyu@chromium.org885f2ff2012-10-17 22:31:52 +0000454
455 return 0;
456}