static int opus_decode_frame(OpusDecoder *st, const unsigned char *data, opus_int32 len, opus_val16 *pcm, int frame_size, int decode_fec) { void *silk_dec; CELTDecoder *celt_dec; int i, silk_ret=0, celt_ret=0; ec_dec dec; opus_int32 silk_frame_size; int pcm_silk_size; VARDECL(opus_int16, pcm_silk); int pcm_transition_silk_size; VARDECL(opus_val16, pcm_transition_silk); int pcm_transition_celt_size; VARDECL(opus_val16, pcm_transition_celt); opus_val16 *pcm_transition=NULL; int redundant_audio_size; VARDECL(opus_val16, redundant_audio); int audiosize; int mode; int transition=0; int start_band; int redundancy=0; int redundancy_bytes = 0; int celt_to_silk=0; int c; int F2_5, F5, F10, F20; const opus_val16 *window; opus_uint32 redundant_rng = 0; int celt_accum; ALLOC_STACK; silk_dec = (char*)st+st->silk_dec_offset; celt_dec = (CELTDecoder*)((char*)st+st->celt_dec_offset); F20 = st->Fs/50; F10 = F20>>1; F5 = F10>>1; F2_5 = F5>>1; if (frame_size < F2_5) { RESTORE_STACK; return OPUS_BUFFER_TOO_SMALL; } /* Limit frame_size to avoid excessive stack allocations. */ frame_size = IMIN(frame_size, st->Fs/25*3); /* Payloads of 1 (2 including ToC) or 0 trigger the PLC/DTX */ if (len<=1) { data = NULL; /* In that case, don't conceal more than what the ToC says */ frame_size = IMIN(frame_size, st->frame_size); } if (data != NULL) { audiosize = st->frame_size; mode = st->mode; ec_dec_init(&dec,(unsigned char*)data,len); } else { audiosize = frame_size; mode = st->prev_mode; if (mode == 0) { /* If we haven't got any packet yet, all we can do is return zeros */ for (i=0; i<audiosize*st->channels; i++) pcm[i] = 0; RESTORE_STACK; return audiosize; } /* Avoids trying to run the PLC on sizes other than 2.5 (CELT), 5 (CELT), 10, or 20 (e.g. 12.5 or 30 ms). */ if (audiosize > F20) { do { int ret = opus_decode_frame(st, NULL, 0, pcm, IMIN(audiosize, F20), 0); if (ret<0) { RESTORE_STACK; return ret; } pcm += ret*st->channels; audiosize -= ret; } while (audiosize > 0); RESTORE_STACK; return frame_size; } else if (audiosize < F20) { if (audiosize > F10) audiosize = F10; else if (mode != MODE_SILK_ONLY && audiosize > F5 && audiosize < F10) audiosize = F5; } } /* In fixed-point, we can tell CELT to do the accumulation on top of the SILK PCM buffer. This saves some stack space. */ #ifdef FIXED_POINT celt_accum = (mode != MODE_CELT_ONLY) && (frame_size >= F10); #else celt_accum = 0; #endif pcm_transition_silk_size = ALLOC_NONE; pcm_transition_celt_size = ALLOC_NONE; if (data!=NULL && st->prev_mode > 0 && ( (mode == MODE_CELT_ONLY && st->prev_mode != MODE_CELT_ONLY && !st->prev_redundancy) || (mode != MODE_CELT_ONLY && st->prev_mode == MODE_CELT_ONLY) ) ) { transition = 1; /* Decide where to allocate the stack memory for pcm_transition */ if (mode == MODE_CELT_ONLY) pcm_transition_celt_size = F5*st->channels; else pcm_transition_silk_size = F5*st->channels; } ALLOC(pcm_transition_celt, pcm_transition_celt_size, opus_val16); if (transition && mode == MODE_CELT_ONLY) { pcm_transition = pcm_transition_celt; opus_decode_frame(st, NULL, 0, pcm_transition, IMIN(F5, audiosize), 0); } if (audiosize > frame_size) { /*fprintf(stderr, "PCM buffer too small: %d vs %d (mode = %d)\n", audiosize, frame_size, mode);*/ RESTORE_STACK; return OPUS_BAD_ARG; } else { frame_size = audiosize; } /* Don't allocate any memory when in CELT-only mode */ pcm_silk_size = (mode != MODE_CELT_ONLY && !celt_accum) ? IMAX(F10, frame_size)*st->channels : ALLOC_NONE; ALLOC(pcm_silk, pcm_silk_size, opus_int16); /* SILK processing */ if (mode != MODE_CELT_ONLY) { int lost_flag, decoded_samples; opus_int16 *pcm_ptr; #ifdef FIXED_POINT if (celt_accum) pcm_ptr = pcm; else #endif pcm_ptr = pcm_silk; if (st->prev_mode==MODE_CELT_ONLY) silk_InitDecoder( silk_dec ); /* The SILK PLC cannot produce frames of less than 10 ms */ st->DecControl.payloadSize_ms = IMAX(10, 1000 * audiosize / st->Fs); if (data != NULL) { st->DecControl.nChannelsInternal = st->stream_channels; if( mode == MODE_SILK_ONLY ) { if( st->bandwidth == OPUS_BANDWIDTH_NARROWBAND ) { st->DecControl.internalSampleRate = 8000; } else if( st->bandwidth == OPUS_BANDWIDTH_MEDIUMBAND ) { st->DecControl.internalSampleRate = 12000; } else if( st->bandwidth == OPUS_BANDWIDTH_WIDEBAND ) { st->DecControl.internalSampleRate = 16000; } else { st->DecControl.internalSampleRate = 16000; silk_assert( 0 ); } } else { /* Hybrid mode */ st->DecControl.internalSampleRate = 16000; } } lost_flag = data == NULL ? 1 : 2 * decode_fec; decoded_samples = 0; do { /* Call SILK decoder */ int first_frame = decoded_samples == 0; silk_ret = silk_Decode( silk_dec, &st->DecControl, lost_flag, first_frame, &dec, pcm_ptr, &silk_frame_size ); if( silk_ret ) { if (lost_flag) { /* PLC failure should not be fatal */ silk_frame_size = frame_size; for (i=0; i<frame_size*st->channels; i++) pcm_ptr[i] = 0; } else { RESTORE_STACK; return OPUS_INTERNAL_ERROR; } } pcm_ptr += silk_frame_size * st->channels; decoded_samples += silk_frame_size; } while( decoded_samples < frame_size ); } start_band = 0; if (!decode_fec && mode != MODE_CELT_ONLY && data != NULL && ec_tell(&dec)+17+20*(st->mode == MODE_HYBRID) <= 8*len) { /* Check if we have a redundant 0-8 kHz band */ if (mode == MODE_HYBRID) redundancy = ec_dec_bit_logp(&dec, 12); else redundancy = 1; if (redundancy) { celt_to_silk = ec_dec_bit_logp(&dec, 1); /* redundancy_bytes will be at least two, in the non-hybrid case due to the ec_tell() check above */ redundancy_bytes = mode==MODE_HYBRID ? (opus_int32)ec_dec_uint(&dec, 256)+2 : len-((ec_tell(&dec)+7)>>3); len -= redundancy_bytes; /* This is a sanity check. It should never happen for a valid packet, so the exact behaviour is not normative. */ if (len*8 < ec_tell(&dec)) { len = 0; redundancy_bytes = 0; redundancy = 0; } /* Shrink decoder because of raw bits */ dec.storage -= redundancy_bytes; } } if (mode != MODE_CELT_ONLY) start_band = 17; { int endband=21; switch(st->bandwidth) { case OPUS_BANDWIDTH_NARROWBAND: endband = 13; break; case OPUS_BANDWIDTH_MEDIUMBAND: case OPUS_BANDWIDTH_WIDEBAND: endband = 17; break; case OPUS_BANDWIDTH_SUPERWIDEBAND: endband = 19; break; case OPUS_BANDWIDTH_FULLBAND: endband = 21; break; } celt_decoder_ctl(celt_dec, CELT_SET_END_BAND(endband)); celt_decoder_ctl(celt_dec, CELT_SET_CHANNELS(st->stream_channels)); } if (redundancy) { transition = 0; pcm_transition_silk_size=ALLOC_NONE; } ALLOC(pcm_transition_silk, pcm_transition_silk_size, opus_val16); if (transition && mode != MODE_CELT_ONLY) { pcm_transition = pcm_transition_silk; opus_decode_frame(st, NULL, 0, pcm_transition, IMIN(F5, audiosize), 0); } /* Only allocation memory for redundancy if/when needed */ redundant_audio_size = redundancy ? F5*st->channels : ALLOC_NONE; ALLOC(redundant_audio, redundant_audio_size, opus_val16); /* 5 ms redundant frame for CELT->SILK*/ if (redundancy && celt_to_silk) { celt_decoder_ctl(celt_dec, CELT_SET_START_BAND(0)); celt_decode_with_ec(celt_dec, data+len, redundancy_bytes, redundant_audio, F5, NULL, 0); celt_decoder_ctl(celt_dec, OPUS_GET_FINAL_RANGE(&redundant_rng)); } /* MUST be after PLC */ celt_decoder_ctl(celt_dec, CELT_SET_START_BAND(start_band)); if (mode != MODE_SILK_ONLY) { int celt_frame_size = IMIN(F20, frame_size); /* Make sure to discard any previous CELT state */ if (mode != st->prev_mode && st->prev_mode > 0 && !st->prev_redundancy) celt_decoder_ctl(celt_dec, OPUS_RESET_STATE); /* Decode CELT */ celt_ret = celt_decode_with_ec(celt_dec, decode_fec ? NULL : data, len, pcm, celt_frame_size, &dec, celt_accum); } else { unsigned char silence[2] = {0xFF, 0xFF}; if (!celt_accum) { for (i=0; i<frame_size*st->channels; i++) pcm[i] = 0; } /* For hybrid -> SILK transitions, we let the CELT MDCT do a fade-out by decoding a silence frame */ if (st->prev_mode == MODE_HYBRID && !(redundancy && celt_to_silk && st->prev_redundancy) ) { celt_decoder_ctl(celt_dec, CELT_SET_START_BAND(0)); celt_decode_with_ec(celt_dec, silence, 2, pcm, F2_5, NULL, celt_accum); } } if (mode != MODE_CELT_ONLY && !celt_accum) { #ifdef FIXED_POINT for (i=0; i<frame_size*st->channels; i++) pcm[i] = SAT16(ADD32(pcm[i], pcm_silk[i])); #else for (i=0; i<frame_size*st->channels; i++) pcm[i] = pcm[i] + (opus_val16)((1.f/32768.f)*pcm_silk[i]); #endif } { const CELTMode *celt_mode; celt_decoder_ctl(celt_dec, CELT_GET_MODE(&celt_mode)); window = celt_mode->window; } /* 5 ms redundant frame for SILK->CELT */ if (redundancy && !celt_to_silk) { celt_decoder_ctl(celt_dec, OPUS_RESET_STATE); celt_decoder_ctl(celt_dec, CELT_SET_START_BAND(0)); celt_decode_with_ec(celt_dec, data+len, redundancy_bytes, redundant_audio, F5, NULL, 0); celt_decoder_ctl(celt_dec, OPUS_GET_FINAL_RANGE(&redundant_rng)); smooth_fade(pcm+st->channels*(frame_size-F2_5), redundant_audio+st->channels*F2_5, pcm+st->channels*(frame_size-F2_5), F2_5, st->channels, window, st->Fs); } if (redundancy && celt_to_silk) { for (c=0; c<st->channels; c++) { for (i=0; i<F2_5; i++) pcm[st->channels*i+c] = redundant_audio[st->channels*i+c]; } smooth_fade(redundant_audio+st->channels*F2_5, pcm+st->channels*F2_5, pcm+st->channels*F2_5, F2_5, st->channels, window, st->Fs); } if (transition) { if (audiosize >= F5) { for (i=0; i<st->channels*F2_5; i++) pcm[i] = pcm_transition[i]; smooth_fade(pcm_transition+st->channels*F2_5, pcm+st->channels*F2_5, pcm+st->channels*F2_5, F2_5, st->channels, window, st->Fs); } else { /* Not enough time to do a clean transition, but we do it anyway This will not preserve amplitude perfectly and may introduce a bit of temporal aliasing, but it shouldn't be too bad and that's pretty much the best we can do. In any case, generating this transition it pretty silly in the first place */ smooth_fade(pcm_transition, pcm, pcm, F2_5, st->channels, window, st->Fs); } } if(st->decode_gain) { opus_val32 gain; gain = celt_exp2(MULT16_16_P15(QCONST16(6.48814081e-4f, 25), st->decode_gain)); for (i=0; i<frame_size*st->channels; i++) { opus_val32 x; x = MULT16_32_P16(pcm[i],gain); pcm[i] = SATURATE(x, 32767); } } if (len <= 1) st->rangeFinal = 0; else st->rangeFinal = dec.rng ^ redundant_rng; st->prev_mode = mode; st->prev_redundancy = redundancy && !celt_to_silk; if (celt_ret>=0) { if (OPUS_CHECK_ARRAY(pcm, audiosize*st->channels)) OPUS_PRINT_INT(audiosize); } RESTORE_STACK; return celt_ret < 0 ? celt_ret : audiosize; }
int main(int _argc,char **_argv){ ec_enc enc; ec_dec dec; long nbits; long nbits2; double entropy; int ft; int ftb; int sz; int i; int ret; unsigned int sym; unsigned int seed; unsigned char *ptr; const char *env_seed; ret=0; entropy=0; if (_argc > 2) { fprintf(stderr, "Usage: %s [<seed>]\n", _argv[0]); return 1; } env_seed = getenv("SEED"); if (_argc > 1) seed = atoi(_argv[1]); else if (env_seed) seed = atoi(env_seed); else seed = time(NULL); /*Testing encoding of raw bit values.*/ ptr = (unsigned char *)malloc(DATA_SIZE); ec_enc_init(&enc,ptr, DATA_SIZE); for(ft=2;ft<1024;ft++){ for(i=0;i<ft;i++){ entropy+=log(ft)*M_LOG2E; ec_enc_uint(&enc,i,ft); } } /*Testing encoding of raw bit values.*/ for(ftb=1;ftb<16;ftb++){ for(i=0;i<(1<<ftb);i++){ entropy+=ftb; nbits=ec_tell(&enc); ec_enc_bits(&enc,i,ftb); nbits2=ec_tell(&enc); if(nbits2-nbits!=ftb){ fprintf(stderr,"Used %li bits to encode %i bits directly.\n", nbits2-nbits,ftb); ret=-1; } } } nbits=ec_tell_frac(&enc); ec_enc_done(&enc); fprintf(stderr, "Encoded %0.2lf bits of entropy to %0.2lf bits (%0.3lf%% wasted).\n", entropy,ldexp(nbits,-3),100*(nbits-ldexp(entropy,3))/nbits); fprintf(stderr,"Packed to %li bytes.\n",(long)ec_range_bytes(&enc)); ec_dec_init(&dec,ptr,DATA_SIZE); for(ft=2;ft<1024;ft++){ for(i=0;i<ft;i++){ sym=ec_dec_uint(&dec,ft); if(sym!=(unsigned)i){ fprintf(stderr,"Decoded %i instead of %i with ft of %i.\n",sym,i,ft); ret=-1; } } } for(ftb=1;ftb<16;ftb++){ for(i=0;i<(1<<ftb);i++){ sym=ec_dec_bits(&dec,ftb); if(sym!=(unsigned)i){ fprintf(stderr,"Decoded %i instead of %i with ftb of %i.\n",sym,i,ftb); ret=-1; } } } nbits2=ec_tell_frac(&dec); if(nbits!=nbits2){ fprintf(stderr, "Reported number of bits used was %0.2lf, should be %0.2lf.\n", ldexp(nbits2,-3),ldexp(nbits,-3)); ret=-1; } /*Testing an encoder bust prefers range coder data over raw bits. This isn't a general guarantee, will only work for data that is buffered in the encoder state and not yet stored in the user buffer, and should never get used in practice. It's mostly here for code coverage completeness.*/ /*Start with a 16-bit buffer.*/ ec_enc_init(&enc,ptr,2); /*Write 7 raw bits.*/ ec_enc_bits(&enc,0x55,7); /*Write 12.3 bits of range coder data.*/ ec_enc_uint(&enc,1,2); ec_enc_uint(&enc,1,3); ec_enc_uint(&enc,1,4); ec_enc_uint(&enc,1,5); ec_enc_uint(&enc,2,6); ec_enc_uint(&enc,6,7); ec_enc_done(&enc); ec_dec_init(&dec,ptr,2); if(!enc.error /*The raw bits should have been overwritten by the range coder data.*/ ||ec_dec_bits(&dec,7)!=0x05 /*And all the range coder data should have been encoded correctly.*/ ||ec_dec_uint(&dec,2)!=1 ||ec_dec_uint(&dec,3)!=1 ||ec_dec_uint(&dec,4)!=1 ||ec_dec_uint(&dec,5)!=1 ||ec_dec_uint(&dec,6)!=2 ||ec_dec_uint(&dec,7)!=6){ fprintf(stderr,"Encoder bust overwrote range coder data with raw bits.\n"); ret=-1; } srand(seed); fprintf(stderr,"Testing random streams... Random seed: %u (%.4X)\n", seed, rand() % 65536); for(i=0;i<409600;i++){ unsigned *data; unsigned *tell; unsigned tell_bits; int j; int zeros; ft=rand()/((RAND_MAX>>(rand()%11U))+1U)+10; sz=rand()/((RAND_MAX>>(rand()%9U))+1U); data=(unsigned *)malloc(sz*sizeof(*data)); tell=(unsigned *)malloc((sz+1)*sizeof(*tell)); ec_enc_init(&enc,ptr,DATA_SIZE2); zeros = rand()%13==0; tell[0]=ec_tell_frac(&enc); for(j=0;j<sz;j++){ if (zeros) data[j]=0; else data[j]=rand()%ft; ec_enc_uint(&enc,data[j],ft); tell[j+1]=ec_tell_frac(&enc); } if (rand()%2==0) while(ec_tell(&enc)%8 != 0) ec_enc_uint(&enc, rand()%2, 2); tell_bits = ec_tell(&enc); ec_enc_done(&enc); if(tell_bits!=(unsigned)ec_tell(&enc)){ fprintf(stderr,"ec_tell() changed after ec_enc_done(): %i instead of %i (Random seed: %u)\n", ec_tell(&enc),tell_bits,seed); ret=-1; } if ((tell_bits+7)/8 < ec_range_bytes(&enc)) { fprintf (stderr, "ec_tell() lied, there's %i bytes instead of %d (Random seed: %u)\n", ec_range_bytes(&enc), (tell_bits+7)/8,seed); ret=-1; } ec_dec_init(&dec,ptr,DATA_SIZE2); if(ec_tell_frac(&dec)!=tell[0]){ fprintf(stderr, "Tell mismatch between encoder and decoder at symbol %i: %i instead of %i (Random seed: %u).\n", 0,ec_tell_frac(&dec),tell[0],seed); } for(j=0;j<sz;j++){ sym=ec_dec_uint(&dec,ft); if(sym!=data[j]){ fprintf(stderr, "Decoded %i instead of %i with ft of %i at position %i of %i (Random seed: %u).\n", sym,data[j],ft,j,sz,seed); ret=-1; } if(ec_tell_frac(&dec)!=tell[j+1]){ fprintf(stderr, "Tell mismatch between encoder and decoder at symbol %i: %i instead of %i (Random seed: %u).\n", j+1,ec_tell_frac(&dec),tell[j+1],seed); } } free(tell); free(data); } /*Test compatibility between multiple different encode/decode routines.*/ for(i=0;i<409600;i++){ unsigned *logp1; unsigned *data; unsigned *tell; unsigned *enc_method; int j; sz=rand()/((RAND_MAX>>(rand()%9U))+1U); logp1=(unsigned *)malloc(sz*sizeof(*logp1)); data=(unsigned *)malloc(sz*sizeof(*data)); tell=(unsigned *)malloc((sz+1)*sizeof(*tell)); enc_method=(unsigned *)malloc(sz*sizeof(*enc_method)); ec_enc_init(&enc,ptr,DATA_SIZE2); tell[0]=ec_tell_frac(&enc); for(j=0;j<sz;j++){ data[j]=rand()/((RAND_MAX>>1)+1); logp1[j]=(rand()%15)+1; enc_method[j]=rand()/((RAND_MAX>>2)+1); switch(enc_method[j]){ case 0:{ ec_encode(&enc,data[j]?(1<<logp1[j])-1:0, (1<<logp1[j])-(data[j]?0:1),1<<logp1[j]); }break; case 1:{ ec_encode_bin(&enc,data[j]?(1<<logp1[j])-1:0, (1<<logp1[j])-(data[j]?0:1),logp1[j]); }break; case 2:{ ec_enc_bit_logp(&enc,data[j],logp1[j]); }break; case 3:{ unsigned char icdf[2]; icdf[0]=1; icdf[1]=0; ec_enc_icdf(&enc,data[j],icdf,logp1[j]); }break; } tell[j+1]=ec_tell_frac(&enc); } ec_enc_done(&enc); if((ec_tell(&enc)+7U)/8U<ec_range_bytes(&enc)){ fprintf(stderr,"tell() lied, there's %i bytes instead of %d (Random seed: %u)\n", ec_range_bytes(&enc),(ec_tell(&enc)+7)/8,seed); ret=-1; } ec_dec_init(&dec,ptr,DATA_SIZE2); if(ec_tell_frac(&dec)!=tell[0]){ fprintf(stderr, "Tell mismatch between encoder and decoder at symbol %i: %i instead of %i (Random seed: %u).\n", 0,ec_tell_frac(&dec),tell[0],seed); } for(j=0;j<sz;j++){ int fs; int dec_method; dec_method=rand()/((RAND_MAX>>2)+1); switch(dec_method){ case 0:{ fs=ec_decode(&dec,1<<logp1[j]); sym=fs>=(1<<logp1[j])-1; ec_dec_update(&dec,sym?(1<<logp1[j])-1:0, (1<<logp1[j])-(sym?0:1),1<<logp1[j]); }break; case 1:{ fs=ec_decode_bin(&dec,logp1[j]); sym=fs>=(1<<logp1[j])-1; ec_dec_update(&dec,sym?(1<<logp1[j])-1:0, (1<<logp1[j])-(sym?0:1),1<<logp1[j]); }break; case 2:{ sym=ec_dec_bit_logp(&dec,logp1[j]); }break; case 3:{ unsigned char icdf[2]; icdf[0]=1; icdf[1]=0; sym=ec_dec_icdf(&dec,icdf,logp1[j]); }break; } if(sym!=data[j]){ fprintf(stderr, "Decoded %i instead of %i with logp1 of %i at position %i of %i (Random seed: %u).\n", sym,data[j],logp1[j],j,sz,seed); fprintf(stderr,"Encoding method: %i, decoding method: %i\n", enc_method[j],dec_method); ret=-1; } if(ec_tell_frac(&dec)!=tell[j+1]){ fprintf(stderr, "Tell mismatch between encoder and decoder at symbol %i: %i instead of %i (Random seed: %u).\n", j+1,ec_tell_frac(&dec),tell[j+1],seed); } } free(enc_method); free(tell); free(data); free(logp1); } ec_enc_init(&enc,ptr,DATA_SIZE2); ec_enc_bit_logp(&enc,0,1); ec_enc_bit_logp(&enc,0,1); ec_enc_bit_logp(&enc,0,1); ec_enc_bit_logp(&enc,0,1); ec_enc_bit_logp(&enc,0,2); ec_enc_patch_initial_bits(&enc,3,2); if(enc.error){ fprintf(stderr,"patch_initial_bits failed"); ret=-1; } ec_enc_patch_initial_bits(&enc,0,5); if(!enc.error){ fprintf(stderr,"patch_initial_bits didn't fail when it should have"); ret=-1; } ec_enc_done(&enc); if(ec_range_bytes(&enc)!=1||ptr[0]!=192){ fprintf(stderr,"Got %d when expecting 192 for patch_initial_bits",ptr[0]); ret=-1; } ec_enc_init(&enc,ptr,DATA_SIZE2); ec_enc_bit_logp(&enc,0,1); ec_enc_bit_logp(&enc,0,1); ec_enc_bit_logp(&enc,1,6); ec_enc_bit_logp(&enc,0,2); ec_enc_patch_initial_bits(&enc,0,2); if(enc.error){ fprintf(stderr,"patch_initial_bits failed"); ret=-1; } ec_enc_done(&enc); if(ec_range_bytes(&enc)!=2||ptr[0]!=63){ fprintf(stderr,"Got %d when expecting 63 for patch_initial_bits",ptr[0]); ret=-1; } ec_enc_init(&enc,ptr,2); ec_enc_bit_logp(&enc,0,2); for(i=0;i<48;i++){ ec_enc_bits(&enc,0,1); } ec_enc_done(&enc); if(!enc.error){ fprintf(stderr,"Raw bits overfill didn't fail when it should have"); ret=-1; } ec_enc_init(&enc,ptr,2); for(i=0;i<17;i++){ ec_enc_bits(&enc,0,1); } ec_enc_done(&enc); if(!enc.error){ fprintf(stderr,"17 raw bits encoded in two bytes"); ret=-1; } free(ptr); return ret; }
int main(int _argc,char **_argv){ ec_byte_buffer buf; ec_enc enc; ec_dec dec; long nbits; long nbits2; double entropy; int ft; int ftb; int sym; int sz; int i; int ret; unsigned int seed; ret=0; entropy=0; unsigned char *ptr; if (_argc > 2) { fprintf(stderr, "Usage: %s [<seed>]\n", _argv[0]); return 1; } if (_argc > 1) seed = atoi(_argv[1]); else seed = (time(NULL) ^ (getpid()%(1<<16) << 16)); /*Testing encoding of raw bit values.*/ ptr = malloc(DATA_SIZE); ec_byte_writeinit_buffer(&buf, ptr, DATA_SIZE); ec_enc_init(&enc,&buf); for(ft=2;ft<1024;ft++){ for(i=0;i<ft;i++){ entropy+=log(ft)*M_LOG2E; ec_enc_uint(&enc,i,ft); } } /*Testing encoding of raw bit values.*/ for(ftb=0;ftb<16;ftb++){ for(i=0;i<(1<<ftb);i++){ entropy+=ftb; nbits=ec_enc_tell(&enc,0); ec_enc_bits(&enc,i,ftb); nbits2=ec_enc_tell(&enc,0); if(nbits2-nbits!=ftb){ fprintf(stderr,"Used %li bits to encode %i bits directly.\n", nbits2-nbits,ftb); ret=-1; } } } nbits=ec_enc_tell(&enc,4); ec_enc_done(&enc); fprintf(stderr, "Encoded %0.2lf bits of entropy to %0.2lf bits (%0.3lf%% wasted).\n", entropy,ldexp(nbits,-4),100*(nbits-ldexp(entropy,4))/nbits); fprintf(stderr,"Packed to %li bytes.\n",(long)(buf.ptr-buf.buf)); ec_byte_readinit(&buf,ptr,DATA_SIZE); ec_dec_init(&dec,&buf); for(ft=2;ft<1024;ft++){ for(i=0;i<ft;i++){ sym=ec_dec_uint(&dec,ft); if(sym!=i){ fprintf(stderr,"Decoded %i instead of %i with ft of %i.\n",sym,i,ft); ret=-1; } } } for(ftb=0;ftb<16;ftb++){ for(i=0;i<(1<<ftb);i++){ sym=ec_dec_bits(&dec,ftb); if(sym!=i){ fprintf(stderr,"Decoded %i instead of %i with ftb of %i.\n",sym,i,ftb); ret=-1; } } } nbits2=ec_dec_tell(&dec,4); if(nbits!=nbits2){ fprintf(stderr, "Reported number of bits used was %0.2lf, should be %0.2lf.\n", ldexp(nbits2,-4),ldexp(nbits,-4)); ret=-1; } ec_byte_writeclear(&buf); srand(seed); fprintf(stderr,"Testing random streams... Random seed: %u (%.4X)\n", seed, rand() % 65536); for(i=0;i<409600;i++){ unsigned *data; int j; int tell_bits; int zeros; ft=rand()/((RAND_MAX>>(rand()%11))+1)+10; sz=rand()/((RAND_MAX>>(rand()%9))+1); data=(unsigned *)malloc(sz*sizeof(*data)); ec_byte_writeinit_buffer(&buf, ptr, DATA_SIZE2); ec_enc_init(&enc,&buf); zeros = rand()%13==0; for(j=0;j<sz;j++){ if (zeros) data[j]=0; else data[j]=rand()%ft; ec_enc_uint(&enc,data[j],ft); } if (rand()%2==0) while(ec_enc_tell(&enc, 0)%8 != 0) ec_enc_uint(&enc, rand()%2, 2); tell_bits = ec_enc_tell(&enc, 0); ec_enc_done(&enc); if ((tell_bits+7)/8 < ec_byte_bytes(&buf)) { fprintf (stderr, "tell() lied, there's %li bytes instead of %d (Random seed: %u)\n", ec_byte_bytes(&buf), (tell_bits+7)/8,seed); ret=-1; } tell_bits -= 8*ec_byte_bytes(&buf); ec_byte_readinit(&buf,ptr,DATA_SIZE2); ec_dec_init(&dec,&buf); for(j=0;j<sz;j++){ sym=ec_dec_uint(&dec,ft); if(sym!=data[j]){ fprintf(stderr, "Decoded %i instead of %i with ft of %i at position %i of %i (Random seed: %u).\n", sym,data[j],ft,j,sz,seed); ret=-1; } } ec_byte_writeclear(&buf); free(data); } free(ptr); return ret; }