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