static int _vorbis_pack_info(oggpack_buffer *opb,vorbis_info *vi) { codec_setup_info *ci=vi->codec_setup; if(!ci|| ci->blocksizes[0]<64|| ci->blocksizes[1]<ci->blocksizes[0]) { return(OV_EFAULT); } /* preamble */ oggpack_write(opb,0x01,8); _v_writestring(opb,"vorbis", 6); /* basic information about the stream */ oggpack_write(opb,0x00,32); oggpack_write(opb,vi->channels,8); oggpack_write(opb,vi->rate,32); oggpack_write(opb,vi->bitrate_upper,32); oggpack_write(opb,vi->bitrate_nominal,32); oggpack_write(opb,vi->bitrate_lower,32); oggpack_write(opb,ov_ilog(ci->blocksizes[0]-1),4); oggpack_write(opb,ov_ilog(ci->blocksizes[1]-1),4); oggpack_write(opb,1,1); return(0); }
/* also responsible for range checking */ static vorbis_info_mapping *mapping0_unpack(vorbis_info *vi,oggpack_buffer *opb){ int i,b; vorbis_info_mapping0 *info=_ogg_calloc(1,sizeof(*info)); codec_setup_info *ci=vi->codec_setup; memset(info,0,sizeof(*info)); if(vi->channels<=0)goto err_out; b=oggpack_read(opb,1); if(b<0)goto err_out; if(b){ info->submaps=oggpack_read(opb,4)+1; if(info->submaps<=0)goto err_out; }else info->submaps=1; b=oggpack_read(opb,1); if(b<0)goto err_out; if(b){ info->coupling_steps=oggpack_read(opb,8)+1; if(info->coupling_steps<=0)goto err_out; for(i=0;i<info->coupling_steps;i++){ /* vi->channels > 0 is enforced in the caller */ int testM=info->coupling_mag[i]= oggpack_read(opb,ov_ilog(vi->channels-1)); int testA=info->coupling_ang[i]= oggpack_read(opb,ov_ilog(vi->channels-1)); if(testM<0 || testA<0 || testM==testA || testM>=vi->channels || testA>=vi->channels) goto err_out; } } if(oggpack_read(opb,2)!=0)goto err_out; /* 2,3:reserved */ if(info->submaps>1){ for(i=0;i<vi->channels;i++){ info->chmuxlist[i]=oggpack_read(opb,4); if(info->chmuxlist[i]>=info->submaps || info->chmuxlist[i]<0)goto err_out; } } for(i=0;i<info->submaps;i++){ oggpack_read(opb,8); /* time submap unused */ info->floorsubmap[i]=oggpack_read(opb,8); if(info->floorsubmap[i]>=ci->floors || info->floorsubmap[i]<0)goto err_out; info->residuesubmap[i]=oggpack_read(opb,8); if(info->residuesubmap[i]>=ci->residues || info->residuesubmap[i]<0)goto err_out; } return info; err_out: mapping0_free_info(info); return(NULL); }
static void mapping0_pack(vorbis_info *vi,vorbis_info_mapping *vm, oggpack_buffer *opb){ int i; vorbis_info_mapping0 *info=(vorbis_info_mapping0 *)vm; /* another 'we meant to do it this way' hack... up to beta 4, we packed 4 binary zeros here to signify one submapping in use. We now redefine that to mean four bitflags that indicate use of deeper features; bit0:submappings, bit1:coupling, bit2,3:reserved. This is backward compatable with all actual uses of the beta code. */ if(info->submaps>1){ oggpack_write(opb,1,1); oggpack_write(opb,info->submaps-1,4); }else oggpack_write(opb,0,1); if(info->coupling_steps>0){ oggpack_write(opb,1,1); oggpack_write(opb,info->coupling_steps-1,8); for(i=0;i<info->coupling_steps;i++){ oggpack_write(opb,info->coupling_mag[i],ov_ilog(vi->channels-1)); oggpack_write(opb,info->coupling_ang[i],ov_ilog(vi->channels-1)); } }else oggpack_write(opb,0,1); oggpack_write(opb,0,2); /* 2,3:reserved */ /* we don't write the channel submappings if we only have one... */ if(info->submaps>1){ for(i=0;i<vi->channels;i++) oggpack_write(opb,info->chmuxlist[i],4); } for(i=0;i<info->submaps;i++){ oggpack_write(opb,0,8); /* time submap unused */ oggpack_write(opb,info->floorsubmap[i],8); oggpack_write(opb,info->residuesubmap[i],8); } }
int vorbis_staticbook_pack(const static_codebook *c,oggpack_buffer *opb){ long i,j; int ordered=0; /* first the basic parameters */ oggpack_write(opb,0x564342,24); oggpack_write(opb,c->dim,16); oggpack_write(opb,c->entries,24); /* pack the codewords. There are two packings; length ordered and length random. Decide between the two now. */ for(i=1;i<c->entries;i++) if(c->lengthlist[i-1]==0 || c->lengthlist[i]<c->lengthlist[i-1])break; if(i==c->entries)ordered=1; if(ordered){ /* length ordered. We only need to say how many codewords of each length. The actual codewords are generated deterministically */ long count=0; oggpack_write(opb,1,1); /* ordered */ oggpack_write(opb,c->lengthlist[0]-1,5); /* 1 to 32 */ for(i=1;i<c->entries;i++){ char this=c->lengthlist[i]; char last=c->lengthlist[i-1]; if(this>last){ for(j=last;j<this;j++){ oggpack_write(opb,i-count,ov_ilog(c->entries-count)); count=i; } } } oggpack_write(opb,i-count,ov_ilog(c->entries-count)); }else{
static void floor1_pack (vorbis_info_floor *i,oggpack_buffer *opb){ vorbis_info_floor1 *info=(vorbis_info_floor1 *)i; int j,k; int count=0; int rangebits; int maxposit=info->postlist[1]; int maxclass=-1; /* save out partitions */ oggpack_write(opb,info->partitions,5); /* only 0 to 31 legal */ for(j=0;j<info->partitions;j++){ oggpack_write(opb,info->partitionclass[j],4); /* only 0 to 15 legal */ if(maxclass<info->partitionclass[j])maxclass=info->partitionclass[j]; } /* save out partition classes */ for(j=0;j<maxclass+1;j++){ oggpack_write(opb,info->class_dim[j]-1,3); /* 1 to 8 */ oggpack_write(opb,info->class_subs[j],2); /* 0 to 3 */ if(info->class_subs[j])oggpack_write(opb,info->class_book[j],8); for(k=0;k<(1<<info->class_subs[j]);k++) oggpack_write(opb,info->class_subbook[j][k]+1,8); } /* save out the post list */ oggpack_write(opb,info->mult-1,2); /* only 1,2,3,4 legal now */ /* maxposit cannot legally be less than 1; this is encode-side, we can assume our setup is OK */ oggpack_write(opb,ov_ilog(maxposit-1),4); rangebits=ov_ilog(maxposit-1); for(j=0,k=0;j<info->partitions;j++){ count+=info->class_dim[info->partitionclass[j]]; for(;k<count;k++) oggpack_write(opb,info->postlist[k+2],rangebits); } }
void res0_pack(vorbis_info_residue *vr,oggpack_buffer *opb){ vorbis_info_residue0 *info=(vorbis_info_residue0 *)vr; int j,acc=0; oggpack_write(opb,info->begin,24); oggpack_write(opb,info->end,24); oggpack_write(opb,info->grouping-1,24); /* residue vectors to group and code with a partitioned book */ oggpack_write(opb,info->partitions-1,6); /* possible partition choices */ oggpack_write(opb,info->groupbook,8); /* group huffman book */ /* secondstages is a bitmask; as encoding progresses pass by pass, a bitmask of one indicates this partition class has bits to write this pass */ for(j=0;j<info->partitions;j++){ if(ov_ilog(info->secondstages[j])>3){ /* yes, this is a minor hack due to not thinking ahead */ oggpack_write(opb,info->secondstages[j],3); oggpack_write(opb,1,1); oggpack_write(opb,info->secondstages[j]>>3,5); }else
long vorbis_packet_blocksize(vorbis_info *vi,ogg_packet *op){ codec_setup_info *ci=vi->codec_setup; oggpack_buffer opb; int mode; if(ci==NULL || ci->modes<=0){ /* codec setup not properly intialized */ return(OV_EFAULT); } oggpack_readinit(&opb,op->packet,op->bytes); /* Check the packet type */ if(oggpack_read(&opb,1)!=0){ /* Oops. This is not an audio data packet */ return(OV_ENOTAUDIO); } /* read our mode and pre/post windowsize */ mode=oggpack_read(&opb,ov_ilog(ci->modes-1)); if(mode==-1 || !ci->mode_param[mode])return(OV_EBADPACKET); return(ci->blocksizes[ci->mode_param[mode]->blockflag]); }
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|| ci->modes<=0|| ci->blocksizes[0]<64|| ci->blocksizes[1]<ci->blocksizes[0]){ 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=ov_ilog(ci->modes-1); 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 */ /* note that the correct computation below is technically: b->window[0]=ov_ilog(ci->blocksizes[0]-1)-6; b->window[1]=ov_ilog(ci->blocksizes[1]-1)-6; but since blocksizes are always powers of two, the below is equivalent. */ b->window[0]=ov_ilog(ci->blocksizes[0])-7; b->window[1]=ov_ilog(ci->blocksizes[1])-7; 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; }