00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include <stdlib.h>
00019 #include <stdio.h>
00020 #include <errno.h>
00021 #include <string.h>
00022 #include <math.h>
00023
00024 #include "vorbis/codec.h"
00025 #include "vorbis/vorbisfile.h"
00026
00027 #include "os.h"
00028 #include "misc.h"
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061 #define CHUNKSIZE 8500
00062
00063 static long _get_data(OggVorbis_File *vf){
00064 errno=0;
00065 if(vf->datasource){
00066 char *buffer=ogg_sync_buffer(&vf->oy,CHUNKSIZE);
00067 long bytes=(vf->callbacks.read_func)(buffer,1,CHUNKSIZE,vf->datasource);
00068 if(bytes>0)ogg_sync_wrote(&vf->oy,bytes);
00069 if(bytes==0 && errno)return(-1);
00070 return(bytes);
00071 }else
00072 return(0);
00073 }
00074
00075
00076 static void _seek_helper(OggVorbis_File *vf,ogg_int64_t offset){
00077 if(vf->datasource){
00078 (vf->callbacks.seek_func)(vf->datasource, offset, SEEK_SET);
00079 vf->offset=offset;
00080 ogg_sync_reset(&vf->oy);
00081 }else{
00082
00083 return;
00084 }
00085 }
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100 static ogg_int64_t _get_next_page(OggVorbis_File *vf,ogg_page *og,
00101 ogg_int64_t boundary){
00102 if(boundary>0)boundary+=vf->offset;
00103 while(1){
00104 long more;
00105
00106 if(boundary>0 && vf->offset>=boundary)return(OV_FALSE);
00107 more=ogg_sync_pageseek(&vf->oy,og);
00108
00109 if(more<0){
00110
00111 vf->offset-=more;
00112 }else{
00113 if(more==0){
00114
00115 if(!boundary)return(OV_FALSE);
00116 {
00117 long ret=_get_data(vf);
00118 if(ret==0)return(OV_EOF);
00119 if(ret<0)return(OV_EREAD);
00120 }
00121 }else{
00122
00123
00124 ogg_int64_t ret=vf->offset;
00125 vf->offset+=more;
00126 return(ret);
00127
00128 }
00129 }
00130 }
00131 }
00132
00133
00134
00135
00136
00137
00138 static ogg_int64_t _get_prev_page(OggVorbis_File *vf,ogg_page *og){
00139 ogg_int64_t begin=vf->offset;
00140 ogg_int64_t end=begin;
00141 ogg_int64_t ret;
00142 ogg_int64_t offset=-1;
00143
00144 while(offset==-1){
00145 begin-=CHUNKSIZE;
00146 if(begin<0)
00147 begin=0;
00148 _seek_helper(vf,begin);
00149 while(vf->offset<end){
00150 ret=_get_next_page(vf,og,end-vf->offset);
00151 if(ret==OV_EREAD)return(OV_EREAD);
00152 if(ret<0){
00153 break;
00154 }else{
00155 offset=ret;
00156 }
00157 }
00158 }
00159
00160
00161 _seek_helper(vf,offset);
00162 ret=_get_next_page(vf,og,CHUNKSIZE);
00163 if(ret<0)
00164
00165 return(OV_EFAULT);
00166
00167 return(offset);
00168 }
00169
00170
00171
00172
00173
00174 static int _bisect_forward_serialno(OggVorbis_File *vf,
00175 ogg_int64_t begin,
00176 ogg_int64_t searched,
00177 ogg_int64_t end,
00178 long currentno,
00179 long m){
00180 ogg_int64_t endsearched=end;
00181 ogg_int64_t next=end;
00182 ogg_page og;
00183 ogg_int64_t ret;
00184
00185
00186
00187 while(searched<endsearched){
00188 ogg_int64_t bisect;
00189
00190 if(endsearched-searched<CHUNKSIZE){
00191 bisect=searched;
00192 }else{
00193 bisect=(searched+endsearched)/2;
00194 }
00195
00196 _seek_helper(vf,bisect);
00197 ret=_get_next_page(vf,&og,-1);
00198 if(ret==OV_EREAD)return(OV_EREAD);
00199 if(ret<0 || ogg_page_serialno(&og)!=currentno){
00200 endsearched=bisect;
00201 if(ret>=0)next=ret;
00202 }else{
00203 searched=ret+og.header_len+og.body_len;
00204 }
00205 }
00206
00207 _seek_helper(vf,next);
00208 ret=_get_next_page(vf,&og,-1);
00209 if(ret==OV_EREAD)return(OV_EREAD);
00210
00211 if(searched>=end || ret<0){
00212 vf->links=m+1;
00213 vf->offsets=_ogg_malloc((vf->links+1)*sizeof(*vf->offsets));
00214 vf->serialnos=_ogg_malloc(vf->links*sizeof(*vf->serialnos));
00215 vf->offsets[m+1]=searched;
00216 }else{
00217 ret=_bisect_forward_serialno(vf,next,vf->offset,
00218 end,ogg_page_serialno(&og),m+1);
00219 if(ret==OV_EREAD)return(OV_EREAD);
00220 }
00221
00222 vf->offsets[m]=begin;
00223 vf->serialnos[m]=currentno;
00224 return(0);
00225 }
00226
00227
00228
00229 static int _fetch_headers(OggVorbis_File *vf,vorbis_info *vi,vorbis_comment *vc,
00230 long *serialno,ogg_page *og_ptr){
00231 ogg_page og;
00232 ogg_packet op;
00233 int i,ret;
00234
00235 if(!og_ptr){
00236 ogg_int64_t llret=_get_next_page(vf,&og,CHUNKSIZE);
00237 if(llret==OV_EREAD)return(OV_EREAD);
00238 if(llret<0)return OV_ENOTVORBIS;
00239 og_ptr=&og;
00240 }
00241
00242 ogg_stream_reset_serialno(&vf->os,ogg_page_serialno(og_ptr));
00243 if(serialno)*serialno=vf->os.serialno;
00244 vf->ready_state=STREAMSET;
00245
00246
00247
00248
00249 vorbis_info_init(vi);
00250 vorbis_comment_init(vc);
00251
00252 i=0;
00253 while(i<3){
00254 ogg_stream_pagein(&vf->os,og_ptr);
00255 while(i<3){
00256 int result=ogg_stream_packetout(&vf->os,&op);
00257 if(result==0)break;
00258 if(result==-1){
00259 ret=OV_EBADHEADER;
00260 goto bail_header;
00261 }
00262 if((ret=vorbis_synthesis_headerin(vi,vc,&op))){
00263 goto bail_header;
00264 }
00265 i++;
00266 }
00267 if(i<3)
00268 if(_get_next_page(vf,og_ptr,CHUNKSIZE)<0){
00269 ret=OV_EBADHEADER;
00270 goto bail_header;
00271 }
00272 }
00273 return 0;
00274
00275 bail_header:
00276 vorbis_info_clear(vi);
00277 vorbis_comment_clear(vc);
00278 vf->ready_state=OPENED;
00279
00280 return ret;
00281 }
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292 static void _prefetch_all_headers(OggVorbis_File *vf, ogg_int64_t dataoffset){
00293 ogg_page og;
00294 int i;
00295 ogg_int64_t ret;
00296
00297 vf->vi=_ogg_realloc(vf->vi,vf->links*sizeof(*vf->vi));
00298 vf->vc=_ogg_realloc(vf->vc,vf->links*sizeof(*vf->vc));
00299 vf->dataoffsets=_ogg_malloc(vf->links*sizeof(*vf->dataoffsets));
00300 vf->pcmlengths=_ogg_malloc(vf->links*2*sizeof(*vf->pcmlengths));
00301
00302 for(i=0;i<vf->links;i++){
00303 if(i==0){
00304
00305 vf->dataoffsets[i]=dataoffset;
00306 _seek_helper(vf,dataoffset);
00307
00308 }else{
00309
00310
00311
00312 _seek_helper(vf,vf->offsets[i]);
00313 if(_fetch_headers(vf,vf->vi+i,vf->vc+i,NULL,NULL)<0){
00314 vf->dataoffsets[i]=-1;
00315 }else{
00316 vf->dataoffsets[i]=vf->offset;
00317 }
00318 }
00319
00320
00321
00322 if(vf->dataoffsets[i]!=-1){
00323 ogg_int64_t accumulated=0;
00324 long lastblock=-1;
00325 int result;
00326
00327 ogg_stream_reset_serialno(&vf->os,vf->serialnos[i]);
00328
00329 while(1){
00330 ogg_packet op;
00331
00332 ret=_get_next_page(vf,&og,-1);
00333 if(ret<0)
00334
00335
00336 break;
00337
00338 if(ogg_page_serialno(&og)!=vf->serialnos[i])
00339 break;
00340
00341
00342 ogg_stream_pagein(&vf->os,&og);
00343 while((result=ogg_stream_packetout(&vf->os,&op))){
00344 if(result>0){
00345 long thisblock=vorbis_packet_blocksize(vf->vi+i,&op);
00346 if(lastblock!=-1)
00347 accumulated+=(lastblock+thisblock)>>2;
00348 lastblock=thisblock;
00349 }
00350 }
00351
00352 if(ogg_page_granulepos(&og)!=-1){
00353
00354 accumulated= ogg_page_granulepos(&og)-accumulated;
00355 break;
00356 }
00357 }
00358
00359
00360
00361 if(accumulated<0)accumulated=0;
00362
00363 vf->pcmlengths[i*2]=accumulated;
00364 }
00365
00366
00367
00368 {
00369 ogg_int64_t end=vf->offsets[i+1];
00370 _seek_helper(vf,end);
00371
00372 while(1){
00373 ret=_get_prev_page(vf,&og);
00374 if(ret<0){
00375
00376 vorbis_info_clear(vf->vi+i);
00377 vorbis_comment_clear(vf->vc+i);
00378 break;
00379 }
00380 if(ogg_page_granulepos(&og)!=-1){
00381 vf->pcmlengths[i*2+1]=ogg_page_granulepos(&og)-vf->pcmlengths[i*2];
00382 break;
00383 }
00384 vf->offset=ret;
00385 }
00386 }
00387 }
00388 }
00389
00390 static int _make_decode_ready(OggVorbis_File *vf){
00391 if(vf->ready_state>STREAMSET)return 0;
00392 if(vf->ready_state<STREAMSET)return OV_EFAULT;
00393 if(vf->seekable){
00394 if(vorbis_synthesis_init(&vf->vd,vf->vi+vf->current_link))
00395 return OV_EBADLINK;
00396 }else{
00397 if(vorbis_synthesis_init(&vf->vd,vf->vi))
00398 return OV_EBADLINK;
00399 }
00400 vorbis_block_init(&vf->vd,&vf->vb);
00401 vf->ready_state=INITSET;
00402 vf->bittrack=0.f;
00403 vf->samptrack=0.f;
00404 return 0;
00405 }
00406
00407 static int _open_seekable2(OggVorbis_File *vf){
00408 long serialno=vf->current_serialno;
00409 ogg_int64_t dataoffset=vf->offset, end;
00410 ogg_page og;
00411
00412
00413
00414
00415 (vf->callbacks.seek_func)(vf->datasource,0,SEEK_END);
00416 vf->offset=vf->end=(vf->callbacks.tell_func)(vf->datasource);
00417
00418
00419
00420 end=_get_prev_page(vf,&og);
00421 if(end<0)return(end);
00422
00423
00424 if(ogg_page_serialno(&og)!=serialno){
00425
00426
00427
00428 if(_bisect_forward_serialno(vf,0,0,end+1,serialno,0)<0)return(OV_EREAD);
00429
00430 }else{
00431
00432
00433 if(_bisect_forward_serialno(vf,0,end,end+1,serialno,0))return(OV_EREAD);
00434
00435 }
00436
00437
00438 _prefetch_all_headers(vf,dataoffset);
00439 return(ov_raw_seek(vf,0));
00440 }
00441
00442
00443 static void _decode_clear(OggVorbis_File *vf){
00444 vorbis_dsp_clear(&vf->vd);
00445 vorbis_block_clear(&vf->vb);
00446 vf->ready_state=OPENED;
00447 }
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460 static int _fetch_and_process_packet(OggVorbis_File *vf,
00461 ogg_packet *op_in,
00462 int readp,
00463 int spanp){
00464 ogg_page og;
00465
00466
00467
00468 while(1){
00469
00470
00471
00472 if(vf->ready_state==INITSET){
00473 while(1) {
00474 ogg_packet op;
00475 ogg_packet *op_ptr=(op_in?op_in:&op);
00476 int result=ogg_stream_packetout(&vf->os,op_ptr);
00477 ogg_int64_t granulepos;
00478
00479 op_in=NULL;
00480 if(result==-1)return(OV_HOLE);
00481 if(result>0){
00482
00483 granulepos=op_ptr->granulepos;
00484 if(!vorbis_synthesis(&vf->vb,op_ptr)){
00485
00486
00487
00488
00489
00490
00491
00492
00493 {
00494 int oldsamples=vorbis_synthesis_pcmout(&vf->vd,NULL);
00495
00496
00497 if(oldsamples)return(OV_EFAULT);
00498
00499 vorbis_synthesis_blockin(&vf->vd,&vf->vb);
00500 vf->samptrack+=vorbis_synthesis_pcmout(&vf->vd,NULL)-oldsamples;
00501 vf->bittrack+=op_ptr->bytes*8;
00502 }
00503
00504
00505 if(granulepos!=-1 && !op_ptr->e_o_s){
00506 int link=(vf->seekable?vf->current_link:0);
00507 int i,samples;
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522 if(vf->seekable && link>0)
00523 granulepos-=vf->pcmlengths[link*2];
00524 if(granulepos<0)granulepos=0;
00525
00526
00527
00528
00529 samples=vorbis_synthesis_pcmout(&vf->vd,NULL);
00530
00531 granulepos-=samples;
00532 for(i=0;i<link;i++)
00533 granulepos+=vf->pcmlengths[i*2+1];
00534 vf->pcm_offset=granulepos;
00535 }
00536 return(1);
00537 }
00538 }
00539 else
00540 break;
00541 }
00542 }
00543
00544 if(vf->ready_state>=OPENED){
00545 ogg_int64_t ret;
00546 if(!readp)return(0);
00547 if((ret=_get_next_page(vf,&og,-1))<0){
00548 return(OV_EOF);
00549
00550 }
00551
00552
00553
00554 vf->bittrack+=og.header_len*8;
00555
00556
00557 if(vf->ready_state==INITSET){
00558 if(vf->current_serialno!=ogg_page_serialno(&og)){
00559 if(!spanp)
00560 return(OV_EOF);
00561
00562 _decode_clear(vf);
00563
00564 if(!vf->seekable){
00565 vorbis_info_clear(vf->vi);
00566 vorbis_comment_clear(vf->vc);
00567 }
00568 }
00569 }
00570 }
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584 if(vf->ready_state!=INITSET){
00585 int link;
00586
00587 if(vf->ready_state<STREAMSET){
00588 if(vf->seekable){
00589 vf->current_serialno=ogg_page_serialno(&og);
00590
00591
00592
00593
00594 for(link=0;link<vf->links;link++)
00595 if(vf->serialnos[link]==vf->current_serialno)break;
00596 if(link==vf->links)return(OV_EBADLINK);
00597
00598
00599
00600
00601 vf->current_link=link;
00602
00603 ogg_stream_reset_serialno(&vf->os,vf->current_serialno);
00604 vf->ready_state=STREAMSET;
00605
00606 }else{
00607
00608
00609
00610 int ret=_fetch_headers(vf,vf->vi,vf->vc,&vf->current_serialno,&og);
00611 if(ret)return(ret);
00612 vf->current_link++;
00613 link=0;
00614 }
00615 }
00616
00617 {
00618 int ret=_make_decode_ready(vf);
00619 if(ret<0)return ret;
00620 }
00621 }
00622 ogg_stream_pagein(&vf->os,&og);
00623 }
00624 }
00625
00626
00627
00628 static int _fseek64_wrap(FILE *f,ogg_int64_t off,int whence){
00629 if(f==NULL)return(-1);
00630 return fseek(f,off,whence);
00631 }
00632
00633 static int _ov_open1(void *f,OggVorbis_File *vf,char *initial,
00634 long ibytes, ov_callbacks callbacks){
00635 int offsettest=(f?callbacks.seek_func(f,0,SEEK_CUR):-1);
00636 int ret;
00637
00638 memset(vf,0,sizeof(*vf));
00639 vf->datasource=f;
00640 vf->callbacks = callbacks;
00641
00642
00643 ogg_sync_init(&vf->oy);
00644
00645
00646
00647
00648
00649 if(initial){
00650 char *buffer=ogg_sync_buffer(&vf->oy,ibytes);
00651 memcpy(buffer,initial,ibytes);
00652 ogg_sync_wrote(&vf->oy,ibytes);
00653 }
00654
00655
00656 if(offsettest!=-1)vf->seekable=1;
00657
00658
00659
00660 vf->links=1;
00661 vf->vi=_ogg_calloc(vf->links,sizeof(*vf->vi));
00662 vf->vc=_ogg_calloc(vf->links,sizeof(*vf->vc));
00663 ogg_stream_init(&vf->os,-1);
00664
00665
00666 if((ret=_fetch_headers(vf,vf->vi,vf->vc,&vf->current_serialno,NULL))<0){
00667 vf->datasource=NULL;
00668 ov_clear(vf);
00669 }else
00670 vf->ready_state=PARTOPEN;
00671 return(ret);
00672 }
00673
00674 static int _ov_open2(OggVorbis_File *vf){
00675 if(vf->ready_state != PARTOPEN) return OV_EINVAL;
00676 vf->ready_state=OPENED;
00677 if(vf->seekable){
00678 int ret=_open_seekable2(vf);
00679 if(ret){
00680 vf->datasource=NULL;
00681 ov_clear(vf);
00682 }
00683 return(ret);
00684 }else
00685 vf->ready_state=STREAMSET;
00686
00687 return 0;
00688 }
00689
00690
00691
00692 int ov_clear(OggVorbis_File *vf){
00693 if(vf){
00694 vorbis_block_clear(&vf->vb);
00695 vorbis_dsp_clear(&vf->vd);
00696 ogg_stream_clear(&vf->os);
00697
00698 if(vf->vi && vf->links){
00699 int i;
00700 for(i=0;i<vf->links;i++){
00701 vorbis_info_clear(vf->vi+i);
00702 vorbis_comment_clear(vf->vc+i);
00703 }
00704 _ogg_free(vf->vi);
00705 _ogg_free(vf->vc);
00706 }
00707 if(vf->dataoffsets)_ogg_free(vf->dataoffsets);
00708 if(vf->pcmlengths)_ogg_free(vf->pcmlengths);
00709 if(vf->serialnos)_ogg_free(vf->serialnos);
00710 if(vf->offsets)_ogg_free(vf->offsets);
00711 ogg_sync_clear(&vf->oy);
00712 if(vf->datasource)(vf->callbacks.close_func)(vf->datasource);
00713 memset(vf,0,sizeof(*vf));
00714 }
00715 #ifdef DEBUG_LEAKS
00716 _VDBG_dump();
00717 #endif
00718 return(0);
00719 }
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729 int ov_open_callbacks(void *f,OggVorbis_File *vf,char *initial,long ibytes,
00730 ov_callbacks callbacks){
00731 int ret=_ov_open1(f,vf,initial,ibytes,callbacks);
00732 if(ret)return ret;
00733 return _ov_open2(vf);
00734 }
00735
00736 int ov_open(FILE *f,OggVorbis_File *vf,char *initial,long ibytes){
00737 ov_callbacks callbacks = {
00738 (size_t (*)(void *, size_t, size_t, void *)) fread,
00739 (int (*)(void *, ogg_int64_t, int)) _fseek64_wrap,
00740 (int (*)(void *)) fclose,
00741 (long (*)(void *)) ftell
00742 };
00743
00744 return ov_open_callbacks((void *)f, vf, initial, ibytes, callbacks);
00745 }
00746
00747
00748
00749
00750 int ov_halfrate(OggVorbis_File *vf,int flag){
00751 int i;
00752 if(vf->vi==NULL)return OV_EINVAL;
00753 if(!vf->seekable)return OV_EINVAL;
00754 if(vf->ready_state>=STREAMSET)
00755 _decode_clear(vf);
00756
00757
00758
00759
00760
00761 for(i=0;i<vf->links;i++){
00762 if(vorbis_synthesis_halfrate(vf->vi+i,flag)){
00763 ov_halfrate(vf,0);
00764 return OV_EINVAL;
00765 }
00766 }
00767 return 0;
00768 }
00769
00770 int ov_halfrate_p(OggVorbis_File *vf){
00771 if(vf->vi==NULL)return OV_EINVAL;
00772 return vorbis_synthesis_halfrate_p(vf->vi);
00773 }
00774
00775
00776
00777
00778
00779
00780 int ov_test_callbacks(void *f,OggVorbis_File *vf,char *initial,long ibytes,
00781 ov_callbacks callbacks)
00782 {
00783 return _ov_open1(f,vf,initial,ibytes,callbacks);
00784 }
00785
00786 int ov_test(FILE *f,OggVorbis_File *vf,char *initial,long ibytes){
00787 ov_callbacks callbacks = {
00788 (size_t (*)(void *, size_t, size_t, void *)) fread,
00789 (int (*)(void *, ogg_int64_t, int)) _fseek64_wrap,
00790 (int (*)(void *)) fclose,
00791 (long (*)(void *)) ftell
00792 };
00793
00794 return ov_test_callbacks((void *)f, vf, initial, ibytes, callbacks);
00795 }
00796
00797 int ov_test_open(OggVorbis_File *vf){
00798 if(vf->ready_state!=PARTOPEN)return(OV_EINVAL);
00799 return _ov_open2(vf);
00800 }
00801
00802
00803 long ov_streams(OggVorbis_File *vf){
00804 return vf->links;
00805 }
00806
00807
00808 long ov_seekable(OggVorbis_File *vf){
00809 return vf->seekable;
00810 }
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821 long ov_bitrate(OggVorbis_File *vf,int i){
00822 if(vf->ready_state<OPENED)return(OV_EINVAL);
00823 if(i>=vf->links)return(OV_EINVAL);
00824 if(!vf->seekable && i!=0)return(ov_bitrate(vf,0));
00825 if(i<0){
00826 ogg_int64_t bits=0;
00827 int i;
00828 float br;
00829 for(i=0;i<vf->links;i++)
00830 bits+=(vf->offsets[i+1]-vf->dataoffsets[i])*8;
00831
00832
00833
00834
00835 br = bits/ov_time_total(vf,-1);
00836 return(rint(br));
00837 }else{
00838 if(vf->seekable){
00839
00840 return(rint((vf->offsets[i+1]-vf->dataoffsets[i])*8/ov_time_total(vf,i)));
00841 }else{
00842
00843 if(vf->vi[i].bitrate_nominal>0){
00844 return vf->vi[i].bitrate_nominal;
00845 }else{
00846 if(vf->vi[i].bitrate_upper>0){
00847 if(vf->vi[i].bitrate_lower>0){
00848 return (vf->vi[i].bitrate_upper+vf->vi[i].bitrate_lower)/2;
00849 }else{
00850 return vf->vi[i].bitrate_upper;
00851 }
00852 }
00853 return(OV_FALSE);
00854 }
00855 }
00856 }
00857 }
00858
00859
00860
00861
00862
00863 long ov_bitrate_instant(OggVorbis_File *vf){
00864 int link=(vf->seekable?vf->current_link:0);
00865 long ret;
00866 if(vf->ready_state<OPENED)return(OV_EINVAL);
00867 if(vf->samptrack==0)return(OV_FALSE);
00868 ret=vf->bittrack/vf->samptrack*vf->vi[link].rate+.5;
00869 vf->bittrack=0.f;
00870 vf->samptrack=0.f;
00871 return(ret);
00872 }
00873
00874
00875 long ov_serialnumber(OggVorbis_File *vf,int i){
00876 if(i>=vf->links)return(ov_serialnumber(vf,vf->links-1));
00877 if(!vf->seekable && i>=0)return(ov_serialnumber(vf,-1));
00878 if(i<0){
00879 return(vf->current_serialno);
00880 }else{
00881 return(vf->serialnos[i]);
00882 }
00883 }
00884
00885
00886
00887
00888
00889
00890 ogg_int64_t ov_raw_total(OggVorbis_File *vf,int i){
00891 if(vf->ready_state<OPENED)return(OV_EINVAL);
00892 if(!vf->seekable || i>=vf->links)return(OV_EINVAL);
00893 if(i<0){
00894 ogg_int64_t acc=0;
00895 int i;
00896 for(i=0;i<vf->links;i++)
00897 acc+=ov_raw_total(vf,i);
00898 return(acc);
00899 }else{
00900 return(vf->offsets[i+1]-vf->offsets[i]);
00901 }
00902 }
00903
00904
00905
00906
00907
00908
00909 ogg_int64_t ov_pcm_total(OggVorbis_File *vf,int i){
00910 if(vf->ready_state<OPENED)return(OV_EINVAL);
00911 if(!vf->seekable || i>=vf->links)return(OV_EINVAL);
00912 if(i<0){
00913 ogg_int64_t acc=0;
00914 int i;
00915 for(i=0;i<vf->links;i++)
00916 acc+=ov_pcm_total(vf,i);
00917 return(acc);
00918 }else{
00919 return(vf->pcmlengths[i*2+1]);
00920 }
00921 }
00922
00923
00924
00925
00926
00927
00928 double ov_time_total(OggVorbis_File *vf,int i){
00929 if(vf->ready_state<OPENED)return(OV_EINVAL);
00930 if(!vf->seekable || i>=vf->links)return(OV_EINVAL);
00931 if(i<0){
00932 double acc=0;
00933 int i;
00934 for(i=0;i<vf->links;i++)
00935 acc+=ov_time_total(vf,i);
00936 return(acc);
00937 }else{
00938 return((double)(vf->pcmlengths[i*2+1])/vf->vi[i].rate);
00939 }
00940 }
00941
00942
00943
00944
00945
00946
00947
00948
00949 int ov_raw_seek(OggVorbis_File *vf,ogg_int64_t pos){
00950 ogg_stream_state work_os;
00951
00952 if(vf->ready_state<OPENED)return(OV_EINVAL);
00953 if(!vf->seekable)
00954 return(OV_ENOSEEK);
00955
00956 if(pos<0 || pos>vf->end)return(OV_EINVAL);
00957
00958
00959
00960
00961
00962 vf->pcm_offset=-1;
00963 ogg_stream_reset_serialno(&vf->os,
00964 vf->current_serialno);
00965 vorbis_synthesis_restart(&vf->vd);
00966
00967 _seek_helper(vf,pos);
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979
00980
00981
00982
00983
00984 {
00985 ogg_page og;
00986 ogg_packet op;
00987 int lastblock=0;
00988 int accblock=0;
00989 int thisblock;
00990 int eosflag;
00991
00992 ogg_stream_init(&work_os,vf->current_serialno);
00993 ogg_stream_reset(&work_os);
00994
00995
00996
00997 while(1){
00998 if(vf->ready_state>=STREAMSET){
00999
01000 int result=ogg_stream_packetout(&work_os,&op);
01001
01002 if(result>0){
01003
01004 if(vf->vi[vf->current_link].codec_setup){
01005 thisblock=vorbis_packet_blocksize(vf->vi+vf->current_link,&op);
01006 if(thisblock<0){
01007 ogg_stream_packetout(&vf->os,NULL);
01008 thisblock=0;
01009 }else{
01010
01011 if(eosflag)
01012 ogg_stream_packetout(&vf->os,NULL);
01013 else
01014 if(lastblock)accblock+=(lastblock+thisblock)>>2;
01015 }
01016
01017 if(op.granulepos!=-1){
01018 int i,link=vf->current_link;
01019 ogg_int64_t granulepos=op.granulepos-vf->pcmlengths[link*2];
01020 if(granulepos<0)granulepos=0;
01021
01022 for(i=0;i<link;i++)
01023 granulepos+=vf->pcmlengths[i*2+1];
01024 vf->pcm_offset=granulepos-accblock;
01025 break;
01026 }
01027 lastblock=thisblock;
01028 continue;
01029 }else
01030 ogg_stream_packetout(&vf->os,NULL);
01031 }
01032 }
01033
01034 if(!lastblock){
01035 if(_get_next_page(vf,&og,-1)<0){
01036 vf->pcm_offset=ov_pcm_total(vf,-1);
01037 break;
01038 }
01039 }else{
01040
01041 vf->pcm_offset=-1;
01042 break;
01043 }
01044
01045
01046 if(vf->ready_state>=STREAMSET)
01047 if(vf->current_serialno!=ogg_page_serialno(&og)){
01048 _decode_clear(vf);
01049 ogg_stream_clear(&work_os);
01050 }
01051
01052 if(vf->ready_state<STREAMSET){
01053 int link;
01054
01055 vf->current_serialno=ogg_page_serialno(&og);
01056 for(link=0;link<vf->links;link++)
01057 if(vf->serialnos[link]==vf->current_serialno)break;
01058 if(link==vf->links)goto seek_error;
01059
01060
01061 vf->current_link=link;
01062
01063 ogg_stream_reset_serialno(&vf->os,vf->current_serialno);
01064 ogg_stream_reset_serialno(&work_os,vf->current_serialno);
01065 vf->ready_state=STREAMSET;
01066
01067 }
01068
01069 ogg_stream_pagein(&vf->os,&og);
01070 ogg_stream_pagein(&work_os,&og);
01071 eosflag=ogg_page_eos(&og);
01072 }
01073 }
01074
01075 ogg_stream_clear(&work_os);
01076 vf->bittrack=0.f;
01077 vf->samptrack=0.f;
01078 return(0);
01079
01080 seek_error:
01081
01082 vf->pcm_offset=-1;
01083 ogg_stream_clear(&work_os);
01084 _decode_clear(vf);
01085 return OV_EBADLINK;
01086 }
01087
01088
01089
01090
01091
01092
01093
01094 int ov_pcm_seek_page(OggVorbis_File *vf,ogg_int64_t pos){
01095 int link=-1;
01096 ogg_int64_t result=0;
01097 ogg_int64_t total=ov_pcm_total(vf,-1);
01098
01099 if(vf->ready_state<OPENED)return(OV_EINVAL);
01100 if(!vf->seekable)return(OV_ENOSEEK);
01101
01102 if(pos<0 || pos>total)return(OV_EINVAL);
01103
01104
01105 for(link=vf->links-1;link>=0;link--){
01106 total-=vf->pcmlengths[link*2+1];
01107 if(pos>=total)break;
01108 }
01109
01110
01111
01112
01113
01114
01115
01116
01117 {
01118 ogg_int64_t end=vf->offsets[link+1];
01119 ogg_int64_t begin=vf->offsets[link];
01120 ogg_int64_t begintime = vf->pcmlengths[link*2];
01121 ogg_int64_t endtime = vf->pcmlengths[link*2+1]+begintime;
01122 ogg_int64_t target=pos-total+begintime;
01123 ogg_int64_t best=begin;
01124
01125 ogg_page og;
01126 while(begin<end){
01127 ogg_int64_t bisect;
01128
01129 if(end-begin<CHUNKSIZE){
01130 bisect=begin;
01131 }else{
01132
01133 bisect=begin +
01134 (target-begintime)*(end-begin)/(endtime-begintime) - CHUNKSIZE;
01135 if(bisect<=begin)
01136 bisect=begin+1;
01137 }
01138
01139 _seek_helper(vf,bisect);
01140
01141 while(begin<end){
01142 result=_get_next_page(vf,&og,end-vf->offset);
01143 if(result==OV_EREAD) goto seek_error;
01144 if(result<0){
01145 if(bisect<=begin+1)
01146 end=begin;
01147 else{
01148 if(bisect==0) goto seek_error;
01149 bisect-=CHUNKSIZE;
01150 if(bisect<=begin)bisect=begin+1;
01151 _seek_helper(vf,bisect);
01152 }
01153 }else{
01154 ogg_int64_t granulepos=ogg_page_granulepos(&og);
01155 if(granulepos==-1)continue;
01156 if(granulepos<target){
01157 best=result;
01158 begin=vf->offset;
01159 begintime=granulepos;
01160
01161 if(target-begintime>44100)break;
01162 bisect=begin;
01163 }else{
01164 if(bisect<=begin+1)
01165 end=begin;
01166 else{
01167 if(end==vf->offset){
01168 end=result;
01169 bisect-=CHUNKSIZE;
01170 if(bisect<=begin)bisect=begin+1;
01171 _seek_helper(vf,bisect);
01172 }else{
01173 end=result;
01174 endtime=granulepos;
01175 break;
01176 }
01177 }
01178 }
01179 }
01180 }
01181 }
01182
01183
01184
01185 {
01186 ogg_page og;
01187 ogg_packet op;
01188
01189
01190 _seek_helper(vf,best);
01191 vf->pcm_offset=-1;
01192
01193 if(_get_next_page(vf,&og,-1)<0)return(OV_EOF);
01194
01195 if(link!=vf->current_link){
01196
01197 _decode_clear(vf);
01198
01199 vf->current_link=link;
01200 vf->current_serialno=ogg_page_serialno(&og);
01201 vf->ready_state=STREAMSET;
01202
01203 }else{
01204 vorbis_synthesis_restart(&vf->vd);
01205 }
01206
01207 ogg_stream_reset_serialno(&vf->os,vf->current_serialno);
01208 ogg_stream_pagein(&vf->os,&og);
01209
01210
01211 while(1){
01212 result=ogg_stream_packetpeek(&vf->os,&op);
01213 if(result==0){
01214
01215
01216
01217
01218
01219 _seek_helper(vf,best);
01220
01221 while(1){
01222 result=_get_prev_page(vf,&og);
01223 if(result<0) goto seek_error;
01224 if(ogg_page_granulepos(&og)>-1 ||
01225 !ogg_page_continued(&og)){
01226 return ov_raw_seek(vf,result);
01227 }
01228 vf->offset=result;
01229 }
01230 }
01231 if(result<0){
01232 result = OV_EBADPACKET;
01233 goto seek_error;
01234 }
01235 if(op.granulepos!=-1){
01236 vf->pcm_offset=op.granulepos-vf->pcmlengths[vf->current_link*2];
01237 if(vf->pcm_offset<0)vf->pcm_offset=0;
01238 vf->pcm_offset+=total;
01239 break;
01240 }else
01241 result=ogg_stream_packetout(&vf->os,NULL);
01242 }
01243 }
01244 }
01245
01246
01247 if(vf->pcm_offset>pos || pos>ov_pcm_total(vf,-1)){
01248 result=OV_EFAULT;
01249 goto seek_error;
01250 }
01251 vf->bittrack=0.f;
01252 vf->samptrack=0.f;
01253 return(0);
01254
01255 seek_error:
01256
01257 vf->pcm_offset=-1;
01258 _decode_clear(vf);
01259 return (int)result;
01260 }
01261
01262
01263
01264
01265 int ov_pcm_seek(OggVorbis_File *vf,ogg_int64_t pos){
01266 int thisblock,lastblock=0;
01267 int ret=ov_pcm_seek_page(vf,pos);
01268 if(ret<0)return(ret);
01269 if((ret=_make_decode_ready(vf)))return ret;
01270
01271
01272
01273
01274 while(1){
01275 ogg_packet op;
01276 ogg_page og;
01277
01278 int ret=ogg_stream_packetpeek(&vf->os,&op);
01279 if(ret>0){
01280 thisblock=vorbis_packet_blocksize(vf->vi+vf->current_link,&op);
01281 if(thisblock<0){
01282 ogg_stream_packetout(&vf->os,NULL);
01283 continue;
01284 }
01285 if(lastblock)vf->pcm_offset+=(lastblock+thisblock)>>2;
01286
01287 if(vf->pcm_offset+((thisblock+
01288 vorbis_info_blocksize(vf->vi,1))>>2)>=pos)break;
01289
01290
01291 ogg_stream_packetout(&vf->os,NULL);
01292 vorbis_synthesis_trackonly(&vf->vb,&op);
01293
01294
01295 vorbis_synthesis_blockin(&vf->vd,&vf->vb);
01296
01297
01298
01299
01300 if(op.granulepos>-1){
01301 int i;
01302
01303 vf->pcm_offset=op.granulepos-vf->pcmlengths[vf->current_link*2];
01304 if(vf->pcm_offset<0)vf->pcm_offset=0;
01305 for(i=0;i<vf->current_link;i++)
01306 vf->pcm_offset+=vf->pcmlengths[i*2+1];
01307 }
01308
01309 lastblock=thisblock;
01310
01311 }else{
01312 if(ret<0 && ret!=OV_HOLE)break;
01313
01314
01315 if(_get_next_page(vf,&og,-1)<0)break;
01316 if(vf->current_serialno!=ogg_page_serialno(&og))_decode_clear(vf);
01317
01318 if(vf->ready_state<STREAMSET){
01319 int link;
01320
01321 vf->current_serialno=ogg_page_serialno(&og);
01322 for(link=0;link<vf->links;link++)
01323 if(vf->serialnos[link]==vf->current_serialno)break;
01324 if(link==vf->links)return(OV_EBADLINK);
01325 vf->current_link=link;
01326
01327 ogg_stream_reset_serialno(&vf->os,vf->current_serialno);
01328 vf->ready_state=STREAMSET;
01329 ret=_make_decode_ready(vf);
01330 if(ret)return ret;
01331 lastblock=0;
01332 }
01333
01334 ogg_stream_pagein(&vf->os,&og);
01335 }
01336 }
01337
01338 vf->bittrack=0.f;
01339 vf->samptrack=0.f;
01340
01341
01342 while(vf->pcm_offset<pos){
01343 ogg_int64_t target=pos-vf->pcm_offset;
01344 long samples=vorbis_synthesis_pcmout(&vf->vd,NULL);
01345
01346 if(samples>target)samples=target;
01347 vorbis_synthesis_read(&vf->vd,samples);
01348 vf->pcm_offset+=samples;
01349
01350 if(samples<target)
01351 if(_fetch_and_process_packet(vf,NULL,1,1)<=0)
01352 vf->pcm_offset=ov_pcm_total(vf,-1);
01353 }
01354 return 0;
01355 }
01356
01357
01358
01359 int ov_time_seek(OggVorbis_File *vf,double seconds){
01360
01361
01362 int link=-1;
01363 ogg_int64_t pcm_total=ov_pcm_total(vf,-1);
01364 double time_total=ov_time_total(vf,-1);
01365
01366 if(vf->ready_state<OPENED)return(OV_EINVAL);
01367 if(!vf->seekable)return(OV_ENOSEEK);
01368 if(seconds<0 || seconds>time_total)return(OV_EINVAL);
01369
01370
01371 for(link=vf->links-1;link>=0;link--){
01372 pcm_total-=vf->pcmlengths[link*2+1];
01373 time_total-=ov_time_total(vf,link);
01374 if(seconds>=time_total)break;
01375 }
01376
01377
01378 {
01379 ogg_int64_t target=pcm_total+(seconds-time_total)*vf->vi[link].rate;
01380 return(ov_pcm_seek(vf,target));
01381 }
01382 }
01383
01384
01385
01386 int ov_time_seek_page(OggVorbis_File *vf,double seconds){
01387
01388
01389 int link=-1;
01390 ogg_int64_t pcm_total=ov_pcm_total(vf,-1);
01391 double time_total=ov_time_total(vf,-1);
01392
01393 if(vf->ready_state<OPENED)return(OV_EINVAL);
01394 if(!vf->seekable)return(OV_ENOSEEK);
01395 if(seconds<0 || seconds>time_total)return(OV_EINVAL);
01396
01397
01398 for(link=vf->links-1;link>=0;link--){
01399 pcm_total-=vf->pcmlengths[link*2+1];
01400 time_total-=ov_time_total(vf,link);
01401 if(seconds>=time_total)break;
01402 }
01403
01404
01405 {
01406 ogg_int64_t target=pcm_total+(seconds-time_total)*vf->vi[link].rate;
01407 return(ov_pcm_seek_page(vf,target));
01408 }
01409 }
01410
01411
01412
01413 ogg_int64_t ov_raw_tell(OggVorbis_File *vf){
01414 if(vf->ready_state<OPENED)return(OV_EINVAL);
01415 return(vf->offset);
01416 }
01417
01418
01419 ogg_int64_t ov_pcm_tell(OggVorbis_File *vf){
01420 if(vf->ready_state<OPENED)return(OV_EINVAL);
01421 return(vf->pcm_offset);
01422 }
01423
01424
01425 double ov_time_tell(OggVorbis_File *vf){
01426 int link=0;
01427 ogg_int64_t pcm_total=0;
01428 double time_total=0.f;
01429
01430 if(vf->ready_state<OPENED)return(OV_EINVAL);
01431 if(vf->seekable){
01432 pcm_total=ov_pcm_total(vf,-1);
01433 time_total=ov_time_total(vf,-1);
01434
01435
01436 for(link=vf->links-1;link>=0;link--){
01437 pcm_total-=vf->pcmlengths[link*2+1];
01438 time_total-=ov_time_total(vf,link);
01439 if(vf->pcm_offset>=pcm_total)break;
01440 }
01441 }
01442
01443 return((double)time_total+(double)(vf->pcm_offset-pcm_total)/vf->vi[link].rate);
01444 }
01445
01446
01447
01448
01449
01450
01451
01452
01453
01454 vorbis_info *ov_info(OggVorbis_File *vf,int link){
01455 if(vf->seekable){
01456 if(link<0)
01457 if(vf->ready_state>=STREAMSET)
01458 return vf->vi+vf->current_link;
01459 else
01460 return vf->vi;
01461 else
01462 if(link>=vf->links)
01463 return NULL;
01464 else
01465 return vf->vi+link;
01466 }else{
01467 return vf->vi;
01468 }
01469 }
01470
01471
01472 vorbis_comment *ov_comment(OggVorbis_File *vf,int link){
01473 if(vf->seekable){
01474 if(link<0)
01475 if(vf->ready_state>=STREAMSET)
01476 return vf->vc+vf->current_link;
01477 else
01478 return vf->vc;
01479 else
01480 if(link>=vf->links)
01481 return NULL;
01482 else
01483 return vf->vc+link;
01484 }else{
01485 return vf->vc;
01486 }
01487 }
01488
01489 static int host_is_big_endian() {
01490 ogg_int32_t pattern = 0xfeedface;
01491 unsigned char *bytewise = (unsigned char *)&pattern;
01492 if (bytewise[0] == 0xfe) return 1;
01493 return 0;
01494 }
01495
01496
01497
01498
01499
01500
01501
01502
01503
01504
01505
01506
01507
01508
01509
01510
01511
01512
01513
01514
01515
01516
01517
01518
01519
01520
01521
01522
01523
01524
01525
01526
01527 long ov_read(OggVorbis_File *vf,char *buffer,int length,
01528 int bigendianp,int word,int sgned,int *bitstream){
01529 int i,j;
01530 int host_endian = host_is_big_endian();
01531
01532 float **pcm;
01533 long samples;
01534
01535 if(vf->ready_state<OPENED)return(OV_EINVAL);
01536
01537 while(1){
01538 if(vf->ready_state==INITSET){
01539 samples=vorbis_synthesis_pcmout(&vf->vd,&pcm);
01540 if(samples)break;
01541 }
01542
01543
01544 {
01545 int ret=_fetch_and_process_packet(vf,NULL,1,1);
01546 if(ret==OV_EOF)
01547 return(0);
01548 if(ret<=0)
01549 return(ret);
01550 }
01551
01552 }
01553
01554 if(samples>0){
01555
01556
01557
01558 long channels=ov_info(vf,-1)->channels;
01559 long bytespersample=word * channels;
01560 vorbis_fpu_control fpu;
01561 if(samples>length/bytespersample)samples=length/bytespersample;
01562
01563 if(samples <= 0)
01564 return OV_EINVAL;
01565
01566
01567 {
01568 int val;
01569 if(word==1){
01570 int off=(sgned?0:128);
01571 vorbis_fpu_setround(&fpu);
01572 for(j=0;j<samples;j++)
01573 for(i=0;i<channels;i++){
01574 val=vorbis_ftoi(pcm[i][j]*128.f);
01575 if(val>127)val=127;
01576 else if(val<-128)val=-128;
01577 *buffer++=val+off;
01578 }
01579 vorbis_fpu_restore(fpu);
01580 }else{
01581 int off=(sgned?0:32768);
01582
01583 if(host_endian==bigendianp){
01584 if(sgned){
01585
01586 vorbis_fpu_setround(&fpu);
01587 for(i=0;i<channels;i++) {
01588 float *src=pcm[i];
01589 short *dest=((short *)buffer)+i;
01590 for(j=0;j<samples;j++) {
01591 val=vorbis_ftoi(src[j]*32768.f);
01592 if(val>32767)val=32767;
01593 else if(val<-32768)val=-32768;
01594 *dest=val;
01595 dest+=channels;
01596 }
01597 }
01598 vorbis_fpu_restore(fpu);
01599
01600 }else{
01601
01602 vorbis_fpu_setround(&fpu);
01603 for(i=0;i<channels;i++) {
01604 float *src=pcm[i];
01605 short *dest=((short *)buffer)+i;
01606 for(j=0;j<samples;j++) {
01607 val=vorbis_ftoi(src[j]*32768.f);
01608 if(val>32767)val=32767;
01609 else if(val<-32768)val=-32768;
01610 *dest=val+off;
01611 dest+=channels;
01612 }
01613 }
01614 vorbis_fpu_restore(fpu);
01615
01616 }
01617 }else if(bigendianp){
01618
01619 vorbis_fpu_setround(&fpu);
01620 for(j=0;j<samples;j++)
01621 for(i=0;i<channels;i++){
01622 val=vorbis_ftoi(pcm[i][j]*32768.f);
01623 if(val>32767)val=32767;
01624 else if(val<-32768)val=-32768;
01625 val+=off;
01626 *buffer++=(val>>8);
01627 *buffer++=(val&0xff);
01628 }
01629 vorbis_fpu_restore(fpu);
01630
01631 }else{
01632 int val;
01633 vorbis_fpu_setround(&fpu);
01634 for(j=0;j<samples;j++)
01635 for(i=0;i<channels;i++){
01636 val=vorbis_ftoi(pcm[i][j]*32768.f);
01637 if(val>32767)val=32767;
01638 else if(val<-32768)val=-32768;
01639 val+=off;
01640 *buffer++=(val&0xff);
01641 *buffer++=(val>>8);
01642 }
01643 vorbis_fpu_restore(fpu);
01644
01645 }
01646 }
01647 }
01648
01649 vorbis_synthesis_read(&vf->vd,samples);
01650 vf->pcm_offset+=samples;
01651 if(bitstream)*bitstream=vf->current_link;
01652 return(samples*bytespersample);
01653 }else{
01654 return(samples);
01655 }
01656 }
01657
01658
01659
01660
01661
01662
01663
01664
01665
01666
01667
01668
01669
01670
01671
01672 long ov_read_float(OggVorbis_File *vf,float ***pcm_channels,int length,
01673 int *bitstream){
01674
01675 if(vf->ready_state<OPENED)return(OV_EINVAL);
01676
01677 while(1){
01678 if(vf->ready_state==INITSET){
01679 float **pcm;
01680 long samples=vorbis_synthesis_pcmout(&vf->vd,&pcm);
01681 if(samples){
01682 if(pcm_channels)*pcm_channels=pcm;
01683 if(samples>length)samples=length;
01684 vorbis_synthesis_read(&vf->vd,samples);
01685 vf->pcm_offset+=samples;
01686 if(bitstream)*bitstream=vf->current_link;
01687 return samples;
01688
01689 }
01690 }
01691
01692
01693 {
01694 int ret=_fetch_and_process_packet(vf,NULL,1,1);
01695 if(ret==OV_EOF)return(0);
01696 if(ret<=0)return(ret);
01697 }
01698
01699 }
01700 }
01701
01702 extern float *vorbis_window(vorbis_dsp_state *v,int W);
01703 extern void _analysis_output_always(char *base,int i,float *v,int n,int bark,int dB,
01704 ogg_int64_t off);
01705
01706 static void _ov_splice(float **pcm,float **lappcm,
01707 int n1, int n2,
01708 int ch1, int ch2,
01709 float *w1, float *w2){
01710 int i,j;
01711 float *w=w1;
01712 int n=n1;
01713
01714 if(n1>n2){
01715 n=n2;
01716 w=w2;
01717 }
01718
01719
01720 for(j=0;j<ch1 && j<ch2;j++){
01721 float *s=lappcm[j];
01722 float *d=pcm[j];
01723
01724 for(i=0;i<n;i++){
01725 float wd=w[i]*w[i];
01726 float ws=1.-wd;
01727 d[i]=d[i]*wd + s[i]*ws;
01728 }
01729 }
01730
01731 for(;j<ch2;j++){
01732 float *d=pcm[j];
01733 for(i=0;i<n;i++){
01734 float wd=w[i]*w[i];
01735 d[i]=d[i]*wd;
01736 }
01737 }
01738
01739 }
01740
01741
01742 static int _ov_initset(OggVorbis_File *vf){
01743 while(1){
01744 if(vf->ready_state==INITSET)break;
01745
01746 {
01747 int ret=_fetch_and_process_packet(vf,NULL,1,0);
01748 if(ret<0 && ret!=OV_HOLE)return(ret);
01749 }
01750 }
01751 return 0;
01752 }
01753
01754
01755
01756
01757 static int _ov_initprime(OggVorbis_File *vf){
01758 vorbis_dsp_state *vd=&vf->vd;
01759 while(1){
01760 if(vf->ready_state==INITSET)
01761 if(vorbis_synthesis_pcmout(vd,NULL))break;
01762
01763
01764 {
01765 int ret=_fetch_and_process_packet(vf,NULL,1,0);
01766 if(ret<0 && ret!=OV_HOLE)return(ret);
01767 }
01768 }
01769 return 0;
01770 }
01771
01772
01773
01774
01775 static void _ov_getlap(OggVorbis_File *vf,vorbis_info *vi,vorbis_dsp_state *vd,
01776 float **lappcm,int lapsize){
01777 int lapcount=0,i;
01778 float **pcm;
01779
01780
01781 while(lapcount<lapsize){
01782 int samples=vorbis_synthesis_pcmout(vd,&pcm);
01783 if(samples){
01784 if(samples>lapsize-lapcount)samples=lapsize-lapcount;
01785 for(i=0;i<vi->channels;i++)
01786 memcpy(lappcm[i]+lapcount,pcm[i],sizeof(**pcm)*samples);
01787 lapcount+=samples;
01788 vorbis_synthesis_read(vd,samples);
01789 }else{
01790
01791 int ret=_fetch_and_process_packet(vf,NULL,1,0);
01792 if(ret==OV_EOF)break;
01793 }
01794 }
01795 if(lapcount<lapsize){
01796
01797
01798
01799 int samples=vorbis_synthesis_lapout(&vf->vd,&pcm);
01800 if(samples==0){
01801 for(i=0;i<vi->channels;i++)
01802 memset(lappcm[i]+lapcount,0,sizeof(**pcm)*lapsize-lapcount);
01803 lapcount=lapsize;
01804 }else{
01805 if(samples>lapsize-lapcount)samples=lapsize-lapcount;
01806 for(i=0;i<vi->channels;i++)
01807 memcpy(lappcm[i]+lapcount,pcm[i],sizeof(**pcm)*samples);
01808 lapcount+=samples;
01809 }
01810 }
01811 }
01812
01813
01814
01815 int ov_crosslap(OggVorbis_File *vf1, OggVorbis_File *vf2){
01816 vorbis_info *vi1,*vi2;
01817 float **lappcm;
01818 float **pcm;
01819 float *w1,*w2;
01820 int n1,n2,i,ret,hs1,hs2;
01821
01822 if(vf1==vf2)return(0);
01823 if(vf1->ready_state<OPENED)return(OV_EINVAL);
01824 if(vf2->ready_state<OPENED)return(OV_EINVAL);
01825
01826
01827
01828
01829
01830 ret=_ov_initset(vf1);
01831 if(ret)return(ret);
01832 ret=_ov_initprime(vf2);
01833 if(ret)return(ret);
01834
01835 vi1=ov_info(vf1,-1);
01836 vi2=ov_info(vf2,-1);
01837 hs1=ov_halfrate_p(vf1);
01838 hs2=ov_halfrate_p(vf2);
01839
01840 lappcm=alloca(sizeof(*lappcm)*vi1->channels);
01841 n1=vorbis_info_blocksize(vi1,0)>>(1+hs1);
01842 n2=vorbis_info_blocksize(vi2,0)>>(1+hs2);
01843 w1=vorbis_window(&vf1->vd,0);
01844 w2=vorbis_window(&vf2->vd,0);
01845
01846 for(i=0;i<vi1->channels;i++)
01847 lappcm[i]=alloca(sizeof(**lappcm)*n1);
01848
01849 _ov_getlap(vf1,vi1,&vf1->vd,lappcm,n1);
01850
01851
01852
01853
01854 vorbis_synthesis_lapout(&vf2->vd,&pcm);
01855 _analysis_output_always("pcmL",0,pcm[0],n1*2,0,0,0);
01856 _analysis_output_always("pcmR",0,pcm[1],n1*2,0,0,0);
01857
01858
01859 _ov_splice(pcm,lappcm,n1,n2,vi1->channels,vi2->channels,w1,w2);
01860
01861
01862 return(0);
01863 }
01864
01865 static int _ov_64_seek_lap(OggVorbis_File *vf,ogg_int64_t pos,
01866 int (*localseek)(OggVorbis_File *,ogg_int64_t)){
01867 vorbis_info *vi;
01868 float **lappcm;
01869 float **pcm;
01870 float *w1,*w2;
01871 int n1,n2,ch1,ch2,hs;
01872 int i,ret;
01873
01874 if(vf->ready_state<OPENED)return(OV_EINVAL);
01875 ret=_ov_initset(vf);
01876 if(ret)return(ret);
01877 vi=ov_info(vf,-1);
01878 hs=ov_halfrate_p(vf);
01879
01880 ch1=vi->channels;
01881 n1=vorbis_info_blocksize(vi,0)>>(1+hs);
01882 w1=vorbis_window(&vf->vd,0);
01883
01884
01885
01886
01887 lappcm=alloca(sizeof(*lappcm)*ch1);
01888 for(i=0;i<ch1;i++)
01889 lappcm[i]=alloca(sizeof(**lappcm)*n1);
01890 _ov_getlap(vf,vi,&vf->vd,lappcm,n1);
01891
01892
01893 ret=localseek(vf,pos);
01894 if(ret)return ret;
01895 ret=_ov_initprime(vf);
01896 if(ret)return(ret);
01897
01898
01899 vi=ov_info(vf,-1);
01900 ch2=vi->channels;
01901 n2=vorbis_info_blocksize(vi,0)>>(1+hs);
01902 w2=vorbis_window(&vf->vd,0);
01903
01904
01905 vorbis_synthesis_lapout(&vf->vd,&pcm);
01906
01907
01908 _ov_splice(pcm,lappcm,n1,n2,ch1,ch2,w1,w2);
01909
01910
01911 return(0);
01912 }
01913
01914 int ov_raw_seek_lap(OggVorbis_File *vf,ogg_int64_t pos){
01915 return _ov_64_seek_lap(vf,pos,ov_raw_seek);
01916 }
01917
01918 int ov_pcm_seek_lap(OggVorbis_File *vf,ogg_int64_t pos){
01919 return _ov_64_seek_lap(vf,pos,ov_pcm_seek);
01920 }
01921
01922 int ov_pcm_seek_page_lap(OggVorbis_File *vf,ogg_int64_t pos){
01923 return _ov_64_seek_lap(vf,pos,ov_pcm_seek_page);
01924 }
01925
01926 static int _ov_d_seek_lap(OggVorbis_File *vf,double pos,
01927 int (*localseek)(OggVorbis_File *,double)){
01928 vorbis_info *vi;
01929 float **lappcm;
01930 float **pcm;
01931 float *w1,*w2;
01932 int n1,n2,ch1,ch2,hs;
01933 int i,ret;
01934
01935 if(vf->ready_state<OPENED)return(OV_EINVAL);
01936 ret=_ov_initset(vf);
01937 if(ret)return(ret);
01938 vi=ov_info(vf,-1);
01939 hs=ov_halfrate_p(vf);
01940
01941 ch1=vi->channels;
01942 n1=vorbis_info_blocksize(vi,0)>>(1+hs);
01943 w1=vorbis_window(&vf->vd,0);
01944
01945
01946
01947
01948 lappcm=alloca(sizeof(*lappcm)*ch1);
01949 for(i=0;i<ch1;i++)
01950 lappcm[i]=alloca(sizeof(**lappcm)*n1);
01951 _ov_getlap(vf,vi,&vf->vd,lappcm,n1);
01952
01953
01954 ret=localseek(vf,pos);
01955 if(ret)return ret;
01956 ret=_ov_initprime(vf);
01957 if(ret)return(ret);
01958
01959
01960 vi=ov_info(vf,-1);
01961 ch2=vi->channels;
01962 n2=vorbis_info_blocksize(vi,0)>>(1+hs);
01963 w2=vorbis_window(&vf->vd,0);
01964
01965
01966 vorbis_synthesis_lapout(&vf->vd,&pcm);
01967
01968
01969 _ov_splice(pcm,lappcm,n1,n2,ch1,ch2,w1,w2);
01970
01971
01972 return(0);
01973 }
01974
01975 int ov_time_seek_lap(OggVorbis_File *vf,double pos){
01976 return _ov_d_seek_lap(vf,pos,ov_time_seek);
01977 }
01978
01979 int ov_time_seek_page_lap(OggVorbis_File *vf,double pos){
01980 return _ov_d_seek_lap(vf,pos,ov_time_seek_page);
01981 }