Chris@69: /* Copyright (c) 2011-2013 Xiph.Org Foundation Chris@69: Written by Gregory Maxwell */ Chris@69: /* Chris@69: Redistribution and use in source and binary forms, with or without Chris@69: modification, are permitted provided that the following conditions Chris@69: are met: Chris@69: Chris@69: - Redistributions of source code must retain the above copyright Chris@69: notice, this list of conditions and the following disclaimer. Chris@69: Chris@69: - Redistributions in binary form must reproduce the above copyright Chris@69: notice, this list of conditions and the following disclaimer in the Chris@69: documentation and/or other materials provided with the distribution. Chris@69: Chris@69: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS Chris@69: ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT Chris@69: LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR Chris@69: A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER Chris@69: OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, Chris@69: EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, Chris@69: PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR Chris@69: PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF Chris@69: LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING Chris@69: NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS Chris@69: SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Chris@69: */ Chris@69: Chris@69: #ifdef HAVE_CONFIG_H Chris@69: #include "config.h" Chris@69: #endif Chris@69: Chris@69: #include Chris@69: #include Chris@69: #include Chris@69: #include Chris@69: #include Chris@69: #include Chris@69: #include Chris@69: #if (!defined WIN32 && !defined _WIN32) || defined(__MINGW32__) Chris@69: #include Chris@69: #else Chris@69: #include Chris@69: #define getpid _getpid Chris@69: #endif Chris@69: #include "opus.h" Chris@69: #include "test_opus_common.h" Chris@69: Chris@69: #define MAX_PACKET (1500) Chris@69: #define MAX_FRAME_SAMP (5760) Chris@69: Chris@69: int test_decoder_code0(int no_fuzz) Chris@69: { Chris@69: static const opus_int32 fsv[5]={48000,24000,16000,12000,8000}; Chris@69: int err,skip,plen; Chris@69: int out_samples,fec; Chris@69: int t; Chris@69: opus_int32 i; Chris@69: OpusDecoder *dec[5*2]; Chris@69: opus_int32 decsize; Chris@69: OpusDecoder *decbak; Chris@69: opus_uint32 dec_final_range1,dec_final_range2,dec_final_acc; Chris@69: unsigned char *packet; Chris@69: unsigned char modes[4096]; Chris@69: short *outbuf_int; Chris@69: short *outbuf; Chris@69: Chris@69: dec_final_range1=dec_final_range2=2; Chris@69: Chris@69: packet=malloc(sizeof(unsigned char)*MAX_PACKET); Chris@69: if(packet==NULL)test_failed(); Chris@69: Chris@69: outbuf_int=malloc(sizeof(short)*(MAX_FRAME_SAMP+16)*2); Chris@69: for(i=0;i<(MAX_FRAME_SAMP+16)*2;i++)outbuf_int[i]=32749; Chris@69: outbuf=&outbuf_int[8*2]; Chris@69: Chris@69: fprintf(stdout," Starting %d decoders...\n",5*2); Chris@69: for(t=0;t<5*2;t++) Chris@69: { Chris@69: int fs=fsv[t>>1]; Chris@69: int c=(t&1)+1; Chris@69: err=OPUS_INTERNAL_ERROR; Chris@69: dec[t] = opus_decoder_create(fs, c, &err); Chris@69: if(err!=OPUS_OK || dec[t]==NULL)test_failed(); Chris@69: fprintf(stdout," opus_decoder_create(%5d,%d) OK. Copy ",fs,c); Chris@69: { Chris@69: OpusDecoder *dec2; Chris@69: /*The opus state structures contain no pointers and can be freely copied*/ Chris@69: dec2=(OpusDecoder *)malloc(opus_decoder_get_size(c)); Chris@69: if(dec2==NULL)test_failed(); Chris@69: memcpy(dec2,dec[t],opus_decoder_get_size(c)); Chris@69: memset(dec[t],255,opus_decoder_get_size(c)); Chris@69: opus_decoder_destroy(dec[t]); Chris@69: printf("OK.\n"); Chris@69: dec[t]=dec2; Chris@69: } Chris@69: } Chris@69: Chris@69: decsize=opus_decoder_get_size(1); Chris@69: decbak=(OpusDecoder *)malloc(decsize); Chris@69: if(decbak==NULL)test_failed(); Chris@69: Chris@69: for(t=0;t<5*2;t++) Chris@69: { Chris@69: int factor=48000/fsv[t>>1]; Chris@69: for(fec=0;fec<2;fec++) Chris@69: { Chris@69: opus_int32 dur; Chris@69: /*Test PLC on a fresh decoder*/ Chris@69: out_samples = opus_decode(dec[t], 0, 0, outbuf, 120/factor, fec); Chris@69: if(out_samples!=120/factor)test_failed(); Chris@69: if(opus_decoder_ctl(dec[t], OPUS_GET_LAST_PACKET_DURATION(&dur))!=OPUS_OK)test_failed(); Chris@69: if(dur!=120/factor)test_failed(); Chris@69: Chris@69: /*Test on a size which isn't a multiple of 2.5ms*/ Chris@69: out_samples = opus_decode(dec[t], 0, 0, outbuf, 120/factor+2, fec); Chris@69: if(out_samples!=OPUS_BAD_ARG)test_failed(); Chris@69: Chris@69: /*Test null pointer input*/ Chris@69: out_samples = opus_decode(dec[t], 0, -1, outbuf, 120/factor, fec); Chris@69: if(out_samples!=120/factor)test_failed(); Chris@69: out_samples = opus_decode(dec[t], 0, 1, outbuf, 120/factor, fec); Chris@69: if(out_samples!=120/factor)test_failed(); Chris@69: out_samples = opus_decode(dec[t], 0, 10, outbuf, 120/factor, fec); Chris@69: if(out_samples!=120/factor)test_failed(); Chris@69: out_samples = opus_decode(dec[t], 0, fast_rand(), outbuf, 120/factor, fec); Chris@69: if(out_samples!=120/factor)test_failed(); Chris@69: if(opus_decoder_ctl(dec[t], OPUS_GET_LAST_PACKET_DURATION(&dur))!=OPUS_OK)test_failed(); Chris@69: if(dur!=120/factor)test_failed(); Chris@69: Chris@69: /*Zero lengths*/ Chris@69: out_samples = opus_decode(dec[t], packet, 0, outbuf, 120/factor, fec); Chris@69: if(out_samples!=120/factor)test_failed(); Chris@69: Chris@69: /*Zero buffer*/ Chris@69: outbuf[0]=32749; Chris@69: out_samples = opus_decode(dec[t], packet, 0, outbuf, 0, fec); Chris@69: if(out_samples>0)test_failed(); Chris@69: #if !defined(OPUS_BUILD) && (OPUS_GNUC_PREREQ(4, 6) || (defined(__clang_major__) && __clang_major__ >= 3)) Chris@69: #pragma GCC diagnostic push Chris@69: #pragma GCC diagnostic ignored "-Wnonnull" Chris@69: #endif Chris@69: out_samples = opus_decode(dec[t], packet, 0, 0, 0, fec); Chris@69: #if !defined(OPUS_BUILD) && (OPUS_GNUC_PREREQ(4, 6) || (defined(__clang_major__) && __clang_major__ >= 3)) Chris@69: #pragma GCC diagnostic pop Chris@69: #endif Chris@69: if(out_samples>0)test_failed(); Chris@69: if(outbuf[0]!=32749)test_failed(); Chris@69: Chris@69: /*Invalid lengths*/ Chris@69: out_samples = opus_decode(dec[t], packet, -1, outbuf, MAX_FRAME_SAMP, fec); Chris@69: if(out_samples>=0)test_failed(); Chris@69: out_samples = opus_decode(dec[t], packet, INT_MIN, outbuf, MAX_FRAME_SAMP, fec); Chris@69: if(out_samples>=0)test_failed(); Chris@69: out_samples = opus_decode(dec[t], packet, -1, outbuf, -1, fec); Chris@69: if(out_samples>=0)test_failed(); Chris@69: Chris@69: /*Crazy FEC values*/ Chris@69: out_samples = opus_decode(dec[t], packet, 1, outbuf, MAX_FRAME_SAMP, fec?-1:2); Chris@69: if(out_samples>=0)test_failed(); Chris@69: Chris@69: /*Reset the decoder*/ Chris@69: if(opus_decoder_ctl(dec[t], OPUS_RESET_STATE)!=OPUS_OK)test_failed(); Chris@69: } Chris@69: } Chris@69: fprintf(stdout," dec[all] initial frame PLC OK.\n"); Chris@69: Chris@69: /*Count code 0 tests*/ Chris@69: for(i=0;i<64;i++) Chris@69: { Chris@69: opus_int32 dur; Chris@69: int j,expected[5*2]; Chris@69: packet[0]=i<<2; Chris@69: packet[1]=255; Chris@69: packet[2]=255; Chris@69: err=opus_packet_get_nb_channels(packet); Chris@69: if(err!=(i&1)+1)test_failed(); Chris@69: Chris@69: for(t=0;t<5*2;t++){ Chris@69: expected[t]=opus_decoder_get_nb_samples(dec[t],packet,1); Chris@69: if(expected[t]>2880)test_failed(); Chris@69: } Chris@69: Chris@69: for(j=0;j<256;j++) Chris@69: { Chris@69: packet[1]=j; Chris@69: for(t=0;t<5*2;t++) Chris@69: { Chris@69: out_samples = opus_decode(dec[t], packet, 3, outbuf, MAX_FRAME_SAMP, 0); Chris@69: if(out_samples!=expected[t])test_failed(); Chris@69: if(opus_decoder_ctl(dec[t], OPUS_GET_LAST_PACKET_DURATION(&dur))!=OPUS_OK)test_failed(); Chris@69: if(dur!=out_samples)test_failed(); Chris@69: opus_decoder_ctl(dec[t], OPUS_GET_FINAL_RANGE(&dec_final_range1)); Chris@69: if(t==0)dec_final_range2=dec_final_range1; Chris@69: else if(dec_final_range1!=dec_final_range2)test_failed(); Chris@69: } Chris@69: } Chris@69: Chris@69: for(t=0;t<5*2;t++){ Chris@69: int factor=48000/fsv[t>>1]; Chris@69: /* The PLC is run for 6 frames in order to get better PLC coverage. */ Chris@69: for(j=0;j<6;j++) Chris@69: { Chris@69: out_samples = opus_decode(dec[t], 0, 0, outbuf, expected[t], 0); Chris@69: if(out_samples!=expected[t])test_failed(); Chris@69: if(opus_decoder_ctl(dec[t], OPUS_GET_LAST_PACKET_DURATION(&dur))!=OPUS_OK)test_failed(); Chris@69: if(dur!=out_samples)test_failed(); Chris@69: } Chris@69: /* Run the PLC once at 2.5ms, as a simulation of someone trying to Chris@69: do small drift corrections. */ Chris@69: if(expected[t]!=120/factor) Chris@69: { Chris@69: out_samples = opus_decode(dec[t], 0, 0, outbuf, 120/factor, 0); Chris@69: if(out_samples!=120/factor)test_failed(); Chris@69: if(opus_decoder_ctl(dec[t], OPUS_GET_LAST_PACKET_DURATION(&dur))!=OPUS_OK)test_failed(); Chris@69: if(dur!=out_samples)test_failed(); Chris@69: } Chris@69: out_samples = opus_decode(dec[t], packet, 2, outbuf, expected[t]-1, 0); Chris@69: if(out_samples>0)test_failed(); Chris@69: } Chris@69: } Chris@69: fprintf(stdout," dec[all] all 2-byte prefix for length 3 and PLC, all modes (64) OK.\n"); Chris@69: Chris@69: if(no_fuzz) Chris@69: { Chris@69: fprintf(stdout," Skipping many tests which fuzz the decoder as requested.\n"); Chris@69: free(decbak); Chris@69: for(t=0;t<5*2;t++)opus_decoder_destroy(dec[t]); Chris@69: printf(" Decoders stopped.\n"); Chris@69: Chris@69: err=0; Chris@69: for(i=0;i<8*2;i++)err|=outbuf_int[i]!=32749; Chris@69: for(i=MAX_FRAME_SAMP*2;i<(MAX_FRAME_SAMP+8)*2;i++)err|=outbuf[i]!=32749; Chris@69: if(err)test_failed(); Chris@69: Chris@69: free(outbuf_int); Chris@69: free(packet); Chris@69: return 0; Chris@69: } Chris@69: Chris@69: { Chris@69: /*We only test a subset of the modes here simply because the longer Chris@69: durations end up taking a long time.*/ Chris@69: static const int cmodes[4]={16,20,24,28}; Chris@69: static const opus_uint32 cres[4]={116290185,2172123586u,2172123586u,2172123586u}; Chris@69: static const opus_uint32 lres[3]={3285687739u,1481572662,694350475}; Chris@69: static const int lmodes[3]={0,4,8}; Chris@69: int mode=fast_rand()%4; Chris@69: Chris@69: packet[0]=cmodes[mode]<<3; Chris@69: dec_final_acc=0; Chris@69: t=fast_rand()%10; Chris@69: Chris@69: for(i=0;i<65536;i++) Chris@69: { Chris@69: int factor=48000/fsv[t>>1]; Chris@69: packet[1]=i>>8; Chris@69: packet[2]=i&255; Chris@69: packet[3]=255; Chris@69: out_samples = opus_decode(dec[t], packet, 4, outbuf, MAX_FRAME_SAMP, 0); Chris@69: if(out_samples!=120/factor)test_failed(); Chris@69: opus_decoder_ctl(dec[t], OPUS_GET_FINAL_RANGE(&dec_final_range1)); Chris@69: dec_final_acc+=dec_final_range1; Chris@69: } Chris@69: if(dec_final_acc!=cres[mode])test_failed(); Chris@69: fprintf(stdout," dec[%3d] all 3-byte prefix for length 4, mode %2d OK.\n",t,cmodes[mode]); Chris@69: Chris@69: mode=fast_rand()%3; Chris@69: packet[0]=lmodes[mode]<<3; Chris@69: dec_final_acc=0; Chris@69: t=fast_rand()%10; Chris@69: for(i=0;i<65536;i++) Chris@69: { Chris@69: int factor=48000/fsv[t>>1]; Chris@69: packet[1]=i>>8; Chris@69: packet[2]=i&255; Chris@69: packet[3]=255; Chris@69: out_samples = opus_decode(dec[t], packet, 4, outbuf, MAX_FRAME_SAMP, 0); Chris@69: if(out_samples!=480/factor)test_failed(); Chris@69: opus_decoder_ctl(dec[t], OPUS_GET_FINAL_RANGE(&dec_final_range1)); Chris@69: dec_final_acc+=dec_final_range1; Chris@69: } Chris@69: if(dec_final_acc!=lres[mode])test_failed(); Chris@69: fprintf(stdout," dec[%3d] all 3-byte prefix for length 4, mode %2d OK.\n",t,lmodes[mode]); Chris@69: } Chris@69: Chris@69: skip=fast_rand()%7; Chris@69: for(i=0;i<64;i++) Chris@69: { Chris@69: int j,expected[5*2]; Chris@69: packet[0]=i<<2; Chris@69: for(t=0;t<5*2;t++)expected[t]=opus_decoder_get_nb_samples(dec[t],packet,1); Chris@69: for(j=2+skip;j<1275;j+=4) Chris@69: { Chris@69: int jj; Chris@69: for(jj=0;jj1.f)test_failed(); Chris@69: if(x[j]<-1.f)test_failed(); Chris@69: } Chris@69: } Chris@69: for(i=1;i<9;i++) Chris@69: { Chris@69: for (j=0;j<1024;j++) Chris@69: { Chris@69: x[j]=(j&255)*(1/32.f)-4.f; Chris@69: } Chris@69: opus_pcm_soft_clip(x,1024/i,i,s); Chris@69: for (j=0;j<(1024/i)*i;j++) Chris@69: { Chris@69: if(x[j]>1.f)test_failed(); Chris@69: if(x[j]<-1.f)test_failed(); Chris@69: } Chris@69: } Chris@69: opus_pcm_soft_clip(x,0,1,s); Chris@69: opus_pcm_soft_clip(x,1,0,s); Chris@69: opus_pcm_soft_clip(x,1,1,0); Chris@69: opus_pcm_soft_clip(x,1,-1,s); Chris@69: opus_pcm_soft_clip(x,-1,1,s); Chris@69: opus_pcm_soft_clip(0,1,1,s); Chris@69: printf("OK.\n"); Chris@69: } Chris@69: #endif Chris@69: Chris@69: int main(int _argc, char **_argv) Chris@69: { Chris@69: const char * oversion; Chris@69: const char * env_seed; Chris@69: int env_used; Chris@69: Chris@69: if(_argc>2) Chris@69: { Chris@69: fprintf(stderr,"Usage: %s []\n",_argv[0]); Chris@69: return 1; Chris@69: } Chris@69: Chris@69: env_used=0; Chris@69: env_seed=getenv("SEED"); Chris@69: if(_argc>1)iseed=atoi(_argv[1]); Chris@69: else if(env_seed) Chris@69: { Chris@69: iseed=atoi(env_seed); Chris@69: env_used=1; Chris@69: } Chris@69: else iseed=(opus_uint32)time(NULL)^(((opus_uint32)getpid()&65535)<<16); Chris@69: Rw=Rz=iseed; Chris@69: Chris@69: oversion=opus_get_version_string(); Chris@69: if(!oversion)test_failed(); Chris@69: fprintf(stderr,"Testing %s decoder. Random seed: %u (%.4X)\n", oversion, iseed, fast_rand() % 65535); Chris@69: if(env_used)fprintf(stderr," Random seed set from the environment (SEED=%s).\n", env_seed); Chris@69: Chris@69: /*Setting TEST_OPUS_NOFUZZ tells the tool not to send garbage data Chris@69: into the decoders. This is helpful because garbage data Chris@69: may cause the decoders to clip, which angers CLANG IOC.*/ Chris@69: test_decoder_code0(getenv("TEST_OPUS_NOFUZZ")!=NULL); Chris@69: #ifndef DISABLE_FLOAT_API Chris@69: test_soft_clip(); Chris@69: #endif Chris@69: Chris@69: return 0; Chris@69: }