info.c - vx32 - Local 9vx git repository for patches.
 (HTM) git clone git://r-36.net/vx32
 (DIR) Log
 (DIR) Files
 (DIR) Refs
       ---
       info.c (17109B)
       ---
            1 /********************************************************************
            2  *                                                                  *
            3  * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE.   *
            4  * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
            5  * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
            6  * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
            7  *                                                                  *
            8  * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2003             *
            9  * by the XIPHOPHORUS Company http://www.xiph.org/                  *
           10  *                                                                  *
           11  ********************************************************************
           12 
           13  function: maintain the info structure, info <-> header packets
           14  last mod: $Id: info.c 1919 2005-07-24 14:18:04Z baford $
           15 
           16  ********************************************************************/
           17 
           18 /* general handling of the header and the vorbis_info structure (and
           19    substructures) */
           20 
           21 #include <stdlib.h>
           22 #include <string.h>
           23 #include <ctype.h>
           24 #include <ogg/ogg.h>
           25 #include "vorbis/codec.h"
           26 #include "codec_internal.h"
           27 #include "codebook.h"
           28 #include "registry.h"
           29 #include "window.h"
           30 #include "psy.h"
           31 #include "misc.h"
           32 #include "os.h"
           33 
           34 /* helpers */
           35 static int ilog2(unsigned int v){
           36   int ret=0;
           37   if(v)--v;
           38   while(v){
           39     ret++;
           40     v>>=1;
           41   }
           42   return(ret);
           43 }
           44 
           45 static void _v_writestring(oggpack_buffer *o,char *s, int bytes){
           46 
           47   while(bytes--){
           48     oggpack_write(o,*s++,8);
           49   }
           50 }
           51 
           52 static void _v_readstring(oggpack_buffer *o,char *buf,int bytes){
           53   while(bytes--){
           54     *buf++=oggpack_read(o,8);
           55   }
           56 }
           57 
           58 void vorbis_comment_init(vorbis_comment *vc){
           59   memset(vc,0,sizeof(*vc));
           60 }
           61 
           62 void vorbis_comment_add(vorbis_comment *vc,char *comment){
           63   vc->user_comments=_ogg_realloc(vc->user_comments,
           64                             (vc->comments+2)*sizeof(*vc->user_comments));
           65   vc->comment_lengths=_ogg_realloc(vc->comment_lengths,
           66                                   (vc->comments+2)*sizeof(*vc->comment_lengths));
           67   vc->comment_lengths[vc->comments]=strlen(comment);
           68   vc->user_comments[vc->comments]=_ogg_malloc(vc->comment_lengths[vc->comments]+1);
           69   strcpy(vc->user_comments[vc->comments], comment);
           70   vc->comments++;
           71   vc->user_comments[vc->comments]=NULL;
           72 }
           73 
           74 void vorbis_comment_add_tag(vorbis_comment *vc, char *tag, char *contents){
           75   char *comment=alloca(strlen(tag)+strlen(contents)+2); /* +2 for = and \0 */
           76   strcpy(comment, tag);
           77   strcat(comment, "=");
           78   strcat(comment, contents);
           79   vorbis_comment_add(vc, comment);
           80 }
           81 
           82 /* This is more or less the same as strncasecmp - but that doesn't exist
           83  * everywhere, and this is a fairly trivial function, so we include it */
           84 static int tagcompare(const char *s1, const char *s2, int n){
           85   int c=0;
           86   while(c < n){
           87     if(toupper(s1[c]) != toupper(s2[c]))
           88       return !0;
           89     c++;
           90   }
           91   return 0;
           92 }
           93 
           94 char *vorbis_comment_query(vorbis_comment *vc, char *tag, int count){
           95   long i;
           96   int found = 0;
           97   int taglen = strlen(tag)+1; /* +1 for the = we append */
           98   char *fulltag = alloca(taglen+ 1);
           99 
          100   strcpy(fulltag, tag);
          101   strcat(fulltag, "=");
          102   
          103   for(i=0;i<vc->comments;i++){
          104     if(!tagcompare(vc->user_comments[i], fulltag, taglen)){
          105       if(count == found)
          106         /* We return a pointer to the data, not a copy */
          107               return vc->user_comments[i] + taglen;
          108       else
          109         found++;
          110     }
          111   }
          112   return NULL; /* didn't find anything */
          113 }
          114 
          115 int vorbis_comment_query_count(vorbis_comment *vc, char *tag){
          116   int i,count=0;
          117   int taglen = strlen(tag)+1; /* +1 for the = we append */
          118   char *fulltag = alloca(taglen+1);
          119   strcpy(fulltag,tag);
          120   strcat(fulltag, "=");
          121 
          122   for(i=0;i<vc->comments;i++){
          123     if(!tagcompare(vc->user_comments[i], fulltag, taglen))
          124       count++;
          125   }
          126 
          127   return count;
          128 }
          129 
          130 void vorbis_comment_clear(vorbis_comment *vc){
          131   if(vc){
          132     long i;
          133     for(i=0;i<vc->comments;i++)
          134       if(vc->user_comments[i])_ogg_free(vc->user_comments[i]);
          135     if(vc->user_comments)_ogg_free(vc->user_comments);
          136         if(vc->comment_lengths)_ogg_free(vc->comment_lengths);
          137     if(vc->vendor)_ogg_free(vc->vendor);
          138   }
          139   memset(vc,0,sizeof(*vc));
          140 }
          141 
          142 /* blocksize 0 is guaranteed to be short, 1 is guarantted to be long.
          143    They may be equal, but short will never ge greater than long */
          144 int vorbis_info_blocksize(vorbis_info *vi,int zo){
          145   codec_setup_info *ci = vi->codec_setup;
          146   return ci ? ci->blocksizes[zo] : -1;
          147 }
          148 
          149 /* used by synthesis, which has a full, alloced vi */
          150 void vorbis_info_init(vorbis_info *vi){
          151   memset(vi,0,sizeof(*vi));
          152   vi->codec_setup=_ogg_calloc(1,sizeof(codec_setup_info));
          153 }
          154 
          155 void vorbis_info_clear(vorbis_info *vi){
          156   codec_setup_info     *ci=vi->codec_setup;
          157   int i;
          158 
          159   if(ci){
          160 
          161     for(i=0;i<ci->modes;i++)
          162       if(ci->mode_param[i])_ogg_free(ci->mode_param[i]);
          163 
          164     for(i=0;i<ci->maps;i++) /* unpack does the range checking */
          165       _mapping_P[ci->map_type[i]]->free_info(ci->map_param[i]);
          166 
          167     for(i=0;i<ci->floors;i++) /* unpack does the range checking */
          168       _floor_P[ci->floor_type[i]]->free_info(ci->floor_param[i]);
          169     
          170     for(i=0;i<ci->residues;i++) /* unpack does the range checking */
          171       _residue_P[ci->residue_type[i]]->free_info(ci->residue_param[i]);
          172 
          173     for(i=0;i<ci->books;i++){
          174       if(ci->book_param[i]){
          175         /* knows if the book was not alloced */
          176         vorbis_staticbook_destroy(ci->book_param[i]);
          177       }
          178       if(ci->fullbooks)
          179         vorbis_book_clear(ci->fullbooks+i);
          180     }
          181     if(ci->fullbooks)
          182         _ogg_free(ci->fullbooks);
          183     
          184     for(i=0;i<ci->psys;i++)
          185       _vi_psy_free(ci->psy_param[i]);
          186 
          187     _ogg_free(ci);
          188   }
          189 
          190   memset(vi,0,sizeof(*vi));
          191 }
          192 
          193 /* Header packing/unpacking ********************************************/
          194 
          195 static int _vorbis_unpack_info(vorbis_info *vi,oggpack_buffer *opb){
          196   codec_setup_info     *ci=vi->codec_setup;
          197   if(!ci)return(OV_EFAULT);
          198 
          199   vi->version=oggpack_read(opb,32);
          200   if(vi->version!=0)return(OV_EVERSION);
          201 
          202   vi->channels=oggpack_read(opb,8);
          203   vi->rate=oggpack_read(opb,32);
          204 
          205   vi->bitrate_upper=oggpack_read(opb,32);
          206   vi->bitrate_nominal=oggpack_read(opb,32);
          207   vi->bitrate_lower=oggpack_read(opb,32);
          208 
          209   ci->blocksizes[0]=1<<oggpack_read(opb,4);
          210   ci->blocksizes[1]=1<<oggpack_read(opb,4);
          211   
          212   if(vi->rate<1)goto err_out;
          213   if(vi->channels<1)goto err_out;
          214   if(ci->blocksizes[0]<8)goto err_out; 
          215   if(ci->blocksizes[1]<ci->blocksizes[0])goto err_out;
          216   
          217   if(oggpack_read(opb,1)!=1)goto err_out; /* EOP check */
          218 
          219   return(0);
          220  err_out:
          221   vorbis_info_clear(vi);
          222   return(OV_EBADHEADER);
          223 }
          224 
          225 static int _vorbis_unpack_comment(vorbis_comment *vc,oggpack_buffer *opb){
          226   int i;
          227   int vendorlen=oggpack_read(opb,32);
          228   if(vendorlen<0)goto err_out;
          229   vc->vendor=_ogg_calloc(vendorlen+1,1);
          230   _v_readstring(opb,vc->vendor,vendorlen);
          231   vc->comments=oggpack_read(opb,32);
          232   if(vc->comments<0)goto err_out;
          233   vc->user_comments=_ogg_calloc(vc->comments+1,sizeof(*vc->user_comments));
          234   vc->comment_lengths=_ogg_calloc(vc->comments+1, sizeof(*vc->comment_lengths));
          235             
          236   for(i=0;i<vc->comments;i++){
          237     int len=oggpack_read(opb,32);
          238     if(len<0)goto err_out;
          239         vc->comment_lengths[i]=len;
          240     vc->user_comments[i]=_ogg_calloc(len+1,1);
          241     _v_readstring(opb,vc->user_comments[i],len);
          242   }          
          243   if(oggpack_read(opb,1)!=1)goto err_out; /* EOP check */
          244 
          245   return(0);
          246  err_out:
          247   vorbis_comment_clear(vc);
          248   return(OV_EBADHEADER);
          249 }
          250 
          251 /* all of the real encoding details are here.  The modes, books,
          252    everything */
          253 static int _vorbis_unpack_books(vorbis_info *vi,oggpack_buffer *opb){
          254   codec_setup_info     *ci=vi->codec_setup;
          255   int i;
          256   if(!ci)return(OV_EFAULT);
          257 
          258   /* codebooks */
          259   ci->books=oggpack_read(opb,8)+1;
          260   /*ci->book_param=_ogg_calloc(ci->books,sizeof(*ci->book_param));*/
          261   for(i=0;i<ci->books;i++){
          262     ci->book_param[i]=_ogg_calloc(1,sizeof(*ci->book_param[i]));
          263     if(vorbis_staticbook_unpack(opb,ci->book_param[i]))goto err_out;
          264   }
          265 
          266   /* time backend settings; hooks are unused */
          267   {
          268     int times=oggpack_read(opb,6)+1;
          269     for(i=0;i<times;i++){
          270       int test=oggpack_read(opb,16);
          271       if(test<0 || test>=VI_TIMEB)goto err_out;
          272     }
          273   }
          274 
          275   /* floor backend settings */
          276   ci->floors=oggpack_read(opb,6)+1;
          277   /*ci->floor_type=_ogg_malloc(ci->floors*sizeof(*ci->floor_type));*/
          278   /*ci->floor_param=_ogg_calloc(ci->floors,sizeof(void *));*/
          279   for(i=0;i<ci->floors;i++){
          280     ci->floor_type[i]=oggpack_read(opb,16);
          281     if(ci->floor_type[i]<0 || ci->floor_type[i]>=VI_FLOORB)goto err_out;
          282     ci->floor_param[i]=_floor_P[ci->floor_type[i]]->unpack(vi,opb);
          283     if(!ci->floor_param[i])goto err_out;
          284   }
          285 
          286   /* residue backend settings */
          287   ci->residues=oggpack_read(opb,6)+1;
          288   /*ci->residue_type=_ogg_malloc(ci->residues*sizeof(*ci->residue_type));*/
          289   /*ci->residue_param=_ogg_calloc(ci->residues,sizeof(void *));*/
          290   for(i=0;i<ci->residues;i++){
          291     ci->residue_type[i]=oggpack_read(opb,16);
          292     if(ci->residue_type[i]<0 || ci->residue_type[i]>=VI_RESB)goto err_out;
          293     ci->residue_param[i]=_residue_P[ci->residue_type[i]]->unpack(vi,opb);
          294     if(!ci->residue_param[i])goto err_out;
          295   }
          296 
          297   /* map backend settings */
          298   ci->maps=oggpack_read(opb,6)+1;
          299   /*ci->map_type=_ogg_malloc(ci->maps*sizeof(*ci->map_type));*/
          300   /*ci->map_param=_ogg_calloc(ci->maps,sizeof(void *));*/
          301   for(i=0;i<ci->maps;i++){
          302     ci->map_type[i]=oggpack_read(opb,16);
          303     if(ci->map_type[i]<0 || ci->map_type[i]>=VI_MAPB)goto err_out;
          304     ci->map_param[i]=_mapping_P[ci->map_type[i]]->unpack(vi,opb);
          305     if(!ci->map_param[i])goto err_out;
          306   }
          307   
          308   /* mode settings */
          309   ci->modes=oggpack_read(opb,6)+1;
          310   /*vi->mode_param=_ogg_calloc(vi->modes,sizeof(void *));*/
          311   for(i=0;i<ci->modes;i++){
          312     ci->mode_param[i]=_ogg_calloc(1,sizeof(*ci->mode_param[i]));
          313     ci->mode_param[i]->blockflag=oggpack_read(opb,1);
          314     ci->mode_param[i]->windowtype=oggpack_read(opb,16);
          315     ci->mode_param[i]->transformtype=oggpack_read(opb,16);
          316     ci->mode_param[i]->mapping=oggpack_read(opb,8);
          317 
          318     if(ci->mode_param[i]->windowtype>=VI_WINDOWB)goto err_out;
          319     if(ci->mode_param[i]->transformtype>=VI_WINDOWB)goto err_out;
          320     if(ci->mode_param[i]->mapping>=ci->maps)goto err_out;
          321   }
          322   
          323   if(oggpack_read(opb,1)!=1)goto err_out; /* top level EOP check */
          324 
          325   return(0);
          326  err_out:
          327   vorbis_info_clear(vi);
          328   return(OV_EBADHEADER);
          329 }
          330 
          331 /* The Vorbis header is in three packets; the initial small packet in
          332    the first page that identifies basic parameters, a second packet
          333    with bitstream comments and a third packet that holds the
          334    codebook. */
          335 
          336 int vorbis_synthesis_headerin(vorbis_info *vi,vorbis_comment *vc,ogg_packet *op){
          337   oggpack_buffer opb;
          338   
          339   if(op){
          340     oggpack_readinit(&opb,op->packet,op->bytes);
          341 
          342     /* Which of the three types of header is this? */
          343     /* Also verify header-ness, vorbis */
          344     {
          345       char buffer[6];
          346       int packtype=oggpack_read(&opb,8);
          347       memset(buffer,0,6);
          348       _v_readstring(&opb,buffer,6);
          349       if(memcmp(buffer,"vorbis",6)){
          350         /* not a vorbis header */
          351         return(OV_ENOTVORBIS);
          352       }
          353       switch(packtype){
          354       case 0x01: /* least significant *bit* is read first */
          355         if(!op->b_o_s){
          356           /* Not the initial packet */
          357           return(OV_EBADHEADER);
          358         }
          359         if(vi->rate!=0){
          360           /* previously initialized info header */
          361           return(OV_EBADHEADER);
          362         }
          363 
          364         return(_vorbis_unpack_info(vi,&opb));
          365 
          366       case 0x03: /* least significant *bit* is read first */
          367         if(vi->rate==0){
          368           /* um... we didn't get the initial header */
          369           return(OV_EBADHEADER);
          370         }
          371 
          372         return(_vorbis_unpack_comment(vc,&opb));
          373 
          374       case 0x05: /* least significant *bit* is read first */
          375         if(vi->rate==0 || vc->vendor==NULL){
          376           /* um... we didn;t get the initial header or comments yet */
          377           return(OV_EBADHEADER);
          378         }
          379 
          380         return(_vorbis_unpack_books(vi,&opb));
          381 
          382       default:
          383         /* Not a valid vorbis header type */
          384         return(OV_EBADHEADER);
          385         break;
          386       }
          387     }
          388   }
          389   return(OV_EBADHEADER);
          390 }
          391 
          392 /* pack side **********************************************************/
          393 
          394 static int _vorbis_pack_info(oggpack_buffer *opb,vorbis_info *vi){
          395   codec_setup_info     *ci=vi->codec_setup;
          396   if(!ci)return(OV_EFAULT);
          397 
          398   /* preamble */  
          399   oggpack_write(opb,0x01,8);
          400   _v_writestring(opb,"vorbis", 6);
          401 
          402   /* basic information about the stream */
          403   oggpack_write(opb,0x00,32);
          404   oggpack_write(opb,vi->channels,8);
          405   oggpack_write(opb,vi->rate,32);
          406 
          407   oggpack_write(opb,vi->bitrate_upper,32);
          408   oggpack_write(opb,vi->bitrate_nominal,32);
          409   oggpack_write(opb,vi->bitrate_lower,32);
          410 
          411   oggpack_write(opb,ilog2(ci->blocksizes[0]),4);
          412   oggpack_write(opb,ilog2(ci->blocksizes[1]),4);
          413   oggpack_write(opb,1,1);
          414 
          415   return(0);
          416 }
          417 
          418 static int _vorbis_pack_comment(oggpack_buffer *opb,vorbis_comment *vc){
          419   char temp[]="Xiph.Org libVorbis I 20030909";
          420   int bytes = strlen(temp);
          421 
          422   /* preamble */  
          423   oggpack_write(opb,0x03,8);
          424   _v_writestring(opb,"vorbis", 6);
          425 
          426   /* vendor */
          427   oggpack_write(opb,bytes,32);
          428   _v_writestring(opb,temp, bytes);
          429   
          430   /* comments */
          431 
          432   oggpack_write(opb,vc->comments,32);
          433   if(vc->comments){
          434     int i;
          435     for(i=0;i<vc->comments;i++){
          436       if(vc->user_comments[i]){
          437         oggpack_write(opb,vc->comment_lengths[i],32);
          438         _v_writestring(opb,vc->user_comments[i], vc->comment_lengths[i]);
          439       }else{
          440         oggpack_write(opb,0,32);
          441       }
          442     }
          443   }
          444   oggpack_write(opb,1,1);
          445 
          446   return(0);
          447 }
          448  
          449 static int _vorbis_pack_books(oggpack_buffer *opb,vorbis_info *vi){
          450   codec_setup_info     *ci=vi->codec_setup;
          451   int i;
          452   if(!ci)return(OV_EFAULT);
          453 
          454   oggpack_write(opb,0x05,8);
          455   _v_writestring(opb,"vorbis", 6);
          456 
          457   /* books */
          458   oggpack_write(opb,ci->books-1,8);
          459   for(i=0;i<ci->books;i++)
          460     if(vorbis_staticbook_pack(ci->book_param[i],opb))goto err_out;
          461 
          462   /* times; hook placeholders */
          463   oggpack_write(opb,0,6);
          464   oggpack_write(opb,0,16);
          465 
          466   /* floors */
          467   oggpack_write(opb,ci->floors-1,6);
          468   for(i=0;i<ci->floors;i++){
          469     oggpack_write(opb,ci->floor_type[i],16);
          470     if(_floor_P[ci->floor_type[i]]->pack)
          471       _floor_P[ci->floor_type[i]]->pack(ci->floor_param[i],opb);
          472     else
          473       goto err_out;
          474   }
          475 
          476   /* residues */
          477   oggpack_write(opb,ci->residues-1,6);
          478   for(i=0;i<ci->residues;i++){
          479     oggpack_write(opb,ci->residue_type[i],16);
          480     _residue_P[ci->residue_type[i]]->pack(ci->residue_param[i],opb);
          481   }
          482 
          483   /* maps */
          484   oggpack_write(opb,ci->maps-1,6);
          485   for(i=0;i<ci->maps;i++){
          486     oggpack_write(opb,ci->map_type[i],16);
          487     _mapping_P[ci->map_type[i]]->pack(vi,ci->map_param[i],opb);
          488   }
          489 
          490   /* modes */
          491   oggpack_write(opb,ci->modes-1,6);
          492   for(i=0;i<ci->modes;i++){
          493     oggpack_write(opb,ci->mode_param[i]->blockflag,1);
          494     oggpack_write(opb,ci->mode_param[i]->windowtype,16);
          495     oggpack_write(opb,ci->mode_param[i]->transformtype,16);
          496     oggpack_write(opb,ci->mode_param[i]->mapping,8);
          497   }
          498   oggpack_write(opb,1,1);
          499 
          500   return(0);
          501 err_out:
          502   return(-1);
          503 } 
          504 
          505 int vorbis_commentheader_out(vorbis_comment *vc,
          506                                           ogg_packet *op){
          507 
          508   oggpack_buffer opb;
          509 
          510   oggpack_writeinit(&opb);
          511   if(_vorbis_pack_comment(&opb,vc)) return OV_EIMPL;
          512 
          513   op->packet = _ogg_malloc(oggpack_bytes(&opb));
          514   memcpy(op->packet, opb.buffer, oggpack_bytes(&opb));
          515 
          516   op->bytes=oggpack_bytes(&opb);
          517   op->b_o_s=0;
          518   op->e_o_s=0;
          519   op->granulepos=0;
          520 
          521   return 0;
          522 }
          523 
          524 int vorbis_analysis_headerout(vorbis_dsp_state *v,
          525                               vorbis_comment *vc,
          526                               ogg_packet *op,
          527                               ogg_packet *op_comm,
          528                               ogg_packet *op_code){
          529   int ret=OV_EIMPL;
          530   vorbis_info *vi=v->vi;
          531   oggpack_buffer opb;
          532   private_state *b=v->backend_state;
          533 
          534   if(!b){
          535     ret=OV_EFAULT;
          536     goto err_out;
          537   }
          538 
          539   /* first header packet **********************************************/
          540 
          541   oggpack_writeinit(&opb);
          542   if(_vorbis_pack_info(&opb,vi))goto err_out;
          543 
          544   /* build the packet */
          545   if(b->header)_ogg_free(b->header);
          546   b->header=_ogg_malloc(oggpack_bytes(&opb));
          547   memcpy(b->header,opb.buffer,oggpack_bytes(&opb));
          548   op->packet=b->header;
          549   op->bytes=oggpack_bytes(&opb);
          550   op->b_o_s=1;
          551   op->e_o_s=0;
          552   op->granulepos=0;
          553 
          554   /* second header packet (comments) **********************************/
          555 
          556   oggpack_reset(&opb);
          557   if(_vorbis_pack_comment(&opb,vc))goto err_out;
          558 
          559   if(b->header1)_ogg_free(b->header1);
          560   b->header1=_ogg_malloc(oggpack_bytes(&opb));
          561   memcpy(b->header1,opb.buffer,oggpack_bytes(&opb));
          562   op_comm->packet=b->header1;
          563   op_comm->bytes=oggpack_bytes(&opb);
          564   op_comm->b_o_s=0;
          565   op_comm->e_o_s=0;
          566   op_comm->granulepos=0;
          567 
          568   /* third header packet (modes/codebooks) ****************************/
          569 
          570   oggpack_reset(&opb);
          571   if(_vorbis_pack_books(&opb,vi))goto err_out;
          572 
          573   if(b->header2)_ogg_free(b->header2);
          574   b->header2=_ogg_malloc(oggpack_bytes(&opb));
          575   memcpy(b->header2,opb.buffer,oggpack_bytes(&opb));
          576   op_code->packet=b->header2;
          577   op_code->bytes=oggpack_bytes(&opb);
          578   op_code->b_o_s=0;
          579   op_code->e_o_s=0;
          580   op_code->granulepos=0;
          581 
          582   oggpack_writeclear(&opb);
          583   return(0);
          584  err_out:
          585   oggpack_writeclear(&opb);
          586   memset(op,0,sizeof(*op));
          587   memset(op_comm,0,sizeof(*op_comm));
          588   memset(op_code,0,sizeof(*op_code));
          589 
          590   if(b->header)_ogg_free(b->header);
          591   if(b->header1)_ogg_free(b->header1);
          592   if(b->header2)_ogg_free(b->header2);
          593   b->header=NULL;
          594   b->header1=NULL;
          595   b->header2=NULL;
          596   return(ret);
          597 }
          598 
          599 double vorbis_granule_time(vorbis_dsp_state *v,ogg_int64_t granulepos){
          600   if(granulepos>=0)
          601     return((double)granulepos/v->vi->rate);
          602   return(-1);
          603 }