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