static vorbis_look_mapping *mapping0_look(vorbis_dsp_state *vd,vorbis_info_mode *vm, vorbis_info_mapping *m){ int i; vorbis_info *vi=vd->vi; codec_setup_info *ci=vi->codec_setup; vorbis_look_mapping0 *look=_ogg_calloc(1,sizeof(vorbis_look_mapping0)); vorbis_info_mapping0 *info=look->map=(vorbis_info_mapping0 *)m; look->mode=vm; look->time_look=_ogg_calloc(info->submaps,sizeof(vorbis_look_time *)); look->floor_look=_ogg_calloc(info->submaps,sizeof(vorbis_look_floor *)); look->residue_look=_ogg_calloc(info->submaps,sizeof(vorbis_look_residue *)); look->time_func=_ogg_calloc(info->submaps,sizeof(vorbis_func_time *)); look->floor_func=_ogg_calloc(info->submaps,sizeof(vorbis_func_floor *)); look->residue_func=_ogg_calloc(info->submaps,sizeof(vorbis_func_residue *)); for(i=0;i<info->submaps;i++){ int timenum=info->timesubmap[i]; int floornum=info->floorsubmap[i]; int resnum=info->residuesubmap[i]; look->time_func[i]=_time_P[ci->time_type[timenum]]; look->time_look[i]=look->time_func[i]-> look(vd,vm,ci->time_param[timenum]); look->floor_func[i]=_floor_P[ci->floor_type[floornum]]; look->floor_look[i]=look->floor_func[i]-> look(vd,vm,ci->floor_param[floornum]); look->residue_func[i]=_residue_P[ci->residue_type[resnum]]; look->residue_look[i]=look->residue_func[i]-> look(vd,vm,ci->residue_param[resnum]); } if(ci->psys && vd->analysisp){ if(info->psy[0] != info->psy[1]){ int psynum=info->psy[0]; look->psy_look[0]=_ogg_calloc(1,sizeof(vorbis_look_psy)); _vp_psy_init(look->psy_look[0],ci->psy_param[psynum], ci->psy_g_param, ci->blocksizes[vm->blockflag]/2,vi->rate); psynum=info->psy[1]; look->psy_look[1]=_ogg_calloc(1,sizeof(vorbis_look_psy)); _vp_psy_init(look->psy_look[1],ci->psy_param[psynum], ci->psy_g_param, ci->blocksizes[vm->blockflag]/2,vi->rate); }else{ int psynum=info->psy[0]; look->psy_look[0]=_ogg_calloc(1,sizeof(vorbis_look_psy)); look->psy_look[1]=look->psy_look[0]; _vp_psy_init(look->psy_look[0],ci->psy_param[psynum], ci->psy_g_param, ci->blocksizes[vm->blockflag]/2,vi->rate); } } look->ch=vi->channels; if(vd->analysisp)drft_init(&look->fft_look,ci->blocksizes[vm->blockflag]); return(look); }
bm->minmax_posstack=_ogg_calloc((bins*2+1), sizeof(*bm->minmax_posstack)); bm->minmax_limitstack=_ogg_calloc((bins*2+1), sizeof(*bm->minmax_limitstack)); }else{ bm->minmax_tail= -1; } /* space for the packet queueing */ bm->packetbuffers=_ogg_calloc(maxpackets,sizeof(*bm->packetbuffers)); bm->packets=_ogg_calloc(maxpackets,sizeof(*bm->packets)); for(i=0;i<maxpackets;i++) oggpack_writeinit(bm->packetbuffers+i); }else{ bm->packetbuffers=_ogg_calloc(1,sizeof(*bm->packetbuffers)); bm->packets=_ogg_calloc(1,sizeof(*bm->packets)); oggpack_writeinit(bm->packetbuffers); } } } void vorbis_bitrate_clear(bitrate_manager_state *bm){ int i; if(bm){ if(bm->queue_binned)_ogg_free(bm->queue_binned); if(bm->queue_actual)_ogg_free(bm->queue_actual); if(bm->avg_binacc)_ogg_free(bm->avg_binacc); if(bm->minmax_binstack)_ogg_free(bm->minmax_binstack); if(bm->minmax_posstack)_ogg_free(bm->minmax_posstack);
/* used by synthesis, which has a full, alloced vi */ void vorbis_info_init(vorbis_info *vi){ memset(vi,0,sizeof(*vi)); vi->codec_setup=_ogg_calloc(1,sizeof(codec_setup_info)); }
static int _vds_shared_init(vorbis_dsp_state *v,vorbis_info *vi,int encp){ int i; codec_setup_info *ci=vi->codec_setup; private_state *b=NULL; int hs; if(ci==NULL) return 1; hs=ci->halfrate_flag; memset(v,0,sizeof(*v)); b=v->backend_state=_ogg_calloc(1,sizeof(*b)); v->vi=vi; b->modebits=ilog2(ci->modes); b->transform[0]=_ogg_calloc(VI_TRANSFORMB,sizeof(*b->transform[0])); b->transform[1]=_ogg_calloc(VI_TRANSFORMB,sizeof(*b->transform[1])); /* MDCT is tranform 0 */ b->transform[0][0]=_ogg_calloc(1,sizeof(mdct_lookup)); b->transform[1][0]=_ogg_calloc(1,sizeof(mdct_lookup)); mdct_init(b->transform[0][0],ci->blocksizes[0]>>hs); mdct_init(b->transform[1][0],ci->blocksizes[1]>>hs); /* Vorbis I uses only window type 0 */ b->window[0]=ilog2(ci->blocksizes[0])-6; b->window[1]=ilog2(ci->blocksizes[1])-6; if(encp){ /* encode/decode differ here */ /* analysis always needs an fft */ drft_init(&b->fft_look[0],ci->blocksizes[0]); drft_init(&b->fft_look[1],ci->blocksizes[1]); /* finish the codebooks */ if(!ci->fullbooks){ ci->fullbooks=_ogg_calloc(ci->books,sizeof(*ci->fullbooks)); for(i=0;i<ci->books;i++) vorbis_book_init_encode(ci->fullbooks+i,ci->book_param[i]); } b->psy=_ogg_calloc(ci->psys,sizeof(*b->psy)); for(i=0;i<ci->psys;i++){ _vp_psy_init(b->psy+i, ci->psy_param[i], &ci->psy_g_param, ci->blocksizes[ci->psy_param[i]->blockflag]/2, vi->rate); } v->analysisp=1; }else{ /* finish the codebooks */ if(!ci->fullbooks){ ci->fullbooks=_ogg_calloc(ci->books,sizeof(*ci->fullbooks)); for(i=0;i<ci->books;i++){ if(ci->book_param[i]==NULL) goto abort_books; if(vorbis_book_init_decode(ci->fullbooks+i,ci->book_param[i])) goto abort_books; /* decode codebooks are now standalone after init */ vorbis_staticbook_destroy(ci->book_param[i]); ci->book_param[i]=NULL; } } } /* initialize the storage vectors. blocksize[1] is small for encode, but the correct size for decode */ v->pcm_storage=ci->blocksizes[1]; v->pcm=_ogg_malloc(vi->channels*sizeof(*v->pcm)); v->pcmret=_ogg_malloc(vi->channels*sizeof(*v->pcmret)); { int i; for(i=0;i<vi->channels;i++) v->pcm[i]=_ogg_calloc(v->pcm_storage,sizeof(*v->pcm[i])); } /* all 1 (large block) or 0 (small block) */ /* explicitly set for the sake of clarity */ v->lW=0; /* previous window size */ v->W=0; /* current window size */ /* all vector indexes */ v->centerW=ci->blocksizes[1]/2; v->pcm_current=v->centerW; /* initialize all the backend lookups */ b->flr=_ogg_calloc(ci->floors,sizeof(*b->flr)); b->residue=_ogg_calloc(ci->residues,sizeof(*b->residue)); for(i=0;i<ci->floors;i++) b->flr[i]=_floor_P[ci->floor_type[i]]-> look(v,ci->floor_param[i]); for(i=0;i<ci->residues;i++) b->residue[i]=_residue_P[ci->residue_type[i]]-> look(v,ci->residue_param[i]); return 0; abort_books: for(i=0;i<ci->books;i++){ if(ci->book_param[i]!=NULL){ vorbis_staticbook_destroy(ci->book_param[i]); ci->book_param[i]=NULL; } } vorbis_dsp_clear(v); return -1; }
int main(int argc,char *argv[]){ codebook *b; static_codebook *c; long *lengths; long *hits; int entries=-1,dim=-1,guard=1; FILE *in=NULL; char *line,*name; long j; if(argv[1]==NULL){ fprintf(stderr,"Need a lattice codebook on the command line.\n"); exit(1); } if(argv[2]==NULL){ fprintf(stderr,"Need a codeword data file on the command line.\n"); exit(1); } if(argv[3]!=NULL)guard=0; { char *ptr; char *filename=strdup(argv[1]); b=codebook_load(filename); c=(static_codebook *)(b->c); ptr=strrchr(filename,'.'); if(ptr){ *ptr='\0'; name=strdup(filename); }else{ name=strdup(filename); } } if(c->maptype!=1){ fprintf(stderr,"Provided book is not a latticebook.\n"); exit(1); } entries=b->entries; dim=b->dim; hits=_ogg_malloc(entries*sizeof(long)); lengths=_ogg_calloc(entries,sizeof(long)); for(j=0;j<entries;j++)hits[j]=guard; in=fopen(argv[2],"r"); if(!in){ fprintf(stderr,"Could not open input file %s\n",argv[2]); exit(1); } if(!strrcmp_i(argv[0],"latticetune")){ long lines=0; line=setup_line(in); while(line){ long code; lines++; if(!(lines&0xfff))spinnit("codewords so far...",lines); if(sscanf(line,"%ld",&code)==1) hits[code]++; line=setup_line(in); } } /* now we simply count already collated by-entry data */ if(!strrcmp_i(argv[0],"res0tune") || !strrcmp_i(argv[0],"res1tune")){ line=setup_line(in); while(line){ /* code:hits\n */ /* likely to have multiple listing for each code entry; must accumulate */ char *pos=strchr(line,':'); if(pos){ long code=atol(line); long val=atol(pos+1); hits[code]+=val; } line=setup_line(in); } } fclose(in); /* build the codeword lengths */ build_tree_from_lengths0(entries,hits,lengths); c->lengthlist=lengths; write_codebook(stdout,name,c); { long bins=_book_maptype1_quantvals(c); long i,k,base=c->lengthlist[0]; for(i=0;i<entries;i++) if(c->lengthlist[i]>base)base=c->lengthlist[i]; for(j=0;j<entries;j++){ if(c->lengthlist[j]){ int indexdiv=1; fprintf(stderr,"%4ld: ",j); for(k=0;k<c->dim;k++){ int index= (j/indexdiv)%bins; fprintf(stderr,"%+3.1f,", c->quantlist[index]*_float32_unpack(c->q_delta)+ _float32_unpack(c->q_min)); indexdiv*=bins; } fprintf(stderr,"\t|"); for(k=0;k<base-c->lengthlist[j];k++)fprintf(stderr,"*"); fprintf(stderr,"\n"); } } } fprintf(stderr,"\r " "\nDone.\n"); exit(0); }
/* vorbis_info is for range checking */ vorbis_info_residue *res0_unpack(vorbis_info *vi,oggpack_buffer *opb){ int j,acc=0; vorbis_info_residue0 *info=(vorbis_info_residue0 *)_ogg_calloc(1,sizeof(*info)); codec_setup_info *ci=(codec_setup_info *)vi->codec_setup; info->begin=oggpack_read(opb,24); info->end=oggpack_read(opb,24); info->grouping=oggpack_read(opb,24)+1; info->partitions=oggpack_read(opb,6)+1; info->groupbook=oggpack_read(opb,8); /* check for premature EOP */ if(info->groupbook<0)goto errout; for(j=0;j<info->partitions;j++){ int cascade=oggpack_read(opb,3); int cflag=oggpack_read(opb,1); if(cflag<0) goto errout; if(cflag){ int c=oggpack_read(opb,5); if(c<0) goto errout; cascade|=(c<<3); } info->secondstages[j]=cascade; acc+=icount(cascade); } for(j=0;j<acc;j++){ int book=oggpack_read(opb,8); if(book<0) goto errout; info->booklist[j]=book; } if(info->groupbook>=ci->books)goto errout; for(j=0;j<acc;j++){ if(info->booklist[j]>=ci->books)goto errout; if(ci->book_param[info->booklist[j]]->maptype==0)goto errout; } /* verify the phrasebook is not specifying an impossible or inconsistent partitioning scheme. */ /* modify the phrasebook ranging check from r16327; an early beta encoder had a bug where it used an oversized phrasebook by accident. These files should continue to be playable, but don't allow an exploit */ { int entries = ci->book_param[info->groupbook]->entries; int dim = ci->book_param[info->groupbook]->dim; int partvals = 1; if (dim<1) goto errout; while(dim>0){ partvals *= info->partitions; if(partvals > entries) goto errout; dim--; } info->partvals = partvals; } return(info); errout: res0_free_info(info); return(NULL); }
static vorbis_info_floor *floor1_unpack (vorbis_info *vi,oggpack_buffer *opb){ codec_setup_info *ci=vi->codec_setup; int j,k,count=0,maxclass=-1,rangebits; vorbis_info_floor1 *info=_ogg_calloc(1,sizeof(*info)); /* read partitions */ info->partitions=oggpack_read(opb,5); /* only 0 to 31 legal */ for(j=0;j<info->partitions;j++){ info->partitionclass[j]=oggpack_read(opb,4); /* only 0 to 15 legal */ if(info->partitionclass[j]<0)goto err_out; if(maxclass<info->partitionclass[j])maxclass=info->partitionclass[j]; } /* read partition classes */ for(j=0;j<maxclass+1;j++){ info->class_dim[j]=oggpack_read(opb,3)+1; /* 1 to 8 */ info->class_subs[j]=oggpack_read(opb,2); /* 0,1,2,3 bits */ if(info->class_subs[j]<0) goto err_out; if(info->class_subs[j])info->class_book[j]=oggpack_read(opb,8); if(info->class_book[j]<0 || info->class_book[j]>=ci->books) goto err_out; for(k=0;k<(1<<info->class_subs[j]);k++){ info->class_subbook[j][k]=oggpack_read(opb,8)-1; if(info->class_subbook[j][k]<-1 || info->class_subbook[j][k]>=ci->books) goto err_out; } } /* read the post list */ info->mult=oggpack_read(opb,2)+1; /* only 1,2,3,4 legal now */ rangebits=oggpack_read(opb,4); if(rangebits<0)goto err_out; for(j=0,k=0;j<info->partitions;j++){ count+=info->class_dim[info->partitionclass[j]]; if(count>VIF_POSIT) goto err_out; for(;k<count;k++){ int t=info->postlist[k+2]=oggpack_read(opb,rangebits); if(t<0 || t>=(1<<rangebits)) goto err_out; } } info->postlist[0]=0; info->postlist[1]=1<<rangebits; /* don't allow repeated values in post list as they'd result in zero-length segments */ { int *sortpointer[VIF_POSIT+2]; for(j=0;j<count+2;j++)sortpointer[j]=info->postlist+j; qsort(sortpointer,count+2,sizeof(*sortpointer),icomp); for(j=1;j<count+2;j++) if(*sortpointer[j-1]==*sortpointer[j])goto err_out; } return(info); err_out: floor1_free_info(info); return(NULL); }
int theora_encode_init(theora_state *th, theora_info *c){ int i; CP_INSTANCE *cpi; memset(th, 0, sizeof(*th)); /*Currently only the 4:2:0 format is supported.*/ if(c->pixelformat!=OC_PF_420)return OC_IMPL; th->internal_encode=cpi=_ogg_calloc(1,sizeof(*cpi)); theora_encode_dispatch_init(cpi); dsp_static_init (&cpi->dsp); memcpy (&cpi->pb.dsp, &cpi->dsp, sizeof(DspFunctions)); c->version_major=TH_VERSION_MAJOR; c->version_minor=TH_VERSION_MINOR; c->version_subminor=TH_VERSION_SUB; InitTmpBuffers(&cpi->pb); InitPPInstance(&cpi->pp, &cpi->dsp); /* Initialise Configuration structure to legal values */ if(c->quality>63)c->quality=63; if(c->quality<0)c->quality=32; if(c->target_bitrate<0)c->target_bitrate=0; /* we clamp target_bitrate to 24 bits after setting up the encoder */ cpi->Configuration.BaseQ = c->quality; cpi->Configuration.FirstFrameQ = c->quality; cpi->Configuration.MaxQ = c->quality; cpi->Configuration.ActiveMaxQ = c->quality; cpi->MVChangeFactor = 14; cpi->FourMvChangeFactor = 8; cpi->MinImprovementForNewMV = 25; cpi->ExhaustiveSearchThresh = 2500; cpi->MinImprovementForFourMV = 100; cpi->FourMVThreshold = 10000; cpi->BitRateCapFactor = 1.5; cpi->InterTripOutThresh = 5000; cpi->MVEnabled = 1; cpi->InterCodeCount = 127; cpi->BpbCorrectionFactor = 1.0; cpi->GoldenFrameEnabled = 1; cpi->InterPrediction = 1; cpi->MotionCompensation = 1; cpi->ThreshMapThreshold = 5; cpi->MaxConsDroppedFrames = 1; /* Set encoder flags. */ /* if not AutoKeyframing cpi->ForceKeyFrameEvery = is frequency */ if(!c->keyframe_auto_p) c->keyframe_frequency_force = c->keyframe_frequency; /* Set the frame rate variables. */ if ( c->fps_numerator < 1 ) c->fps_numerator = 1; if ( c->fps_denominator < 1 ) c->fps_denominator = 1; /* don't go too nuts on keyframe spacing; impose a high limit to make certain the granulepos encoding strategy works */ if(c->keyframe_frequency_force>32768)c->keyframe_frequency_force=32768; if(c->keyframe_mindistance>32768)c->keyframe_mindistance=32768; if(c->keyframe_mindistance>c->keyframe_frequency_force) c->keyframe_mindistance=c->keyframe_frequency_force; cpi->pb.keyframe_granule_shift=_ilog(c->keyframe_frequency_force-1); /* clamp the target_bitrate to a maximum of 24 bits so we get a more meaningful value when we write this out in the header. */ if(c->target_bitrate>(1<<24)-1)c->target_bitrate=(1<<24)-1; /* copy in config */ memcpy(&cpi->pb.info,c,sizeof(*c)); th->i=&cpi->pb.info; th->granulepos=-1; /* Set up default values for QTargetModifier[Q_TABLE_SIZE] table */ for ( i = 0; i < Q_TABLE_SIZE; i++ ) cpi->QTargetModifier[i] = 1.0; /* Set up an encode buffer */ cpi->oggbuffer = _ogg_malloc(sizeof(oggpack_buffer)); oggpackB_writeinit(cpi->oggbuffer); /* Set data rate related variables. */ cpi->Configuration.TargetBandwidth = (c->target_bitrate) / 8; cpi->Configuration.OutputFrameRate = (double)( c->fps_numerator / c->fps_denominator ); cpi->frame_target_rate = cpi->Configuration.TargetBandwidth / cpi->Configuration.OutputFrameRate; /* Set key frame data rate target; this is nominal keyframe size */ cpi->Configuration.KeyFrameDataTarget = (c->keyframe_data_target_bitrate * c->fps_denominator / c->fps_numerator ) / 8; /* Note the height and width in the pre-processor control structure. */ cpi->ScanConfig.VideoFrameHeight = cpi->pb.info.height; cpi->ScanConfig.VideoFrameWidth = cpi->pb.info.width; InitFrameDetails(&cpi->pb); EInitFragmentInfo(cpi); EInitFrameInfo(cpi); /* Set up pre-processor config pointers. */ cpi->ScanConfig.Yuv0ptr = cpi->yuv0ptr; cpi->ScanConfig.Yuv1ptr = cpi->yuv1ptr; cpi->ScanConfig.SrfWorkSpcPtr = cpi->ConvDestBuffer; cpi->ScanConfig.disp_fragments = cpi->pb.display_fragments; cpi->ScanConfig.RegionIndex = cpi->pb.pixel_index_table; /* Initialise the pre-processor module. */ ScanYUVInit(&cpi->pp, &(cpi->ScanConfig)); /* Initialise Motion compensation */ InitMotionCompensation(cpi); /* Initialise the compression process. */ /* We always start at frame 1 */ cpi->CurrentFrame = 1; /* Reset the rate targeting correction factor. */ cpi->BpbCorrectionFactor = 1.0; cpi->TotalByteCount = 0; cpi->TotalMotionScore = 0; /* Up regulation variables. */ cpi->FinalPassLastPos = 0; /* Used to regulate a final unrestricted pass. */ cpi->LastEndSB = 0; /* Where we were in the loop last time. */ cpi->ResidueLastEndSB = 0; /* Where we were in the residue update loop last time. */ InitHuffmanSet(&cpi->pb); /* This makes sure encoder version specific tables are initialised */ memcpy(&cpi->pb.quant_info, &TH_VP31_QUANT_INFO, sizeof(th_quant_info)); InitQTables(&cpi->pb); /* Indicate that the next frame to be compressed is the first in the current clip. */ cpi->ThisIsFirstFrame = 1; cpi->readyflag = 1; cpi->pb.HeadersWritten = 0; /*We overload this flag to track header output.*/ cpi->doneflag=-3; return 0; }
static vorbis_info_mapping *mapping0_unpack(vorbis_info *vi,oggpack_buffer *opb) { int i; vorbis_info_mapping0 *info=_ogg_calloc(1,sizeof(*info)); codec_setup_info *ci=vi->codec_setup; if(!info) goto err_out; _ogg_memset(info,0,sizeof(*info)); if(oggpack_read1(opb)) info->submaps=oggpack_read24(opb,4)+1; else info->submaps=1; if(oggpack_read1(opb)){ info->coupling_steps=oggpack_read24(opb,8)+1; info->coupling_mag=_ogg_malloc(sizeof(*info->coupling_mag)*info->coupling_steps); info->coupling_ang=_ogg_malloc(sizeof(*info->coupling_ang)*info->coupling_steps); if(!info->coupling_mag || !info->coupling_ang) goto err_out; for(i=0;i<info->coupling_steps;i++){ int testM=info->coupling_mag[i]=oggpack_read24(opb,ilog(vi->channels)); int testA=info->coupling_ang[i]=oggpack_read24(opb,ilog(vi->channels)); if(testM<0 || testA<0 || testM==testA || testM>=vi->channels || testA>=vi->channels) goto err_out; } } if(oggpack_read24(opb,2)!=0) goto err_out; info->chmuxlist=_ogg_calloc(vi->channels,sizeof(*info->chmuxlist)); if(!info->chmuxlist) goto err_out; if(info->submaps>1){ for(i=0;i<vi->channels;i++){ info->chmuxlist[i]=oggpack_read24(opb,4); if(info->chmuxlist[i]>=info->submaps) goto err_out; } } info->floorsubmap=_ogg_malloc(sizeof(*info->floorsubmap)*info->submaps); info->residuesubmap=_ogg_malloc(sizeof(*info->residuesubmap)*info->submaps); if(!info->floorsubmap || !info->residuesubmap) goto err_out; for(i=0;i<info->submaps;i++){ oggpack_adv(opb,8); info->floorsubmap[i]=oggpack_read24(opb,8); if(info->floorsubmap[i]>=ci->floors) goto err_out; info->residuesubmap[i]=oggpack_read24(opb,8); if(info->residuesubmap[i]>=ci->residues) goto err_out; } info->pcmbundle =_ogg_malloc(sizeof(*info->pcmbundle)*vi->channels); info->nonzero =_ogg_malloc(sizeof(*info->nonzero)*vi->channels); info->floormemo =_ogg_malloc(sizeof(*info->floormemo)*vi->channels); if(!info->pcmbundle || !info->nonzero || !info->floormemo) goto err_out; return info; err_out: mapping0_free_info(info); return(NULL); }
static int _vds_init(vorbis_dsp_state *v,vorbis_info *vi){ int i; codec_setup_info *ci=(codec_setup_info *)vi->codec_setup; private_state *b=NULL; if(ci==NULL) return 1; memset(v,0,sizeof(*v)); b=(private_state *)(v->backend_state=_ogg_calloc(1,sizeof(*b))); v->vi=vi; b->modebits=ilog(ci->modes); /* Vorbis I uses only window type 0 */ b->window[0]=_vorbis_window(0,ci->blocksizes[0]/2); b->window[1]=_vorbis_window(0,ci->blocksizes[1]/2); /* finish the codebooks */ if(!ci->fullbooks){ ci->fullbooks=(codebook *)_ogg_calloc(ci->books,sizeof(*ci->fullbooks)); for(i=0;i<ci->books;i++){ if(ci->book_param[i]==NULL) goto abort_books; if(vorbis_book_init_decode(ci->fullbooks+i,ci->book_param[i])) goto abort_books; /* decode codebooks are now standalone after init */ vorbis_staticbook_destroy(ci->book_param[i]); ci->book_param[i]=NULL; } } v->pcm_storage=ci->blocksizes[1]; v->pcm=(ogg_int32_t **)_ogg_malloc(vi->channels*sizeof(*v->pcm)); v->pcmret=(ogg_int32_t **)_ogg_malloc(vi->channels*sizeof(*v->pcmret)); for(i=0;i<vi->channels;i++) v->pcm[i]=(ogg_int32_t *)_ogg_calloc(v->pcm_storage,sizeof(*v->pcm[i])); /* all 1 (large block) or 0 (small block) */ /* explicitly set for the sake of clarity */ v->lW=0; /* previous window size */ v->W=0; /* current window size */ /* initialize all the mapping/backend lookups */ b->mode=(vorbis_look_mapping **)_ogg_calloc(ci->modes,sizeof(*b->mode)); for(i=0;i<ci->modes;i++){ int mapnum=ci->mode_param[i]->mapping; int maptype=ci->map_type[mapnum]; b->mode[i]=_mapping_P[maptype]->look(v,ci->mode_param[i], ci->map_param[mapnum]); } return 0; abort_books: for(i=0;i<ci->books;i++){ if(ci->book_param[i]!=NULL){ vorbis_staticbook_destroy(ci->book_param[i]); ci->book_param[i]=NULL; } } vorbis_dsp_clear(v); return -1; }
/* compute bitrate tracking setup, allocate circular packet size queue */ void vorbis_bitrate_init(vorbis_info *vi,bitrate_manager_state *bm) { int i; codec_setup_info *ci=vi->codec_setup; bitrate_manager_info *bi=&ci->bi; long maxlatency; memset(bm,0,sizeof(*bm)); if(bi) { bm->avg_sampledesired=bi->queue_avg_time*vi->rate; bm->avg_centerdesired=bi->queue_avg_time*vi->rate*bi->queue_avg_center; bm->minmax_sampledesired=bi->queue_minmax_time*vi->rate; /* first find the max possible needed queue size */ maxlatency=max(bm->avg_sampledesired-bm->avg_centerdesired, bm->minmax_sampledesired)+bm->avg_centerdesired; if(maxlatency>0 && (bi->queue_avgmin>0 || bi->queue_avgmax>0 || bi->queue_hardmax>0 || bi->queue_hardmin>0)) { long maxpackets=maxlatency/(ci->blocksizes[0]>>1)+3; long bins=PACKETBLOBS; bm->queue_size=maxpackets; bm->queue_bins=bins; bm->queue_binned=_ogg_calloc(maxpackets,bins*sizeof(*bm->queue_binned)); bm->queue_actual=_ogg_calloc(maxpackets,sizeof(*bm->queue_actual)); if((bi->queue_avgmin>0 || bi->queue_avgmax>0) && bi->queue_avg_time>0) { bm->avg_binacc=_ogg_calloc(bins,sizeof(*bm->avg_binacc)); bm->avgfloat=PACKETBLOBS/2; } else { bm->avg_tail= -1; } if((bi->queue_hardmin>0 || bi->queue_hardmax>0) && bi->queue_minmax_time>0) { bm->minmax_binstack=_ogg_calloc((bins*2+1)*bins*2, sizeof(*bm->minmax_binstack)); bm->minmax_posstack=_ogg_calloc((bins*2+1), sizeof(*bm->minmax_posstack)); bm->minmax_limitstack=_ogg_calloc((bins*2+1), sizeof(*bm->minmax_limitstack)); } else { bm->minmax_tail= -1; } /* space for the packet queueing */ bm->packetbuffers=_ogg_calloc(maxpackets,sizeof(*bm->packetbuffers)); bm->packets=_ogg_calloc(maxpackets,sizeof(*bm->packets)); for(i=0; i<maxpackets; i++) oggpack_writeinit(bm->packetbuffers+i); } else {
int main(int argc,char *argv[]){ char *basename; codebook **b=_ogg_calloc(1,sizeof(codebook *)); int *addmul=_ogg_calloc(1,sizeof(int)); int books=0; int input=0; int interleave=0; int j; int start=0; int num=-1; argv++; if(*argv==NULL){ process_usage(); exit(1); } /* yes, this is evil. However, it's very convenient to parse file extentions */ while(*argv){ if(*argv[0]=='-'){ /* option */ if(argv[0][1]=='s'){ /* subvector */ if(sscanf(argv[1],"%d,%d",&start,&num)!=2){ num= -1; if(sscanf(argv[1],"%d",&start)!=1){ fprintf(stderr,"Syntax error using -s\n"); exit(1); } } argv+=2; } if(argv[0][1]=='i'){ /* interleave */ interleave=1; argv+=1; } }else{ /* input file. What kind? */ char *dot; char *ext=NULL; char *name=strdup(*argv++); dot=strrchr(name,'.'); if(dot) ext=dot+1; else ext=""; /* codebook */ if(!strcmp(ext,"vqh")){ int multp=0; if(input){ fprintf(stderr,"specify all input data (.vqd) files following\n" "codebook header (.vqh) files\n"); exit(1); } /* is it additive or multiplicative? */ if(name[0]=='*'){ multp=1; name++; } if(name[0]=='+')name++; basename=strrchr(name,'/'); if(basename) basename=strdup(basename)+1; else basename=strdup(name); dot=strrchr(basename,'.'); if(dot)*dot='\0'; b=_ogg_realloc(b,sizeof(codebook *)*(books+2)); b[books]=codebook_load(name); addmul=_ogg_realloc(addmul,sizeof(int)*(books+1)); addmul[books++]=multp; b[books]=NULL; } /* data file */ if(!strcmp(ext,"vqd")){ int cols; long lines=0; char *line; float *vec; FILE *in=fopen(name,"r"); if(!in){ fprintf(stderr,"Could not open input file %s\n",name); exit(1); } if(!input){ process_preprocess(b,basename); input++; } reset_next_value(); line=setup_line(in); /* count cols before we start reading */ { char *temp=line; while(*temp==' ')temp++; for(cols=0;*temp;cols++){ while(*temp>32)temp++; while(*temp==' ')temp++; } } vec=alloca(cols*sizeof(float)); while(line){ lines++; for(j=0;j<cols;j++) if(get_line_value(in,vec+j)){ fprintf(stderr,"Too few columns on line %ld in data file\n",lines); exit(1); } /* ignores -s for now */ process_vector(b,addmul,interleave,vec,cols); line=setup_line(in); } fclose(in); } } } /* take any data from stdin */ { struct stat st; if(fstat(STDIN_FILENO,&st)==-1){ fprintf(stderr,"Could not stat STDIN\n"); exit(1); } if((S_IFIFO|S_IFREG|S_IFSOCK)&st.st_mode){ int cols; char *line; long lines=0; float *vec; if(!input){ process_preprocess(b,basename); input++; } line=setup_line(stdin); /* count cols before we start reading */ { char *temp=line; while(*temp==' ')temp++; for(cols=0;*temp;cols++){ while(*temp>32)temp++; while(*temp==' ')temp++; } } vec=alloca(cols*sizeof(float)); while(line){ lines++; for(j=0;j<cols;j++) if(get_line_value(stdin,vec+j)){ fprintf(stderr,"Too few columns on line %ld in data file\n",lines); exit(1); } /* ignores -s for now */ process_vector(b,addmul,interleave,vec,cols); line=setup_line(stdin); } } } process_postprocess(b,basename); return 0; }
static int _vds_shared_init(vorbis_dsp_state *v,vorbis_info *vi,int encp){ int i; codec_setup_info *ci=vi->codec_setup; backend_lookup_state *b=NULL; memset(v,0,sizeof(*v)); b=v->backend_state=_ogg_calloc(1,sizeof(*b)); v->vi=vi; b->modebits=ilog2(ci->modes); b->transform[0]=_ogg_calloc(VI_TRANSFORMB,sizeof(*b->transform[0])); b->transform[1]=_ogg_calloc(VI_TRANSFORMB,sizeof(*b->transform[1])); /* MDCT is tranform 0 */ b->transform[0][0]=_ogg_calloc(1,sizeof(mdct_lookup)); b->transform[1][0]=_ogg_calloc(1,sizeof(mdct_lookup)); mdct_init(b->transform[0][0],ci->blocksizes[0]); mdct_init(b->transform[1][0],ci->blocksizes[1]); b->window[0][0][0]=_ogg_calloc(VI_WINDOWB,sizeof(*b->window[0][0][0])); b->window[0][0][1]=b->window[0][0][0]; b->window[0][1][0]=b->window[0][0][0]; b->window[0][1][1]=b->window[0][0][0]; b->window[1][0][0]=_ogg_calloc(VI_WINDOWB,sizeof(*b->window[1][0][0])); b->window[1][0][1]=_ogg_calloc(VI_WINDOWB,sizeof(*b->window[1][0][1])); b->window[1][1][0]=_ogg_calloc(VI_WINDOWB,sizeof(*b->window[1][1][0])); b->window[1][1][1]=_ogg_calloc(VI_WINDOWB,sizeof(*b->window[1][1][1])); for(i=0;i<VI_WINDOWB;i++){ b->window[0][0][0][i]= _vorbis_window(i,ci->blocksizes[0],ci->blocksizes[0]/2,ci->blocksizes[0]/2); b->window[1][0][0][i]= _vorbis_window(i,ci->blocksizes[1],ci->blocksizes[0]/2,ci->blocksizes[0]/2); b->window[1][0][1][i]= _vorbis_window(i,ci->blocksizes[1],ci->blocksizes[0]/2,ci->blocksizes[1]/2); b->window[1][1][0][i]= _vorbis_window(i,ci->blocksizes[1],ci->blocksizes[1]/2,ci->blocksizes[0]/2); b->window[1][1][1][i]= _vorbis_window(i,ci->blocksizes[1],ci->blocksizes[1]/2,ci->blocksizes[1]/2); } if(encp){ /* encode/decode differ here */ /* finish the codebooks */ b->fullbooks=_ogg_calloc(ci->books,sizeof(*b->fullbooks)); for(i=0;i<ci->books;i++) vorbis_book_init_encode(b->fullbooks+i,ci->book_param[i]); v->analysisp=1; }else{ /* finish the codebooks */ b->fullbooks=_ogg_calloc(ci->books,sizeof(*b->fullbooks)); for(i=0;i<ci->books;i++) vorbis_book_init_decode(b->fullbooks+i,ci->book_param[i]); } /* initialize the storage vectors to a decent size greater than the minimum */ v->pcm_storage=8192; /* we'll assume later that we have a minimum of twice the blocksize of accumulated samples in analysis */ v->pcm=_ogg_malloc(vi->channels*sizeof(*v->pcm)); v->pcmret=_ogg_malloc(vi->channels*sizeof(*v->pcmret)); { int i; for(i=0;i<vi->channels;i++) v->pcm[i]=_ogg_calloc(v->pcm_storage,sizeof(*v->pcm[i])); } /* all 1 (large block) or 0 (small block) */ /* explicitly set for the sake of clarity */ v->lW=0; /* previous window size */ v->W=0; /* current window size */ /* all vector indexes */ v->centerW=ci->blocksizes[1]/2; v->pcm_current=v->centerW; /* initialize all the mapping/backend lookups */ b->mode=_ogg_calloc(ci->modes,sizeof(*b->mode)); for(i=0;i<ci->modes;i++){ int mapnum=ci->mode_param[i]->mapping; int maptype=ci->map_type[mapnum]; b->mode[i]=_mapping_P[maptype]->look(v,ci->mode_param[i], ci->map_param[mapnum]); } return(0); }
static int oc_dec_headerin(oc_pack_buf *_opb,th_info *_info, th_comment *_tc,th_setup_info **_setup,ogg_packet *_op){ char buffer[6]; long val; int packtype; int ret; val=oc_pack_read(_opb,8); packtype=(int)val; /*If we're at a data packet and we have received all three headers, we're done.*/ if(!(packtype&0x80)&&_info->frame_width>0&&_tc->vendor!=NULL&&*_setup!=NULL){ return 0; } /*Check the codec string.*/ oc_unpack_octets(_opb,buffer,6); if(memcmp(buffer,"theora",6)!=0)return TH_ENOTFORMAT; switch(packtype){ /*Codec info header.*/ case 0x80:{ /*This should be the first packet, and we should not already be initialized.*/ if(!_op->b_o_s||_info->frame_width>0)return TH_EBADHEADER; ret=oc_info_unpack(_opb,_info); if(ret<0)th_info_clear(_info); else ret=3; }break; /*Comment header.*/ case 0x81:{ if(_tc==NULL)return TH_EFAULT; /*We shoud have already decoded the info header, and should not yet have decoded the comment header.*/ if(_info->frame_width==0||_tc->vendor!=NULL)return TH_EBADHEADER; ret=oc_comment_unpack(_opb,_tc); if(ret<0)th_comment_clear(_tc); else ret=2; }break; /*Codec setup header.*/ case 0x82:{ oc_setup_info *setup; if(_tc==NULL||_setup==NULL)return TH_EFAULT; /*We should have already decoded the info header and the comment header, and should not yet have decoded the setup header.*/ if(_info->frame_width==0||_tc->vendor==NULL||*_setup!=NULL){ return TH_EBADHEADER; } setup=(oc_setup_info *)_ogg_calloc(1,sizeof(*setup)); if(setup==NULL)return TH_EFAULT; ret=oc_setup_unpack(_opb,setup); if(ret<0){ oc_setup_clear(setup); _ogg_free(setup); } else{ *_setup=setup; ret=1; } }break; default:{ /*We don't know what this header is.*/ return TH_EBADHEADER; }break; } return ret; }
static void BuildHuffmanTree( HUFF_ENTRY **HuffRoot, ogg_uint32_t *HuffCodeArray, unsigned char *HuffCodeLengthArray, ogg_uint32_t HIndex, const ogg_uint32_t *FreqList ){ HUFF_ENTRY *entry_ptr; HUFF_ENTRY *search_ptr; /* First create a sorted linked list representing the frequencies of each token. */ CreateHuffmanList( HuffRoot, HIndex, FreqList ); /* Now build the tree from the list. */ /* While there are at least two items left in the list. */ while ( HuffRoot[HIndex]->Next != NULL ){ /* Create the new node as the parent of the first two in the list. */ entry_ptr = (HUFF_ENTRY *)_ogg_calloc(1,sizeof(*entry_ptr)); entry_ptr->Value = -1; entry_ptr->Frequency = HuffRoot[HIndex]->Frequency + HuffRoot[HIndex]->Next->Frequency ; entry_ptr->ZeroChild = HuffRoot[HIndex]; entry_ptr->OneChild = HuffRoot[HIndex]->Next; /* If there are still more items in the list then insert the new node into the list. */ if (entry_ptr->OneChild->Next != NULL ){ /* Set up the provisional 'new root' */ HuffRoot[HIndex] = entry_ptr->OneChild->Next; HuffRoot[HIndex]->Previous = NULL; /* Now scan through the remaining list to insert the new entry at the appropriate point. */ if ( entry_ptr->Frequency <= HuffRoot[HIndex]->Frequency ){ entry_ptr->Next = HuffRoot[HIndex]; HuffRoot[HIndex]->Previous = entry_ptr; entry_ptr->Previous = NULL; HuffRoot[HIndex] = entry_ptr; }else{ search_ptr = HuffRoot[HIndex]; while ( (search_ptr->Next != NULL) && (search_ptr->Frequency < entry_ptr->Frequency) ){ search_ptr = search_ptr->Next; } if ( search_ptr->Frequency < entry_ptr->Frequency ){ entry_ptr->Next = NULL; entry_ptr->Previous = search_ptr; search_ptr->Next = entry_ptr; }else{ entry_ptr->Next = search_ptr; entry_ptr->Previous = search_ptr->Previous; search_ptr->Previous->Next = entry_ptr; search_ptr->Previous = entry_ptr; } } }else{ /* Build has finished. */ entry_ptr->Next = NULL; entry_ptr->Previous = NULL; HuffRoot[HIndex] = entry_ptr; } /* Delete the Next/Previous properties of the children (PROB NOT NEC). */ entry_ptr->ZeroChild->Next = NULL; entry_ptr->ZeroChild->Previous = NULL; entry_ptr->OneChild->Next = NULL; entry_ptr->OneChild->Previous = NULL; } /* Now build a code array from the tree. */ CreateCodeArray( HuffRoot[HIndex], HuffCodeArray, HuffCodeLengthArray, 0, 0); }
/* all of the real encoding details are here. The modes, books, everything */ static int _vorbis_unpack_books(vorbis_info *vi,oggpack_buffer *opb){ codec_setup_info *ci=(codec_setup_info *)vi->codec_setup; int i; if(!ci)return(OV_EFAULT); /* codebooks */ ci->books=tremoroggpack_read(opb,8)+1; ci->book_param=(codebook *)_ogg_calloc(ci->books,sizeof(*ci->book_param)); for(i=0;i<ci->books;i++) if(vorbis_book_unpack(opb,ci->book_param+i))goto err_out; /* time backend settings, not actually used */ i=tremoroggpack_read(opb,6); for(;i>=0;i--) if(tremoroggpack_read(opb,16)!=0)goto err_out; /* floor backend settings */ ci->floors=tremoroggpack_read(opb,6)+1; ci->floor_param=_ogg_malloc(sizeof(*ci->floor_param)*ci->floors); ci->floor_type=_ogg_malloc(sizeof(*ci->floor_type)*ci->floors); for(i=0;i<ci->floors;i++){ ci->floor_type[i]=tremoroggpack_read(opb,16); if(ci->floor_type[i]<0 || ci->floor_type[i]>=VI_FLOORB)goto err_out; if(ci->floor_type[i]) ci->floor_param[i]=floor1_info_unpack(vi,opb); else ci->floor_param[i]=floor0_info_unpack(vi,opb); if(!ci->floor_param[i])goto err_out; } /* residue backend settings */ ci->residues=tremoroggpack_read(opb,6)+1; ci->residue_param=_ogg_malloc(sizeof(*ci->residue_param)*ci->residues); for(i=0;i<ci->residues;i++) if(res_unpack(ci->residue_param+i,vi,opb))goto err_out; /* map backend settings */ ci->maps=tremoroggpack_read(opb,6)+1; ci->map_param=_ogg_malloc(sizeof(*ci->map_param)*ci->maps); for(i=0;i<ci->maps;i++){ if(tremoroggpack_read(opb,16)!=0)goto err_out; if(mapping_info_unpack(ci->map_param+i,vi,opb))goto err_out; } /* mode settings */ ci->modes=tremoroggpack_read(opb,6)+1; ci->mode_param= (vorbis_info_mode *)_ogg_malloc(ci->modes*sizeof(*ci->mode_param)); for(i=0;i<ci->modes;i++){ ci->mode_param[i].blockflag=tremoroggpack_read(opb,1); if(tremoroggpack_read(opb,16))goto err_out; if(tremoroggpack_read(opb,16))goto err_out; ci->mode_param[i].mapping=tremoroggpack_read(opb,8); if(ci->mode_param[i].mapping>=ci->maps)goto err_out; } if(tremoroggpack_read(opb,1)!=1)goto err_out; /* top level EOP check */ return(0); err_out: vorbis_info_clear(vi); return(OV_EBADHEADER); }
int main(int argc,char *argv[]){ char *basename; codebook *b=NULL; int entries=0; int dim=0; long i,j,target=-1,protect=-1; FILE *out=NULL; int argnum=0; argv++; if(*argv==NULL){ usage(); exit(1); } while(*argv){ if(*argv[0]=='-'){ argv++; }else{ switch (argnum++){ case 0:case 1: { /* yes, this is evil. However, it's very convenient to parse file extentions */ /* input file. What kind? */ char *dot; char *ext=NULL; char *name=strdup(*argv++); dot=strrchr(name,'.'); if(dot) ext=dot+1; else{ ext=""; } /* codebook */ if(!strcmp(ext,"vqh")){ basename=strrchr(name,'/'); if(basename) basename=strdup(basename)+1; else basename=strdup(name); dot=strrchr(basename,'.'); if(dot)*dot='\0'; b=codebook_load(name); dim=b->dim; entries=b->entries; } /* data file; we do actually need to suck it into memory */ /* we're dealing with just one book, so we can de-interleave */ if(!strcmp(ext,"vqd") && !points){ int cols; long lines=0; char *line; float *vec; FILE *in=fopen(name,"r"); if(!in){ fprintf(stderr,"Could not open input file %s\n",name); exit(1); } reset_next_value(); line=setup_line(in); /* count cols before we start reading */ { char *temp=line; while(*temp==' ')temp++; for(cols=0;*temp;cols++){ while(*temp>32)temp++; while(*temp==' ')temp++; } } vec=alloca(cols*sizeof(float)); /* count, then load, to avoid fragmenting the hell out of memory */ while(line){ lines++; for(j=0;j<cols;j++) if(get_line_value(in,vec+j)){ fprintf(stderr,"Too few columns on line %ld in data file\n",lines); exit(1); } if((lines&0xff)==0)spinnit("counting samples...",lines*cols); line=setup_line(in); } pointlist=_ogg_malloc((cols*lines+entries*dim)*sizeof(float)); rewind(in); line=setup_line(in); while(line){ lines--; for(j=0;j<cols;j++) if(get_line_value(in,vec+j)){ fprintf(stderr,"Too few columns on line %ld in data file\n",lines); exit(1); } /* deinterleave, add to heap */ add_vector(b,vec,cols); if((lines&0xff)==0)spinnit("loading samples...",lines*cols); line=setup_line(in); } fclose(in); } } break; case 2: target=atol(*argv++); if(target==0)target=entries; break; case 3: protect=atol(*argv++); break; case 4: { char *buff=alloca(strlen(*argv)+5); sprintf(buff,"%s.vqh",*argv); basename=*argv++; out=fopen(buff,"w"); if(!out){ fprintf(stderr,"unable ot open %s for output",buff); exit(1); } } break; default: usage(); } } } if(!entries || !points || !out)usage(); if(target==-1)usage(); /* add guard points */ for(i=0;i<entries;i++) for(j=0;j<dim;j++) pointlist[points++]=b->valuelist[i*dim+j]; points/=dim; /* set up auxiliary vectors for error tracking */ { encode_aux_nearestmatch *nt=NULL; long pointssofar=0; long *pointindex; long indexedpoints=0; long *entryindex; long *reventry; long *membership=_ogg_malloc(points*sizeof(long)); long *firsthead=_ogg_malloc(entries*sizeof(long)); long *secondary=_ogg_malloc(points*sizeof(long)); long *secondhead=_ogg_malloc(entries*sizeof(long)); long *cellcount=_ogg_calloc(entries,sizeof(long)); long *cellcount2=_ogg_calloc(entries,sizeof(long)); float *cellerror=_ogg_calloc(entries,sizeof(float)); float *cellerrormax=_ogg_calloc(entries,sizeof(float)); long cellsleft=entries; for(i=0;i<points;i++)membership[i]=-1; for(i=0;i<entries;i++)firsthead[i]=-1; for(i=0;i<points;i++)secondary[i]=-1; for(i=0;i<entries;i++)secondhead[i]=-1; for(i=0;i<points;i++){ /* assign vectors to the nearest cell. Also keep track of second nearest for error statistics */ float *ppt=pointlist+i*dim; int firstentry=closest(b,ppt,-1); int secondentry=closest(b,ppt,firstentry); float firstmetric=_dist(dim,b->valuelist+dim*firstentry,ppt); float secondmetric=_dist(dim,b->valuelist+dim*secondentry,ppt); if(!(i&0xff))spinnit("initializing... ",points-i); membership[i]=firsthead[firstentry]; firsthead[firstentry]=i; secondary[i]=secondhead[secondentry]; secondhead[secondentry]=i; if(i<points-entries){ cellerror[firstentry]+=secondmetric-firstmetric; cellerrormax[firstentry]=max(cellerrormax[firstentry], _heuristic(b,ppt,secondentry)); cellcount[firstentry]++; cellcount2[secondentry]++; } } /* which cells are most heavily populated? Protect as many from dispersal as the user has requested */ { long **countindex=_ogg_calloc(entries,sizeof(long *)); for(i=0;i<entries;i++)countindex[i]=cellcount+i; qsort(countindex,entries,sizeof(long *),longsort); for(i=0;i<protect;i++){ int ptr=countindex[i]-cellcount; cellerrormax[ptr]=9e50f; } } { fprintf(stderr,"\r"); for(i=0;i<entries;i++){ /* decompose index */ int entry=i; for(j=0;j<dim;j++){ fprintf(stderr,"%d:",entry%b->c->thresh_tree->quantvals); entry/=b->c->thresh_tree->quantvals; } fprintf(stderr,":%ld/%ld, ",cellcount[i],cellcount2[i]); } fprintf(stderr,"\n"); } /* do the automatic cull request */ while(cellsleft>target){ int bestcell=-1; float besterror=0; float besterror2=0; long head=-1; char spinbuf[80]; sprintf(spinbuf,"cells left to eliminate: %ld : ",cellsleft-target); /* find the cell with lowest removal impact */ for(i=0;i<entries;i++){ if(b->c->lengthlist[i]>0){ if(bestcell==-1 || cellerrormax[i]<=besterror2){ if(bestcell==-1 || cellerrormax[i]<besterror2 || besterror>cellerror[i]){ besterror=cellerror[i]; besterror2=cellerrormax[i]; bestcell=i; } } } } fprintf(stderr,"\reliminating cell %d \n" " dispersal error of %g max/%g total (%ld hits)\n", bestcell,besterror2,besterror,cellcount[bestcell]); /* disperse it. move each point out, adding it (properly) to the second best */ b->c->lengthlist[bestcell]=0; head=firsthead[bestcell]; firsthead[bestcell]=-1; while(head!=-1){ /* head is a point number */ float *ppt=pointlist+head*dim; int firstentry=closest(b,ppt,-1); int secondentry=closest(b,ppt,firstentry); float firstmetric=_dist(dim,b->valuelist+dim*firstentry,ppt); float secondmetric=_dist(dim,b->valuelist+dim*secondentry,ppt); long next=membership[head]; if(head<points-entries){ cellcount[firstentry]++; cellcount[bestcell]--; cellerror[firstentry]+=secondmetric-firstmetric; cellerrormax[firstentry]=max(cellerrormax[firstentry], _heuristic(b,ppt,secondentry)); } membership[head]=firsthead[firstentry]; firsthead[firstentry]=head; head=next; if(cellcount[bestcell]%128==0) spinnit(spinbuf,cellcount[bestcell]+cellcount2[bestcell]); } /* now see that all points that had the dispersed cell as second choice have second choice reassigned */ head=secondhead[bestcell]; secondhead[bestcell]=-1; while(head!=-1){ float *ppt=pointlist+head*dim; /* who are we assigned to now? */ int firstentry=closest(b,ppt,-1); /* what is the new second closest match? */ int secondentry=closest(b,ppt,firstentry); /* old second closest is the cell being disbanded */ float oldsecondmetric=_dist(dim,b->valuelist+dim*bestcell,ppt); /* new second closest error */ float secondmetric=_dist(dim,b->valuelist+dim*secondentry,ppt); long next=secondary[head]; if(head<points-entries){ cellcount2[secondentry]++; cellcount2[bestcell]--; cellerror[firstentry]+=secondmetric-oldsecondmetric; cellerrormax[firstentry]=max(cellerrormax[firstentry], _heuristic(b,ppt,secondentry)); } secondary[head]=secondhead[secondentry]; secondhead[secondentry]=head; head=next; if(cellcount2[bestcell]%128==0) spinnit(spinbuf,cellcount2[bestcell]); } cellsleft--; } /* paring is over. Build decision trees using points that now fall through the thresh matcher. */ /* we don't free membership; we flatten it in order to use in lp_split */ for(i=0;i<entries;i++){ long head=firsthead[i]; spinnit("rearranging membership cache... ",entries-i); while(head!=-1){ long next=membership[head]; membership[head]=i; head=next; } } free(secondhead); free(firsthead); free(cellerror); free(cellerrormax); free(secondary); pointindex=_ogg_malloc(points*sizeof(long)); /* make a point index of fall-through points */ for(i=0;i<points;i++){ int best=_best(b,pointlist+i*dim,1); if(best==-1) pointindex[indexedpoints++]=i; spinnit("finding orphaned points... ",points-i); } /* make an entry index */ entryindex=_ogg_malloc(entries*sizeof(long)); target=0; for(i=0;i<entries;i++){ if(b->c->lengthlist[i]>0) entryindex[target++]=i; } /* make working space for a reverse entry index */ reventry=_ogg_malloc(entries*sizeof(long)); /* do the split */ nt=b->c->nearest_tree= _ogg_calloc(1,sizeof(encode_aux_nearestmatch)); nt->alloc=4096; nt->ptr0=_ogg_malloc(sizeof(long)*nt->alloc); nt->ptr1=_ogg_malloc(sizeof(long)*nt->alloc); nt->p=_ogg_malloc(sizeof(long)*nt->alloc); nt->q=_ogg_malloc(sizeof(long)*nt->alloc); nt->aux=0; fprintf(stderr,"Leaves added: %d \n", lp_split(pointlist,points, b,entryindex,target, pointindex,indexedpoints, membership,reventry, 0,&pointssofar)); free(membership); free(reventry); free(pointindex); /* hack alert. I should just change the damned splitter and codebook writer */ for(i=0;i<nt->aux;i++)nt->p[i]*=dim; for(i=0;i<nt->aux;i++)nt->q[i]*=dim; /* recount hits. Build new lengthlist. reuse entryindex storage */ for(i=0;i<entries;i++)entryindex[i]=1; for(i=0;i<points-entries;i++){ int best=_best(b,pointlist+i*dim,1); float *a=pointlist+i*dim; if(!(i&0xff))spinnit("counting hits...",i); if(best==-1){ fprintf(stderr,"\nINTERNAL ERROR; a point count not be matched to a\n" "codebook entry. The new decision tree is broken.\n"); exit(1); } entryindex[best]++; } for(i=0;i<nt->aux;i++)nt->p[i]/=dim; for(i=0;i<nt->aux;i++)nt->q[i]/=dim; /* the lengthlist builder doesn't actually deal with 0 hit entries. So, we pack the 'sparse' hit list into a dense list, then unpack the lengths after the build */ { int upper=0; long *lengthlist=_ogg_calloc(entries,sizeof(long)); for(i=0;i<entries;i++){ if(b->c->lengthlist[i]>0) entryindex[upper++]=entryindex[i]; else{ if(entryindex[i]>1){ fprintf(stderr,"\nINTERNAL ERROR; _best matched to unused entry\n"); exit(1); } } } /* sanity check */ if(upper != target){ fprintf(stderr,"\nINTERNAL ERROR; packed the wrong number of entries\n"); exit(1); } build_tree_from_lengths(upper,entryindex,lengthlist); upper=0; for(i=0;i<entries;i++){ if(b->c->lengthlist[i]>0) b->c->lengthlist[i]=lengthlist[upper++]; } } } /* we're done. write it out. */ write_codebook(out,basename,b->c); fprintf(stderr,"\r \nDone.\n"); return(0); }
int main(int argc,char *argv[]) { codebook b; static_codebook c; double *quantlist; long *hits; int entries=-1,dim=-1,quantvals=-1,addmul=-1,sequencep=0; FILE *in=NULL; char *line,*name; long i,j; memset(&b,0,sizeof(b)); memset(&c,0,sizeof(c)); if(argv[1]==NULL) { fprintf(stderr,"Need a lattice description file on the command line.\n"); exit(1); } { char *ptr; char *filename=_ogg_calloc(strlen(argv[1])+4,1); strcpy(filename,argv[1]); in=fopen(filename,"r"); if(!in) { fprintf(stderr,"Could not open input file %s\n",filename); exit(1); } ptr=strrchr(filename,'.'); if(ptr) { *ptr='\0'; name=strdup(filename); } else { name=strdup(filename); } } /* read the description */ line=get_line(in); if(sscanf(line,"%d %d %d %d",&quantvals,&dim,&addmul,&sequencep)!=4) { if(sscanf(line,"%d %d %d",&quantvals,&dim,&addmul)!=3) { fprintf(stderr,"Syntax error reading description file (line 1)\n"); exit(1); } } entries=pow(quantvals,dim); c.dim=dim; c.entries=entries; c.lengthlist=_ogg_malloc(entries*sizeof(long)); c.maptype=1; c.q_sequencep=sequencep; c.quantlist=_ogg_calloc(quantvals,sizeof(long)); quantlist=_ogg_malloc(sizeof(double)*c.dim*c.entries); hits=_ogg_malloc(c.entries*sizeof(long)); for(j=0; j<entries; j++)hits[j]=1; for(j=0; j<entries; j++)c.lengthlist[j]=1; reset_next_value(); line=setup_line(in); for(j=0; j<quantvals; j++) { char *temp; if(!line || sscanf(line,"%lf",quantlist+j)!=1) { fprintf(stderr,"Ran out of data on line 2 of description file\n"); exit(1); } temp=strchr(line,','); if(!temp)temp=strchr(line,' '); if(temp)temp++; line=temp; } /* gen a real quant list from the more easily human-grokked input */ { double min=quantlist[0]; double mindel=-1; int fac=1; for(j=1; j<quantvals; j++)if(quantlist[j]<min)min=quantlist[j]; for(j=0; j<quantvals; j++) for(i=j+1; i<quantvals; i++) if(mindel==-1 || fabs(quantlist[j]-quantlist[i])<mindel) mindel=fabs(quantlist[j]-quantlist[i]); j=0; while(j<quantvals) { for(j=0; j<quantvals; j++) { double test=fac*(quantlist[j]-min)/mindel; if( fabs(rint(test)-test)>.00001f) break; } if(fac>100)break; if(j<quantvals)fac++; } mindel/=fac; fprintf(stderr,"min=%g mindel=%g\n",min,mindel); c.q_min=_float32_pack(min); c.q_delta=_float32_pack(mindel); c.q_quant=0; min=_float32_unpack(c.q_min); mindel=_float32_unpack(c.q_delta); for(j=0; j<quantvals; j++) { c.quantlist[j]=rint((quantlist[j]-min)/mindel); if(ilog(c.quantlist[j])>c.q_quant)c.q_quant=ilog(c.quantlist[j]); } } /* build the [default] codeword lengths */ memset(c.lengthlist,0,sizeof(long)*entries); for(i=0; i<entries; i++)hits[i]=1; build_tree_from_lengths(entries,hits,c.lengthlist); /* save the book in C header form */ write_codebook(stdout,name,&c); fprintf(stderr,"\r " "\nDone.\n"); exit(0); }
int main(int argc,char *argv[]) { int eos=0; float nonz=0.f; float acc=0.f; float tot=0.f; float ampmax=-9999,newmax; float local_ampmax[2]; int framesize=2048; float ampmax_att_per_sec=-6.; float *pcm[2],*out[2],*window,*flr[2],*mask[2],*work[2]; signed char *buffer,*buffer2; mdct_lookup m_look; drft_lookup f_look; vorbis_look_psy p_look; vorbis_look_psy_global *pg_look; vorbis_look_floor *floor_look; vorbis_info vi; long i,j,k; int ath=0; int decayp=0; argv++; while(*argv) { if(*argv[0]=='-') { /* option */ if(argv[0][1]=='v') { noisy=0; } } else if(*argv[0]=='+') { /* option */ if(argv[0][1]=='v') { noisy=1; } } else framesize=atoi(argv[0]); argv++; } vi.channels=2; vi.codec_setup=&codec_setup0; pcm[0]=_ogg_malloc(framesize*sizeof(float)); pcm[1]=_ogg_malloc(framesize*sizeof(float)); out[0]=_ogg_calloc(framesize/2,sizeof(float)); out[1]=_ogg_calloc(framesize/2,sizeof(float)); work[0]=_ogg_calloc(framesize,sizeof(float)); work[1]=_ogg_calloc(framesize,sizeof(float)); flr[0]=_ogg_calloc(framesize/2,sizeof(float)); flr[1]=_ogg_calloc(framesize/2,sizeof(float)); buffer=_ogg_malloc(framesize*4); buffer2=buffer+framesize*2; window=_vorbis_window_create(0,framesize,framesize/2,framesize/2); mdct_init(&m_look,framesize); drft_init(&f_look,framesize); _vp_psy_init(&p_look,&_psy_set0,&_psy_set0G,framesize/2,44100); pg_look=_vp_global_look(&vi); floor_look=_floor_P[1]->look(NULL,NULL,&_floor_set0); /* we cheat on the WAV header; we just bypass 44 bytes and never verify that it matches 16bit/stereo/44.1kHz. */ fread(buffer,1,44,stdin); fwrite(buffer,1,44,stdout); memset(buffer,0,framesize*2); analysis("window",0,window,framesize,0,0); fprintf(stderr,"Processing for frame size %d...\n",framesize); while(!eos) { long bytes=fread(buffer2,1,framesize*2,stdin); if(bytes<framesize*2) memset(buffer2+bytes,0,framesize*2-bytes); if(bytes!=0) { int nonzero[2]; /* uninterleave samples */ for(i=0; i<framesize; i++) { pcm[0][i]=((buffer[i*4+1]<<8)| (0x00ff&(int)buffer[i*4]))/32768.f; pcm[1][i]=((buffer[i*4+3]<<8)| (0x00ff&(int)buffer[i*4+2]))/32768.f; } { float secs=framesize/44100.; ampmax+=secs*ampmax_att_per_sec; if(ampmax<-9999)ampmax=-9999; } for(i=0; i<2; i++) { float scale=4.f/framesize; float *fft=work[i]; float *mdct=pcm[i]; float *logmdct=mdct+framesize/2; analysis("pre",frameno+i,pcm[i],framesize,0,0); /* fft and mdct transforms */ for(j=0; j<framesize; j++) fft[j]=pcm[i][j]*=window[j]; drft_forward(&f_look,fft); local_ampmax[i]=-9999.f; fft[0]*=scale; fft[0]=todB(fft); for(j=1; j<framesize-1; j+=2) { float temp=scale*FAST_HYPOT(fft[j],fft[j+1]); temp=fft[(j+1)>>1]=todB(&temp); if(temp>local_ampmax[i])local_ampmax[i]=temp; } if(local_ampmax[i]>ampmax)ampmax=local_ampmax[i]; mdct_forward(&m_look,pcm[i],mdct); for(j=0; j<framesize/2; j++) logmdct[j]=todB(mdct+j); analysis("mdct",frameno+i,logmdct,framesize/2,1,0); analysis("fft",frameno+i,fft,framesize/2,1,0); } for(i=0; i<2; i++) { float amp; float *fft=work[i]; float *logmax=fft; float *mdct=pcm[i]; float *logmdct=mdct+framesize/2; float *mask=fft+framesize/2; /* floor psychoacoustics */ _vp_compute_mask(&p_look, pg_look, i, fft, logmdct, mask, ampmax, local_ampmax[i], framesize/2); analysis("mask",frameno+i,mask,framesize/2,1,0); { vorbis_block vb; vorbis_dsp_state vd; memset(&vd,0,sizeof(vd)); vd.vi=&vi; vb.vd=&vd; vb.pcmend=framesize; /* floor quantization/application */ nonzero[i]=_floor_P[1]->forward(&vb,floor_look, mdct, logmdct, mask, logmax, flr[i]); } _vp_remove_floor(&p_look, pg_look, logmdct, mdct, flr[i], pcm[i], local_ampmax[i]); for(j=0; j<framesize/2; j++) if(fabs(pcm[i][j])>1500) fprintf(stderr,"%ld ",frameno+i); analysis("res",frameno+i,pcm[i],framesize/2,1,0); analysis("codedflr",frameno+i,flr[i],framesize/2,1,1); } /* residue prequantization */ _vp_partition_prequant(&p_look, &vi, pcm, nonzero); for(i=0; i<2; i++) analysis("quant",frameno+i,pcm[i],framesize/2,1,0); /* channel coupling / stereo quantization */ _vp_couple(&p_look, &mapping_info, pcm, nonzero); for(i=0; i<2; i++) analysis("coupled",frameno+i,pcm[i],framesize/2,1,0); /* decoupling */ for(i=mapping_info.coupling_steps-1; i>=0; i--) { float *pcmM=pcm[mapping_info.coupling_mag[i]]; float *pcmA=pcm[mapping_info.coupling_ang[i]]; for(j=0; j<framesize/2; j++) { float mag=pcmM[j]; float ang=pcmA[j]; if(mag>0) if(ang>0) { pcmM[j]=mag; pcmA[j]=mag-ang; } else { pcmA[j]=mag; pcmM[j]=mag+ang; } else if(ang>0) { pcmM[j]=mag; pcmA[j]=mag+ang; } else { pcmA[j]=mag; pcmM[j]=mag-ang; } } } for(i=0; i<2; i++) analysis("decoupled",frameno+i,pcm[i],framesize/2,1,0); for(i=0; i<2; i++) { float amp; for(j=0; j<framesize/2; j++) pcm[i][j]*=flr[i][j]; analysis("final",frameno+i,pcm[i],framesize/2,1,1); /* take it back to time */ mdct_backward(&m_look,pcm[i],pcm[i]); for(j=0; j<framesize/2; j++) out[i][j]+=pcm[i][j]*window[j]; analysis("out",frameno+i,out[i],framesize/2,0,0); } /* write data. Use the part of buffer we're about to shift out */ for(i=0; i<2; i++) { char *ptr=buffer+i*2; float *mono=out[i]; int flag=0; for(j=0; j<framesize/2; j++) { int val=mono[j]*32767.; /* might as well guard against clipping */ if(val>32767) { if(!flag)fprintf(stderr,"clipping in frame %ld ",frameno+i); flag=1; val=32767; } if(val<-32768) { if(!flag)fprintf(stderr,"clipping in frame %ld ",frameno+i); flag=1; val=-32768; } ptr[0]=val&0xff; ptr[1]=(val>>8)&0xff; ptr+=4; } } fprintf(stderr,"*"); fwrite(buffer,1,framesize*2,stdout); memmove(buffer,buffer2,framesize*2); for(i=0; i<2; i++) { for(j=0,k=framesize/2; j<framesize/2; j++,k++) out[i][j]=pcm[i][k]*window[k]; } frameno+=2; } else
/* all of the real encoding details are here. The modes, books, everything */ static int _vorbis_unpack_books(vorbis_info *vi,oggpack_buffer *opb){ codec_setup_info *ci=(codec_setup_info *)vi->codec_setup; int i; if(!ci)return(OV_EFAULT); /* codebooks */ ci->books=oggpack_read(opb,8)+1; /*ci->book_param=_ogg_calloc(ci->books,sizeof(*ci->book_param));*/ for(i=0;i<ci->books;i++){ ci->book_param[i]=(static_codebook *)_ogg_calloc(1,sizeof(*ci->book_param[i])); if(vorbis_staticbook_unpack(opb,ci->book_param[i]))goto err_out; } /* time backend settings */ ci->times=oggpack_read(opb,6)+1; /*ci->time_type=_ogg_malloc(ci->times*sizeof(*ci->time_type));*/ /*ci->time_param=_ogg_calloc(ci->times,sizeof(void *));*/ for(i=0;i<ci->times;i++){ ci->time_type[i]=oggpack_read(opb,16); if(ci->time_type[i]<0 || ci->time_type[i]>=VI_TIMEB)goto err_out; /* ci->time_param[i]=_time_P[ci->time_type[i]]->unpack(vi,opb); Vorbis I has no time backend */ /*if(!ci->time_param[i])goto err_out;*/ } /* floor backend settings */ ci->floors=oggpack_read(opb,6)+1; /*ci->floor_type=_ogg_malloc(ci->floors*sizeof(*ci->floor_type));*/ /*ci->floor_param=_ogg_calloc(ci->floors,sizeof(void *));*/ for(i=0;i<ci->floors;i++){ ci->floor_type[i]=oggpack_read(opb,16); if(ci->floor_type[i]<0 || ci->floor_type[i]>=VI_FLOORB)goto err_out; ci->floor_param[i]=_floor_P[ci->floor_type[i]]->unpack(vi,opb); if(!ci->floor_param[i])goto err_out; } /* residue backend settings */ ci->residues=oggpack_read(opb,6)+1; /*ci->residue_type=_ogg_malloc(ci->residues*sizeof(*ci->residue_type));*/ /*ci->residue_param=_ogg_calloc(ci->residues,sizeof(void *));*/ for(i=0;i<ci->residues;i++){ ci->residue_type[i]=oggpack_read(opb,16); if(ci->residue_type[i]<0 || ci->residue_type[i]>=VI_RESB)goto err_out; ci->residue_param[i]=_residue_P[ci->residue_type[i]]->unpack(vi,opb); if(!ci->residue_param[i])goto err_out; } /* map backend settings */ ci->maps=oggpack_read(opb,6)+1; /*ci->map_type=_ogg_malloc(ci->maps*sizeof(*ci->map_type));*/ /*ci->map_param=_ogg_calloc(ci->maps,sizeof(void *));*/ for(i=0;i<ci->maps;i++){ ci->map_type[i]=oggpack_read(opb,16); if(ci->map_type[i]<0 || ci->map_type[i]>=VI_MAPB)goto err_out; ci->map_param[i]=_mapping_P[ci->map_type[i]]->unpack(vi,opb); if(!ci->map_param[i])goto err_out; } /* mode settings */ ci->modes=oggpack_read(opb,6)+1; /*vi->mode_param=_ogg_calloc(vi->modes,sizeof(void *));*/ for(i=0;i<ci->modes;i++){ ci->mode_param[i]=(vorbis_info_mode *)_ogg_calloc(1,sizeof(*ci->mode_param[i])); ci->mode_param[i]->blockflag=oggpack_read(opb,1); ci->mode_param[i]->windowtype=oggpack_read(opb,16); ci->mode_param[i]->transformtype=oggpack_read(opb,16); ci->mode_param[i]->mapping=oggpack_read(opb,8); if(ci->mode_param[i]->windowtype>=VI_WINDOWB)goto err_out; if(ci->mode_param[i]->transformtype>=VI_WINDOWB)goto err_out; if(ci->mode_param[i]->mapping>=ci->maps)goto err_out; } if(oggpack_read(opb,1)!=1)goto err_out; /* top level EOP check */ return(0); err_out: vorbis_info_clear(vi); return(OV_EBADHEADER); }
static vorbis_look_floor *floor1_look(vorbis_dsp_state *vd, vorbis_info_floor *in){ int *sortpointer[VIF_POSIT+2]; vorbis_info_floor1 *info=(vorbis_info_floor1 *)in; vorbis_look_floor1 *look=_ogg_calloc(1,sizeof(*look)); int i,j,n=0; look->vi=info; look->n=info->postlist[1]; /* we drop each position value in-between already decoded values, and use linear interpolation to predict each new value past the edges. The positions are read in the order of the position list... we precompute the bounding positions in the lookup. Of course, the neighbors can change (if a position is declined), but this is an initial mapping */ for(i=0;i<info->partitions;i++)n+=info->class_dim[info->partitionclass[i]]; n+=2; look->posts=n; /* also store a sorted position index */ for(i=0;i<n;i++)sortpointer[i]=info->postlist+i; qsort(sortpointer,n,sizeof(*sortpointer),icomp); /* points from sort order back to range number */ for(i=0;i<n;i++)look->forward_index[i]=sortpointer[i]-info->postlist; /* points from range order to sorted position */ for(i=0;i<n;i++)look->reverse_index[look->forward_index[i]]=i; /* we actually need the post values too */ for(i=0;i<n;i++)look->sorted_index[i]=info->postlist[look->forward_index[i]]; /* quantize values to multiplier spec */ switch(info->mult){ case 1: /* 1024 -> 256 */ look->quant_q=256; break; case 2: /* 1024 -> 128 */ look->quant_q=128; break; case 3: /* 1024 -> 86 */ look->quant_q=86; break; case 4: /* 1024 -> 64 */ look->quant_q=64; break; } /* discover our neighbors for decode where we don't use fit flags (that would push the neighbors outward) */ for(i=0;i<n-2;i++){ int lo=0; int hi=1; int lx=0; int hx=look->n; int currentx=info->postlist[i+2]; for(j=0;j<i+2;j++){ int x=info->postlist[j]; if(x>lx && x<currentx){ lo=j; lx=x; } if(x<hx && x>currentx){ hi=j; hx=x; } } look->loneighbor[i]=lo; look->hineighbor[i]=hi; } return(look); }
codebook *codebook_load(char *filename){ codebook *b=_ogg_calloc(1,sizeof(codebook)); static_codebook *c=(static_codebook *)(b->c=_ogg_calloc(1,sizeof(static_codebook))); encode_aux_nearestmatch *a=NULL; encode_aux_threshmatch *t=NULL; encode_aux_pigeonhole *p=NULL; int quant_to_read=0; FILE *in=fopen(filename,"r"); char *line; long i; if(in==NULL){ fprintf(stderr,"Couldn't open codebook %s\n",filename); exit(1); } /* find the codebook struct */ find_seek_to(in,"static static_codebook "); /* get the major important values */ line=get_line(in); if(sscanf(line,"%ld, %ld,", &(c->dim),&(c->entries))!=2){ fprintf(stderr,"1: syntax in %s in line:\t %s",filename,line); exit(1); } line=get_line(in); line=get_line(in); if(sscanf(line,"%d, %ld, %ld, %d, %d,", &(c->maptype),&(c->q_min),&(c->q_delta),&(c->q_quant), &(c->q_sequencep))!=5){ fprintf(stderr,"1: syntax in %s in line:\t %s",filename,line); exit(1); } /* find the auxiliary encode struct[s] (if any) */ if(find_seek_to(in,"static encode_aux_nearestmatch _vq_aux")){ /* how big? */ c->nearest_tree=a=_ogg_calloc(1,sizeof(encode_aux_nearestmatch)); line=get_line(in); line=get_line(in); line=get_line(in); line=get_line(in); line=get_line(in); if(sscanf(line,"%ld, %ld",&(a->aux),&(a->alloc))!=2){ fprintf(stderr,"2: syntax in %s in line:\t %s",filename,line); exit(1); } /* load ptr0 */ find_seek_to(in,"static long _vq_ptr0"); reset_next_value(); a->ptr0=_ogg_malloc(sizeof(long)*a->aux); for(i=0;i<a->aux;i++) if(get_next_ivalue(in,a->ptr0+i)){ fprintf(stderr,"out of data while reading codebook %s\n",filename); exit(1); } /* load ptr1 */ find_seek_to(in,"static long _vq_ptr1"); reset_next_value(); a->ptr1=_ogg_malloc(sizeof(long)*a->aux); for(i=0;i<a->aux;i++) if(get_next_ivalue(in,a->ptr1+i)){ fprintf(stderr,"out of data while reading codebook %s\n",filename); exit(1); } /* load p */ find_seek_to(in,"static long _vq_p_"); reset_next_value(); a->p=_ogg_malloc(sizeof(long)*a->aux); for(i=0;i<a->aux;i++) if(get_next_ivalue(in,a->p+i)){ fprintf(stderr,"out of data while reading codebook %s\n",filename); exit(1); } /* load q */ find_seek_to(in,"static long _vq_q_"); reset_next_value(); a->q=_ogg_malloc(sizeof(long)*a->aux); for(i=0;i<a->aux;i++) if(get_next_ivalue(in,a->q+i)){ fprintf(stderr,"out of data while reading codebook %s\n",filename); exit(1); } } if(find_seek_to(in,"static encode_aux_threshmatch _vq_aux")){ /* how big? */ c->thresh_tree=t=_ogg_calloc(1,sizeof(encode_aux_threshmatch)); line=get_line(in); line=get_line(in); line=get_line(in); if(sscanf(line,"%d",&(t->quantvals))!=1){ fprintf(stderr,"3: syntax in %s in line:\t %s",filename,line); exit(1); } line=get_line(in); if(sscanf(line,"%d",&(t->threshvals))!=1){ fprintf(stderr,"4: syntax in %s in line:\t %s",filename,line); exit(1); } /* load quantthresh */ find_seek_to(in,"static float _vq_quantthresh_"); reset_next_value(); t->quantthresh=_ogg_malloc(sizeof(float)*t->threshvals); for(i=0;i<t->threshvals-1;i++) if(get_next_value(in,t->quantthresh+i)){ fprintf(stderr,"out of data 1 while reading codebook %s\n",filename); exit(1); } /* load quantmap */ find_seek_to(in,"static long _vq_quantmap_"); reset_next_value(); t->quantmap=_ogg_malloc(sizeof(long)*t->threshvals); for(i=0;i<t->threshvals;i++) if(get_next_ivalue(in,t->quantmap+i)){ fprintf(stderr,"out of data 2 while reading codebook %s\n",filename); exit(1); } } if(find_seek_to(in,"static encode_aux_pigeonhole _vq_aux")){ int pigeons=1,i; /* how big? */ c->pigeon_tree=p=_ogg_calloc(1,sizeof(encode_aux_pigeonhole)); line=get_line(in); if(sscanf(line,"%f, %f, %d, %d",&(p->min),&(p->del), &(p->mapentries),&(p->quantvals))!=4){ fprintf(stderr,"5: syntax in %s in line:\t %s",filename,line); exit(1); } line=get_line(in); line=get_line(in); if(sscanf(line,"%ld",&(p->fittotal))!=1){ fprintf(stderr,"6: syntax in %s in line:\t %s",filename,line); exit(1); } /* load pigeonmap */ find_seek_to(in,"static long _vq_pigeonmap_"); reset_next_value(); p->pigeonmap=_ogg_malloc(sizeof(long)*p->mapentries); for(i=0;i<p->mapentries;i++) if(get_next_ivalue(in,p->pigeonmap+i)){ fprintf(stderr,"out of data (pigeonmap) while reading codebook %s\n",filename); exit(1); } /* load fitlist */ find_seek_to(in,"static long _vq_fitlist_"); reset_next_value(); p->fitlist=_ogg_malloc(sizeof(long)*p->fittotal); for(i=0;i<p->fittotal;i++) if(get_next_ivalue(in,p->fitlist+i)){ fprintf(stderr,"out of data (fitlist) while reading codebook %s\n",filename); exit(1); } /* load fitmap */ find_seek_to(in,"static long _vq_fitmap_"); reset_next_value(); for(i=0;i<c->dim;i++)pigeons*=p->quantvals; p->fitmap=_ogg_malloc(sizeof(long)*pigeons); for(i=0;i<pigeons;i++) if(get_next_ivalue(in,p->fitmap+i)){ fprintf(stderr,"out of data (fitmap) while reading codebook %s\n",filename); exit(1); } /* load fitlength */ find_seek_to(in,"static long _vq_fitlength_"); reset_next_value(); p->fitlength=_ogg_malloc(sizeof(long)*pigeons); for(i=0;i<pigeons;i++) if(get_next_ivalue(in,p->fitlength+i)){ fprintf(stderr,"out of data (fitlength) while reading codebook %s\n",filename); exit(1); } } switch(c->maptype){ case 0: quant_to_read=0; break; case 1: quant_to_read=_book_maptype1_quantvals(c); break; case 2: quant_to_read=c->entries*c->dim; break; } /* load the quantized entries */ find_seek_to(in,"static long _vq_quantlist_"); reset_next_value(); c->quantlist=_ogg_malloc(sizeof(long)*quant_to_read); for(i=0;i<quant_to_read;i++) if(get_next_ivalue(in,c->quantlist+i)){ fprintf(stderr,"out of data while reading codebook %s\n",filename); exit(1); } /* load the lengthlist */ find_seek_to(in,"_lengthlist"); reset_next_value(); c->lengthlist=_ogg_malloc(sizeof(long)*c->entries); for(i=0;i<c->entries;i++) if(get_next_ivalue(in,c->lengthlist+i)){ fprintf(stderr,"out of data while reading codebook %s\n",filename); exit(1); } /* got it all */ fclose(in); vorbis_book_init_encode(b,c); return(b); }
int lp_split(float *pointlist,long totalpoints, codebook *b, long *entryindex,long entries, long *pointindex,long points, long *membership,long *reventry, long depth, long *pointsofar){ encode_aux_nearestmatch *t=b->c->nearest_tree; /* The encoder, regardless of book, will be using a straight euclidian distance-to-point metric to determine closest point. Thus we split the cells using the same (we've already trained the codebook set spacing and distribution using special metrics and even a midpoint division won't disturb the basic properties) */ int dim=b->dim; float *entrylist=b->valuelist; long ret; long *entryA=_ogg_calloc(entries,sizeof(long)); long *entryB=_ogg_calloc(entries,sizeof(long)); long entriesA=0; long entriesB=0; long entriesC=0; long pointsA=0; long i,j,k; long besti=-1; long bestj=-1; char spinbuf[80]; sprintf(spinbuf,"splitting [%ld left]... ",totalpoints-*pointsofar); /* one reverse index needed */ for(i=0;i<b->entries;i++)reventry[i]=-1; for(i=0;i<entries;i++)reventry[entryindex[i]]=i; /* We need to find the dividing hyperplane. find the median of each axis as the centerpoint and the normal facing farthest point */ /* more than one way to do this part. For small sets, we can brute force it. */ if(entries<8 || (float)points*entries*entries<16.f*1024*1024){ /* try every pair possibility */ float best=0; float this; for(i=0;i<entries-1;i++){ for(j=i+1;j<entries;j++){ spinnit(spinbuf,entries-i); vqsp_count(b->valuelist,pointlist,dim, membership,reventry, entryindex,entries, pointindex,points,0, entryA,entryB, entryindex[i],entryindex[j], &entriesA,&entriesB,&entriesC); this=(entriesA-entriesC)*(entriesB-entriesC); /* when choosing best, we also want some form of stability to make sure more branches are pared later; secondary weighting isn;t needed as the entry lists are in ascending order, and we always try p/q in the same sequence */ if( (besti==-1) || (this>best) ){ best=this; besti=entryindex[i]; bestj=entryindex[j]; } } } }else{
static vorbis_look_residue *res012_look(vorbis_dsp_state *vd,vorbis_info_residue *vr) { vorbis_info_residue0 *info=(vorbis_info_residue0 *)vr; vorbis_info *vi=vd->vi; codec_setup_info *ci=vi->codec_setup; int j,k,acc=0,partwordnum; int dim; int maxstage=0; // if there are submaps we cannot use 'setpart' (vorbis_book_decodexx_set) // (but it seems the existent Vorbis versions have no submaps (1 submap only)) for(j=0;j<ci->maps;j++){ if(ci->map_type[j]==0){ vorbis_info_mapping0 *vim0=ci->map_param[j]; if(vim0->submaps>1){ info->setpart=info->decodepart; break; } } } info->phrasebook=ci->fullbooks+info->groupbook; dim=info->phrasebook->dim; for(j=0;j<info->partitions;j++){ int stages=ilog(info->secondstages[j]); if(stages>maxstage) maxstage=stages; } // we allocate a little more memory, but this is the decoding order (->faster decoding (?)) info->partbooks=_ogg_calloc(maxstage,sizeof(*info->partbooks)); for(k=0;k<maxstage;k++) info->partbooks[k]=_ogg_calloc(info->partitions,sizeof(*info->partbooks[k])); for(j=0;j<info->partitions;j++){ int stages=ilog(info->secondstages[j]); for(k=0;k<stages;k++) if(info->secondstages[j]&(1<<k)) info->partbooks[k][j]=ci->fullbooks+info->booklist[acc++]; } info->look_partvals=rint(pow((float)info->partitions,(float)dim)); info->stages=maxstage; info->decodemap=_ogg_malloc(info->look_partvals*sizeof(*info->decodemap)); for(j=0;j<info->look_partvals;j++){ long val=j; long mult=info->look_partvals/info->partitions; info->decodemap[j]=_ogg_malloc(dim*sizeof(*info->decodemap[j])); for(k=0;k<dim;k++){ long deco=val/mult; val-=deco*mult; mult/=info->partitions; info->decodemap[j][k]=deco; } } info->dim=dim; info->info_partvals=info->len/info->samples_per_partition; partwordnum=(info->info_partvals+info->dim-1)/info->dim; info->partwordp=_ogg_malloc(vi->channels*partwordnum*sizeof(*(info->partwordp))); return((vorbis_look_residue *)info); }
int main(int argc, char *argv[]){ char *base; char *infile; int i,j,k,begin,n,subn,guard=1; FILE *file; int maxval=0; int loval=0; if(argc<3)usage(); if(argc==4)guard=0; infile=strdup(argv[1]); base=strdup(infile); if(strrchr(base,'.')) strrchr(base,'.')[0]='\0'; { char *pos=strchr(argv[2],','); char *dpos=strchr(argv[2],'-'); if(dpos){ loval=atoi(argv[2]); maxval=atoi(dpos+1); subn=1; begin=0; }else{ begin=atoi(argv[2]); if(!pos) usage(); else n=atoi(pos+1); pos=strchr(pos+1,','); if(!pos) usage(); else subn=atoi(pos+1); if(n/subn*subn != n){ fprintf(stderr,"n must be divisible by group\n"); exit(1); } } } /* scan the file for maximum value */ file=fopen(infile,"r"); if(!file){ fprintf(stderr,"Could not open file %s\n",infile); if(!maxval) exit(1); else fprintf(stderr," making untrained books.\n"); } if(!maxval){ i=0; while(1){ long v; if(get_next_ivalue(file,&v))break; if(v>maxval)maxval=v; if(!(i++&0xff))spinnit("loading... ",i); } rewind(file); maxval++; } { long vals=pow(maxval,subn); long *hist=_ogg_calloc(vals,sizeof(long)); long *lengths=_ogg_calloc(vals,sizeof(long)); for(j=loval;j<vals;j++)hist[j]=guard; if(file){ reset_next_value(); i/=subn; while(!feof(file)){ long val=getval(file,begin,n,subn,maxval); if(val==-1 || val>=vals)break; hist[val]++; if(!(i--&0xff))spinnit("loading... ",i*subn); } fclose(file); } /* we have the probabilities, build the tree */ fprintf(stderr,"Building tree for %ld entries\n",vals); build_tree_from_lengths0(vals,hist,lengths); /* save the book */ { char *buffer=alloca(strlen(base)+5); strcpy(buffer,base); strcat(buffer,".vqh"); file=fopen(buffer,"w"); if(!file){ fprintf(stderr,"Could not open file %s\n",buffer); exit(1); } } /* first, the static vectors, then the book structure to tie it together. */ /* lengthlist */ fprintf(file,"static long _huff_lengthlist_%s[] = {\n",base); for(j=0;j<vals;){ fprintf(file,"\t"); for(k=0;k<16 && j<vals;k++,j++) fprintf(file,"%2ld,",lengths[j]); fprintf(file,"\n"); } fprintf(file,"};\n\n"); /* the toplevel book */ fprintf(file,"static static_codebook _huff_book_%s = {\n",base); fprintf(file,"\t%d, %ld,\n",subn,vals); fprintf(file,"\t_huff_lengthlist_%s,\n",base); fprintf(file,"\t0, 0, 0, 0, 0,\n"); fprintf(file,"\tNULL,\n"); fprintf(file,"\tNULL,\n"); fprintf(file,"\tNULL,\n"); fprintf(file,"\tNULL,\n"); fprintf(file,"\t0\n};\n\n"); fclose(file); fprintf(stderr,"Done. \n\n"); } exit(0); }
static int _vds_shared_init(vorbis_dsp_state *v,vorbis_info *vi) { int i; codec_setup_info *ci=vi->codec_setup; backend_lookup_state *b=NULL; _ogg_memset(v,0,sizeof(*v)); b=v->backend_state=_ogg_calloc(1,sizeof(*b)); if(!b) return -1; v->vi=vi; b->modebits=ilog2(ci->modes); b->transform[0]=oggdec_mdct_init(ci->blocksizes[0]); b->transform[1]=oggdec_mdct_init(ci->blocksizes[1]); if(!b->transform[0] || !b->transform[1]) return -1; b->window[0]=_vorbis_window_get(ci->blocksizes[0]/2); b->window[1]=_vorbis_window_get(ci->blocksizes[1]/2); if(!b->window[0] || !b->window[1]) return -1; if(!ci->fullbooks){ ci->fullbooks=_ogg_calloc(ci->books,sizeof(*ci->fullbooks)); for(i=0;i<ci->books;i++){ if(vorbis_book_init_decode(ci->fullbooks+i,ci->book_param[i])<0) return -1; } for(i=0;i<ci->books;i++){ vorbis_staticbook_destroy(ci->book_param[i]); ci->book_param[i]=NULL; } } v->pcm_storage=ci->blocksizes[1]; v->pcm=_ogg_malloc(vi->channels*sizeof(*v->pcm)); v->pcmret=_ogg_malloc(vi->channels*sizeof(*v->pcmret)); if(!v->pcm || !v->pcmret) return -1; for(i=0;i<vi->channels;i++){ v->pcm[i]=_ogg_malloc(v->pcm_storage*sizeof(*v->pcm[i])); if(!v->pcm[i]) return -1; } b->flr=_ogg_calloc(ci->floors,sizeof(*b->flr)); b->residue=_ogg_calloc(ci->residues,sizeof(*b->residue)); if(!b->flr || !b->residue) return -1; for(i=0;i<ci->floors;i++) b->flr[i]=_floor_P[ci->floor_type[i]]->look(v,ci->floor_param[i]); for(i=0;i<ci->residues;i++) b->residue[i]=_residue_P[ci->residue_type[i]]->look(v,ci->residue_param[i]); return(0); }
void drft_init(drft_lookup *l,int n) { l->n=n; l->trigcache=_ogg_calloc(3*n,sizeof(*l->trigcache)); l->splitcache=_ogg_calloc(32,sizeof(*l->splitcache)); fdrffti(n, l->trigcache, l->splitcache); }
int main(int argc,char *argv[]){ codebook *b; static_codebook *c; int entries=-1,dim=-1; float min,del; char *name; long i,j; float *suggestions; int suggcount=0; if(argv[1]==NULL){ fprintf(stderr,"Need a lattice book on the command line.\n"); exit(1); } { char *ptr; char *filename=strdup(argv[1]); b=codebook_load(filename); c=(static_codebook *)(b->c); ptr=strrchr(filename,'.'); if(ptr){ *ptr='\0'; name=strdup(filename); }else{ name=strdup(filename); } } if(c->maptype!=1){ fprintf(stderr,"Provided book is not a latticebook.\n"); exit(1); } entries=b->entries; dim=b->dim; min=_float32_unpack(c->q_min); del=_float32_unpack(c->q_delta); /* Do we want to gen a threshold hint? */ if(c->q_sequencep==0){ /* yes. Discard any preexisting threshhold hint */ long quantvals=_book_maptype1_quantvals(c); long **quantsort=alloca(quantvals*sizeof(long *)); encode_aux_threshmatch *t=_ogg_calloc(1,sizeof(encode_aux_threshmatch)); c->thresh_tree=t; fprintf(stderr,"Adding threshold hint to %s...\n",name); /* partial/complete suggestions */ if(argv[2]){ char *ptr=strdup(argv[2]); suggestions=alloca(sizeof(float)*quantvals); for(suggcount=0;ptr && suggcount<quantvals;suggcount++){ char *ptr2=strchr(ptr,','); if(ptr2)*ptr2++='\0'; suggestions[suggcount]=atof(ptr); ptr=ptr2; } } /* simplest possible threshold hint only */ t->quantthresh=_ogg_calloc(quantvals-1,sizeof(float)); t->quantmap=_ogg_calloc(quantvals,sizeof(int)); t->threshvals=quantvals; t->quantvals=quantvals; /* the quantvals may not be in order; sort em first */ for(i=0;i<quantvals;i++)quantsort[i]=c->quantlist+i; qsort(quantsort,quantvals,sizeof(long *),longsort); /* ok, gen the map and thresholds */ for(i=0;i<quantvals;i++)t->quantmap[i]=quantsort[i]-c->quantlist; for(i=0;i<quantvals-1;i++){ float v1=*(quantsort[i])*del+min; float v2=*(quantsort[i+1])*del+min; for(j=0;j<suggcount;j++) if(v1<suggestions[j] && suggestions[j]<v2){ t->quantthresh[i]=suggestions[j]; break; } if(j==suggcount){ t->quantthresh[i]=(v1+v2)*.5; } } } /* Do we want to gen a pigeonhole hint? */ #if 0 for(i=0;i<entries;i++)if(c->lengthlist[i]==0)break; if(c->q_sequencep || i<entries){ long **tempstack; long *tempcount; long *temptrack; float *tempmin; float *tempmax; long totalstack=0; long pigeons; long subpigeons; long quantvals=_book_maptype1_quantvals(c); int changep=1,factor; encode_aux_pigeonhole *p=_ogg_calloc(1,sizeof(encode_aux_pigeonhole)); c->pigeon_tree=p; fprintf(stderr,"Adding pigeonhole hint to %s...\n",name); /* the idea is that we quantize uniformly, even in a nonuniform lattice, so that quantization of one scalar has a predictable result on the next sequential scalar in a greedy matching algorithm. We generate a lookup based on the quantization of the vector (pigeonmap groups quantized entries together) and list the entries that could possible be the best fit for any given member of that pigeonhole. The encode process then has a much smaller list to brute force */ /* find our pigeonhole-specific quantization values, fill in the quant value->pigeonhole map */ factor=3; p->del=del; p->min=min; p->quantvals=quantvals; { int max=0; for(i=0;i<quantvals;i++)if(max<c->quantlist[i])max=c->quantlist[i]; p->mapentries=max; } p->pigeonmap=_ogg_malloc(p->mapentries*sizeof(long)); p->quantvals=(quantvals+factor-1)/factor; /* pigeonhole roughly on the boundaries of the quantvals; the exact pigeonhole grouping is an optimization issue, not a correctness issue */ for(i=0;i<p->mapentries;i++){ float thisval=del*i+min; /* middle of the quant zone */ int quant=0; float err=fabs(c->quantlist[0]*del+min-thisval); for(j=1;j<quantvals;j++){ float thiserr=fabs(c->quantlist[j]*del+min-thisval); if(thiserr<err){ quant=j/factor; err=thiserr; } } p->pigeonmap[i]=quant; } /* pigeonmap complete. Now do the grungy business of finding the entries that could possibly be the best fit for a value appearing in the pigeonhole. The trick that allows the below to work is the uniform quantization; even though the scalars may be 'sequential' (each a delta from the last), the uniform quantization means that the error variance is *not* dependant. Given a pigeonhole and an entry, we can find the minimum and maximum possible errors (relative to the entry) for any point that could appear in the pigeonhole */ /* must iterate over both pigeonholes and entries */ /* temporarily (in order to avoid thinking hard), we grow each pigeonhole seperately, the build a stack of 'em later */ pigeons=1; subpigeons=1; for(i=0;i<dim;i++)subpigeons*=p->mapentries; for(i=0;i<dim;i++)pigeons*=p->quantvals; temptrack=_ogg_calloc(dim,sizeof(long)); tempmin=_ogg_calloc(dim,sizeof(float)); tempmax=_ogg_calloc(dim,sizeof(float)); tempstack=_ogg_calloc(pigeons,sizeof(long *)); tempcount=_ogg_calloc(pigeons,sizeof(long)); while(1){ float errorpost=-1; char buffer[80]; /* map our current pigeonhole to a 'big pigeonhole' so we know what list we're after */ int entry=0; for(i=dim-1;i>=0;i--)entry=entry*p->quantvals+p->pigeonmap[temptrack[i]]; setvals(dim,p,temptrack,tempmin,tempmax,c->q_sequencep); sprintf(buffer,"Building pigeonhole search list [%ld]...",totalstack); /* Search all entries to find the one with the minimum possible maximum error. Record that error */ for(i=0;i<entries;i++){ if(c->lengthlist[i]>0){ float this=maxerror(dim,b->valuelist+i*dim,p, temptrack,tempmin,tempmax); if(errorpost==-1 || this<errorpost)errorpost=this; spinnit(buffer,subpigeons); } } /* Our search list will contain all entries with a minimum possible error <= our errorpost */ for(i=0;i<entries;i++) if(c->lengthlist[i]>0){ spinnit(buffer,subpigeons); if(minerror(dim,b->valuelist+i*dim,p, temptrack,tempmin,tempmax)<errorpost) totalstack+=addtosearch(entry,tempstack,tempcount,i); } for(i=0;i<dim;i++){ temptrack[i]++; if(temptrack[i]<p->mapentries)break; temptrack[i]=0; } if(i==dim)break; subpigeons--; }
/* all of the real encoding details are here. The modes, books, everything */ static int _vorbis_unpack_books(vorbis_info *vi,oggpack_buffer *opb){ codec_setup_info *ci=vi->codec_setup; int i; if(!ci)return(OV_EFAULT); /* codebooks */ ci->books=oggpack_read(opb,8)+1; if(ci->books<=0)goto err_out; for(i=0;i<ci->books;i++){ ci->book_param[i]=_ogg_calloc(1,sizeof(*ci->book_param[i])); if(vorbis_staticbook_unpack(opb,ci->book_param[i]))goto err_out; } /* time backend settings; hooks are unused */ { int times=oggpack_read(opb,6)+1; if(times<=0)goto err_out; for(i=0;i<times;i++){ int test=oggpack_read(opb,16); if(test<0 || test>=VI_TIMEB)goto err_out; } } /* floor backend settings */ ci->floors=oggpack_read(opb,6)+1; if(ci->floors<=0)goto err_out; for(i=0;i<ci->floors;i++){ ci->floor_type[i]=oggpack_read(opb,16); if(ci->floor_type[i]<0 || ci->floor_type[i]>=VI_FLOORB)goto err_out; ci->floor_param[i]=_floor_P[ci->floor_type[i]]->unpack(vi,opb); if(!ci->floor_param[i])goto err_out; } /* residue backend settings */ ci->residues=oggpack_read(opb,6)+1; if(ci->residues<=0)goto err_out; for(i=0;i<ci->residues;i++){ ci->residue_type[i]=oggpack_read(opb,16); if(ci->residue_type[i]<0 || ci->residue_type[i]>=VI_RESB)goto err_out; ci->residue_param[i]=_residue_P[ci->residue_type[i]]->unpack(vi,opb); if(!ci->residue_param[i])goto err_out; } /* map backend settings */ ci->maps=oggpack_read(opb,6)+1; if(ci->maps<=0)goto err_out; for(i=0;i<ci->maps;i++){ ci->map_type[i]=oggpack_read(opb,16); if(ci->map_type[i]<0 || ci->map_type[i]>=VI_MAPB)goto err_out; ci->map_param[i]=_mapping_P[ci->map_type[i]]->unpack(vi,opb); if(!ci->map_param[i])goto err_out; } /* mode settings */ ci->modes=oggpack_read(opb,6)+1; if(ci->modes<=0)goto err_out; for(i=0;i<ci->modes;i++){ ci->mode_param[i]=_ogg_calloc(1,sizeof(*ci->mode_param[i])); ci->mode_param[i]->blockflag=oggpack_read(opb,1); ci->mode_param[i]->windowtype=oggpack_read(opb,16); ci->mode_param[i]->transformtype=oggpack_read(opb,16); ci->mode_param[i]->mapping=oggpack_read(opb,8); if(ci->mode_param[i]->windowtype>=VI_WINDOWB)goto err_out; if(ci->mode_param[i]->transformtype>=VI_WINDOWB)goto err_out; if(ci->mode_param[i]->mapping>=ci->maps)goto err_out; if(ci->mode_param[i]->mapping<0)goto err_out; } if(oggpack_read(opb,1)!=1)goto err_out; /* top level EOP check */ return(0); err_out: vorbis_info_clear(vi); return(OV_EBADHEADER); }
ogg_sync_state *ogg_sync_create(void){ ogg_sync_state *oy=_ogg_calloc(1,sizeof(*oy)); memset(oy,0,sizeof(*oy)); oy->bufferpool=ogg_buffer_create(); return oy; }