DarkPlaces
Game engine based on the Quake 1 engine by id Software, developed by LadyHavoc
 
snd_ogg.c
Go to the documentation of this file.
1/*
2 Copyright (C) 2003-2005 Mathieu Olivier
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to:
17
18 Free Software Foundation, Inc.
19 59 Temple Place - Suite 330
20 Boston, MA 02111-1307, USA
21
22*/
23
24
25#include "darkplaces.h"
26#include "snd_main.h"
27#include "snd_ogg.h"
28#include "snd_wav.h"
29#include "sound.h"
30
31#ifdef LINK_TO_LIBVORBIS
32#define OV_EXCLUDE_STATIC_CALLBACKS
33#include <ogg/ogg.h>
34#include <vorbis/vorbisfile.h>
35
36#define qov_clear ov_clear
37#define qov_info ov_info
38#define qov_comment ov_comment
39#define qov_open_callbacks ov_open_callbacks
40#define qov_pcm_seek ov_pcm_seek
41#define qov_pcm_total ov_pcm_total
42#define qov_read ov_read
43#define qvorbis_comment_query vorbis_comment_query
44
45qbool OGG_OpenLibrary (void) {return true;}
46void OGG_CloseLibrary (void) {}
47#else
48
49/*
50=================================================================
51
52 Minimal set of definitions from the Ogg Vorbis lib
53 (C) COPYRIGHT 1994-2001 by the XIPHOPHORUS Company
54 http://www.xiph.org/
55
56 WARNING: for a matter of simplicity, several pointer types are
57 casted to "void*", and most enumerated values are not included
58
59=================================================================
60*/
61
62typedef struct
63{
64 size_t (*read_func) (void *ptr, size_t size, size_t nmemb, void *datasource);
65 int (*seek_func) (void *datasource, int64_t offset, int whence);
66 int (*close_func) (void *datasource);
67 long (*tell_func) (void *datasource);
69
70typedef struct
71{
72 unsigned char *data;
73 int storage;
74 int fill;
75 int returned;
76 int unsynced;
77 int headerbytes;
78 int bodybytes;
80
81typedef struct
82{
83 int version;
84 int channels;
85 long rate;
86 long bitrate_upper;
87 long bitrate_nominal;
88 long bitrate_lower;
89 long bitrate_window;
90 void *codec_setup;
92
93typedef struct
94{
95 unsigned char *body_data;
96 long body_storage;
97 long body_fill;
98 long body_returned;
99 int *lacing_vals;
100 int64_t *granule_vals;
101 long lacing_storage;
102 long lacing_fill;
103 long lacing_packet;
104 long lacing_returned;
105 unsigned char header[282];
106 int header_fill;
107 int e_o_s;
108 int b_o_s;
109 long serialno;
110 long pageno;
111 int64_t packetno;
112 int64_t granulepos;
114
115typedef struct
116{
117 int analysisp;
118 vorbis_info *vi;
119 float **pcm;
120 float **pcmret;
121 int pcm_storage;
122 int pcm_current;
123 int pcm_returned;
124 int preextrapolate;
125 int eofflag;
126 long lW;
127 long W;
128 long nW;
129 long centerW;
130 int64_t granulepos;
131 int64_t sequence;
132 int64_t glue_bits;
133 int64_t time_bits;
134 int64_t floor_bits;
135 int64_t res_bits;
136 void *backend_state;
138
139typedef struct
140{
141 long endbyte;
142 int endbit;
143 unsigned char *buffer;
144 unsigned char *ptr;
145 long storage;
147
148typedef struct
149{
150 float **pcm;
151 oggpack_buffer opb;
152 long lW;
153 long W;
154 long nW;
155 int pcmend;
156 int mode;
157 int eofflag;
158 int64_t granulepos;
159 int64_t sequence;
161 void *localstore;
162 long localtop;
163 long localalloc;
164 long totaluse;
165 void *reap; // VOIDED POINTER
166 long glue_bits;
167 long time_bits;
168 long floor_bits;
169 long res_bits;
170 void *internal;
172
173typedef struct
174{
175 char **user_comments;
176 int *comment_lengths;
177 int comments;
178 char *vendor;
180
206
207
208/*
209=================================================================
210
211 DarkPlaces definitions
212
213=================================================================
214*/
215
216// Functions exported from the vorbisfile library
218static vorbis_info* (*qov_info) (OggVorbis_File *vf,int link);
219static vorbis_comment* (*qov_comment) (OggVorbis_File *vf,int link);
220static char * (*qvorbis_comment_query) (vorbis_comment *vc, const char *tag, int count);
221static int (*qov_open_callbacks) (void *datasource, OggVorbis_File *vf,
222 char *initial, long ibytes,
224static int (*qov_pcm_seek) (OggVorbis_File *vf,int64_t pos);
225static int64_t (*qov_pcm_total) (OggVorbis_File *vf,int i);
226static long (*qov_read) (OggVorbis_File *vf,char *buffer,int length,
227 int bigendianp,int word,int sgned,int *bitstream);
228
230{
231 {"ov_clear", (void **) &qov_clear},
232 {"ov_info", (void **) &qov_info},
233 {"ov_comment", (void **) &qov_comment},
234 {"ov_open_callbacks", (void **) &qov_open_callbacks},
235 {"ov_pcm_seek", (void **) &qov_pcm_seek},
236 {"ov_pcm_total", (void **) &qov_pcm_total},
237 {"ov_read", (void **) &qov_read},
238 {NULL, NULL}
239};
240
242{
243 {"vorbis_comment_query", (void **) &qvorbis_comment_query},
244 {NULL, NULL}
245};
246
247// Handles for the Vorbis and Vorbisfile DLLs
250
251
252/*
253=================================================================
254
255 DLL load & unload
256
257=================================================================
258*/
259
260/*
261====================
262OGG_OpenLibrary
263
264Try to load the VorbisFile DLL
265====================
266*/
268{
269 const char* dllnames_vo [] =
270 {
271#if defined(WIN32)
272 "libvorbis-0.dll",
273 "libvorbis.dll",
274 "vorbis.dll",
275#elif defined(MACOSX)
276 "libvorbis.dylib",
277#else
278 "libvorbis.so.0",
279 "libvorbis.so",
280#endif
281 NULL
282 };
283 const char* dllnames_vf [] =
284 {
285#if defined(WIN32)
286 "libvorbisfile-3.dll",
287 "libvorbisfile.dll",
288 "vorbisfile.dll",
289#elif defined(MACOSX)
290 "libvorbisfile.dylib",
291#else
292 "libvorbisfile.so.3",
293 "libvorbisfile.so",
294#endif
295 NULL
296 };
297
298 // Already loaded?
299 if (vf_dll)
300 return true;
301
302// COMMANDLINEOPTION: Sound: -novorbis disables ogg vorbis sound support
303 if (Sys_CheckParm("-novorbis"))
304 return false;
305
306 // Load the DLLs
307 // We need to load both by hand because some OSes seem to not load
308 // the vorbis DLL automatically when loading the VorbisFile DLL
309 return Sys_LoadDependency (dllnames_vo, &vo_dll, vorbisfuncs) && Sys_LoadDependency (dllnames_vf, &vf_dll, vorbisfilefuncs);
310}
311
312
313/*
314====================
315OGG_CloseLibrary
316
317Unload the VorbisFile DLL
318====================
319*/
321{
324}
325
326#endif
327
328/*
329=================================================================
330
331 Ogg Vorbis decoding
332
333=================================================================
334*/
335
336typedef struct
337{
338 unsigned char *buffer;
339 int64_t ind, buffsize;
341
342static size_t ovcb_read (void *ptr, size_t size, size_t nb, void *datasource)
343{
344 ov_decode_t *ov_decode = (ov_decode_t*)datasource;
345 size_t remain, len;
346
347 remain = ov_decode->buffsize - ov_decode->ind;
348 len = size * nb;
349 if (remain < len)
350 len = remain - remain % size;
351
352 memcpy (ptr, ov_decode->buffer + ov_decode->ind, len);
353 ov_decode->ind += len;
354
355 return len / size;
356}
357
358static int ovcb_seek (void *datasource, int64_t offset, int whence)
359{
360 ov_decode_t *ov_decode = (ov_decode_t*)datasource;
361
362 switch (whence)
363 {
364 case SEEK_SET:
365 break;
366 case SEEK_CUR:
367 offset += ov_decode->ind;
368 break;
369 case SEEK_END:
370 offset += ov_decode->buffsize;
371 break;
372 default:
373 return -1;
374 }
375 if (offset < 0 || offset > ov_decode->buffsize)
376 return -1;
377
378 ov_decode->ind = offset;
379 return 0;
380}
381
382static int ovcb_close (void *ov_decode)
383{
384 return 0;
385}
386
387static long ovcb_tell (void *ov_decode)
388{
389 return ((ov_decode_t*)ov_decode)->ind;
390}
391
392// Per-sfx data structure
393typedef struct
394{
395 unsigned char *file;
396 size_t filesize;
398
399// Per-channel data structure
409
410
412
413/*
414====================
415OGG_GetSamplesFloat
416====================
417*/
418static void OGG_GetSamplesFloat (channel_t *ch, sfx_t *sfx, int firstsampleframe, int numsampleframes, float *outsamplesfloat)
419{
421 ogg_stream_persfx_t *per_sfx = (ogg_stream_persfx_t *)sfx->fetcher_data;
422 int f = sfx->format.width * sfx->format.channels; // bytes per frame in the buffer
423 short *buf;
424 int i, len;
425 int newlength, done, ret;
426
427 // if this channel does not yet have a channel fetcher, make one
428 if (per_ch == NULL)
429 {
430 // allocate a struct to keep track of our file position and buffer
431 per_ch = (ogg_stream_perchannel_t *)Mem_Alloc(snd_mempool, sizeof(*per_ch));
432 // begin decoding the file
433 per_ch->ov_decode.buffer = per_sfx->file;
434 per_ch->ov_decode.ind = 0;
435 per_ch->ov_decode.buffsize = per_sfx->filesize;
436 if (qov_open_callbacks(&per_ch->ov_decode, &per_ch->vf, NULL, 0, callbacks) < 0)
437 {
438 // this never happens - this function succeeded earlier on the same data
439 Mem_Free(per_ch);
440 return;
441 }
442 per_ch->bs = 0;
443 per_ch->buffer_firstframe = 0;
444 per_ch->buffer_numframes = 0;
445 // attach the struct to our channel
446 ch->fetcher_data = (void *)per_ch;
447 }
448
449 // if the request is too large for our buffer, loop...
450 while (numsampleframes * f > (int)sizeof(per_ch->buffer))
451 {
452 done = sizeof(per_ch->buffer) / f;
453 OGG_GetSamplesFloat(ch, sfx, firstsampleframe, done, outsamplesfloat);
454 firstsampleframe += done;
455 numsampleframes -= done;
456 outsamplesfloat += done * sfx->format.channels;
457 }
458
459 // seek if the request is before the current buffer (loop back)
460 // seek if the request starts beyond the current buffer by at least one frame (channel was zero volume for a while)
461 // do not seek if the request overlaps the buffer end at all (expected behavior)
462 if (per_ch->buffer_firstframe > firstsampleframe || per_ch->buffer_firstframe + per_ch->buffer_numframes < firstsampleframe)
463 {
464 // we expect to decode forward from here so this will be our new buffer start
465 per_ch->buffer_firstframe = firstsampleframe;
466 per_ch->buffer_numframes = 0;
467 ret = qov_pcm_seek(&per_ch->vf, (int64_t)firstsampleframe);
468 if (ret != 0)
469 {
470 // LadyHavoc: we can't Con_Printf here, not thread safe...
471 //Con_Printf("OGG_FetchSound: qov_pcm_seek(..., %d) returned %d\n", firstsampleframe, ret);
472 return;
473 }
474 }
475
476 // decompress the file as needed
477 if (firstsampleframe + numsampleframes > per_ch->buffer_firstframe + per_ch->buffer_numframes)
478 {
479 // first slide the buffer back, discarding any data preceding the range we care about
480 int offset = firstsampleframe - per_ch->buffer_firstframe;
481 int keeplength = per_ch->buffer_numframes - offset;
482 if (keeplength > 0)
483 memmove(per_ch->buffer, per_ch->buffer + offset * sfx->format.width * sfx->format.channels, keeplength * sfx->format.width * sfx->format.channels);
484 per_ch->buffer_firstframe = firstsampleframe;
485 per_ch->buffer_numframes -= offset;
486 // decompress as much as we can fit in the buffer
487 newlength = sizeof(per_ch->buffer) - per_ch->buffer_numframes * f;
488 done = 0;
489 while (newlength > done && (ret = qov_read(&per_ch->vf, (char *)per_ch->buffer + per_ch->buffer_numframes * f + done, (int)(newlength - done), mem_bigendian, 2, 1, &per_ch->bs)) > 0)
490 done += ret;
491 // clear the missing space if any
492 if (done < newlength)
493 memset(per_ch->buffer + done, 0, newlength - done);
494 // we now have more data in the buffer
495 per_ch->buffer_numframes += done / f;
496 }
497
498 // convert the sample format for the caller
499 buf = (short *)((char *)per_ch->buffer + (firstsampleframe - per_ch->buffer_firstframe) * f);
500 len = numsampleframes * sfx->format.channels;
501 for (i = 0;i < len;i++)
502 outsamplesfloat[i] = buf[i] * (1.0f / 32768.0f);
503}
504
505
506/*
507====================
508OGG_StopChannel
509====================
510*/
512{
514 if (per_ch != NULL)
515 {
516 // release the vorbis decompressor
517 qov_clear(&per_ch->vf);
518 Mem_Free(per_ch);
519 }
520}
521
522
523/*
524====================
525OGG_FreeSfx
526====================
527*/
528static void OGG_FreeSfx(sfx_t *sfx)
529{
530 ogg_stream_persfx_t *per_sfx = (ogg_stream_persfx_t *)sfx->fetcher_data;
531 // free the complete file we were keeping around
532 Mem_Free(per_sfx->file);
533 // free the file information structure
534 Mem_Free(per_sfx);
535}
536
537
539
540static void OGG_DecodeTags(vorbis_comment *vc, unsigned int *start, unsigned int *length, unsigned int numsamples, double *peak, double *gaindb)
541{
542 const char *startcomment = NULL, *lengthcomment = NULL, *endcomment = NULL, *thiscomment = NULL;
543
544 *start = numsamples;
545 *length = numsamples;
546 *peak = 0.0;
547 *gaindb = 0.0;
548
549 if(!vc)
550 return;
551
552 thiscomment = qvorbis_comment_query(vc, "REPLAYGAIN_TRACK_PEAK", 0);
553 if(thiscomment)
554 *peak = atof(thiscomment);
555 thiscomment = qvorbis_comment_query(vc, "REPLAYGAIN_TRACK_GAIN", 0);
556 if(thiscomment)
557 *gaindb = atof(thiscomment);
558
559 startcomment = qvorbis_comment_query(vc, "LOOP_START", 0); // DarkPlaces, and some Japanese app
560 if(startcomment)
561 {
562 endcomment = qvorbis_comment_query(vc, "LOOP_END", 0);
563 if(!endcomment)
564 lengthcomment = qvorbis_comment_query(vc, "LOOP_LENGTH", 0);
565 }
566 else
567 {
568 startcomment = qvorbis_comment_query(vc, "LOOPSTART", 0); // RPG Maker VX
569 if(startcomment)
570 {
571 lengthcomment = qvorbis_comment_query(vc, "LOOPLENGTH", 0);
572 if(!lengthcomment)
573 endcomment = qvorbis_comment_query(vc, "LOOPEND", 0);
574 }
575 else
576 {
577 startcomment = qvorbis_comment_query(vc, "LOOPPOINT", 0); // Sonic Robo Blast 2
578 }
579 }
580
581 if(startcomment)
582 {
583 *start = (unsigned int) bound(0, atof(startcomment), numsamples);
584 if(endcomment)
585 *length = (unsigned int) bound(0, atof(endcomment), numsamples);
586 else if(lengthcomment)
587 *length = (unsigned int) bound(0, *start + atof(lengthcomment), numsamples);
588 }
589}
590
591/*
592====================
593OGG_LoadVorbisFile
594
595Load an Ogg Vorbis file into memory
596====================
597*/
598qbool OGG_LoadVorbisFile(const char *filename, sfx_t *sfx)
599{
600 unsigned char *data;
601 fs_offset_t filesize;
602 ov_decode_t ov_decode;
604 vorbis_info *vi;
605 vorbis_comment *vc;
606 double peak, gaindb;
607
608#ifndef LINK_TO_LIBVORBIS
609 if (!vf_dll)
610 return false;
611#endif
612
613 // Return if already loaded
614 if (sfx->fetcher != NULL)
615 return true;
616
617 // Load the file completely
618 data = FS_LoadFile(filename, snd_mempool, false, &filesize);
619 if (data == NULL)
620 return false;
621
622 if (developer_loading.integer >= 2)
623 Con_Printf("Loading Ogg Vorbis file \"%s\"\n", filename);
624
625 // Open it with the VorbisFile API
626 ov_decode.buffer = data;
627 ov_decode.ind = 0;
628 ov_decode.buffsize = filesize;
629 if (qov_open_callbacks(&ov_decode, &vf, NULL, 0, callbacks) < 0)
630 {
631 Con_Printf("error while opening Ogg Vorbis file \"%s\"\n", filename);
632 Mem_Free(data);
633 return false;
634 }
635
636 // Get the stream information
637 vi = qov_info(&vf, -1);
638 if (vi->channels < 1 || vi->channels > 2)
639 {
640 Con_Printf("%s has an unsupported number of channels (%i)\n",
641 sfx->name, vi->channels);
642 qov_clear (&vf);
643 Mem_Free(data);
644 return false;
645 }
646
647 sfx->format.speed = vi->rate;
648 sfx->format.channels = vi->channels;
649 sfx->format.width = 2; // We always work with 16 bits samples
650
651 sfx->total_length = qov_pcm_total(&vf, -1);
652
653 if (snd_streaming.integer && (snd_streaming.integer >= 2 || sfx->total_length > max(sizeof(ogg_stream_perchannel_t), snd_streaming_length.value * sfx->format.speed)))
654 {
655 // large sounds use the OGG fetcher to decode the file on demand (but the entire file is held in memory)
656 ogg_stream_persfx_t* per_sfx;
657 if (developer_loading.integer >= 2)
658 Con_Printf("Ogg sound file \"%s\" will be streamed\n", filename);
659 per_sfx = (ogg_stream_persfx_t *)Mem_Alloc(snd_mempool, sizeof(*per_sfx));
660 sfx->memsize += sizeof (*per_sfx);
661 per_sfx->file = data;
662 per_sfx->filesize = filesize;
663 sfx->memsize += filesize;
664 sfx->fetcher_data = per_sfx;
665 sfx->fetcher = &ogg_fetcher;
666 sfx->flags |= SFXFLAG_STREAMED;
667 vc = qov_comment(&vf, -1);
668 OGG_DecodeTags(vc, &sfx->loopstart, &sfx->total_length, sfx->total_length, &peak, &gaindb);
669 qov_clear(&vf);
670 }
671 else
672 {
673 // small sounds are entirely loaded and use the PCM fetcher
674 char *buff;
675 int64_t len;
676 int64_t done;
677 int bs;
678 long ret;
679 if (developer_loading.integer >= 2)
680 Con_Printf ("Ogg sound file \"%s\" will be cached\n", filename);
681 len = sfx->total_length * sfx->format.channels * sfx->format.width;
682 sfx->flags &= ~SFXFLAG_STREAMED;
683 sfx->memsize += len;
684 sfx->fetcher = &wav_fetcher;
685 sfx->fetcher_data = Mem_Alloc(snd_mempool, (size_t)len);
686 buff = (char *)sfx->fetcher_data;
687 done = 0;
688 bs = 0;
689 while ((ret = qov_read(&vf, &buff[done], (int)(len - done), mem_bigendian, 2, 1, &bs)) > 0)
690 done += ret;
691 vc = qov_comment(&vf, -1);
692 OGG_DecodeTags(vc, &sfx->loopstart, &sfx->total_length, sfx->total_length, &peak, &gaindb);
693 qov_clear(&vf);
694 Mem_Free(data);
695 }
696
697 if(peak)
698 {
699 sfx->volume_mult = min(1.0f / peak, exp(gaindb * 0.05f * log(10.0f)));
700 sfx->volume_peak = peak;
701 if (developer_loading.integer >= 2)
702 Con_Printf ("Ogg sound file \"%s\" uses ReplayGain (gain %f, peak %f)\n", filename, sfx->volume_mult, sfx->volume_peak);
703 }
704 else if(gaindb != 0)
705 {
706 sfx->volume_mult = min(1.0f / peak, exp(gaindb * 0.05f * log(10.0f)));
707 sfx->volume_peak = 1.0; // if peak is not defined, we won't trust it
708 if (developer_loading.integer >= 2)
709 Con_Printf ("Ogg sound file \"%s\" uses ReplayGain (gain %f, peak not defined and assumed to be %f)\n", filename, sfx->volume_mult, sfx->volume_peak);
710 }
711
712 return true;
713}
void Con_Printf(const char *fmt,...)
Prints to all appropriate console targets.
Definition console.c:1514
vector size
float log(float f)
unsigned char * FS_LoadFile(const char *path, mempool_t *pool, qbool quiet, fs_offset_t *filesizepointer)
Definition fs.c:3540
static int(ZEXPORT *qz_inflate)(z_stream *strm
static int const char * version
Definition fs.c:479
int64_t fs_offset_t
Definition fs.h:37
GLenum mode
Definition glquake.h:718
GLuint buffer
Definition glquake.h:630
GLenum GLuint GLenum GLsizei length
Definition glquake.h:657
GLenum GLenum GLsizei count
Definition glquake.h:656
GLsizeiptr const GLvoid * data
Definition glquake.h:639
GLuint GLuint GLintptr offset
Definition glquake.h:632
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition glquake.h:657
cvar_t developer_loading
Definition host.c:52
#define max(A, B)
Definition mathlib.h:38
#define min(A, B)
Definition mathlib.h:37
#define bound(min, num, max)
Definition mathlib.h:34
int i
#define NULL
Definition qtypes.h:12
bool qbool
Definition qtypes.h:9
return ret
float f
mempool_t * snd_mempool
Definition snd_main.c:144
cvar_t snd_streaming
Definition snd_main.c:171
channel_t channels[MAX_CHANNELS]
Definition snd_main.c:128
cvar_t snd_streaming_length
Definition snd_main.c:172
#define STREAM_BUFFERSIZE
in sampleframes
Definition snd_main.h:150
#define SFXFLAG_STREAMED
informative only. You shouldn't need to know that
Definition snd_main.h:62
static void OGG_StopChannel(channel_t *ch)
Definition snd_ogg.c:511
qbool OGG_OpenLibrary(void)
Definition snd_ogg.c:267
static const ov_callbacks callbacks
Definition snd_ogg.c:411
static long(* qov_read)(OggVorbis_File *vf, char *buffer, int length, int bigendianp, int word, int sgned, int *bitstream)
Definition snd_ogg.c:226
static const snd_fetcher_t ogg_fetcher
Definition snd_ogg.c:538
static vorbis_info *(* qov_info)(OggVorbis_File *vf, int link)
Definition snd_ogg.c:218
static int ovcb_seek(void *datasource, int64_t offset, int whence)
Definition snd_ogg.c:358
static dllhandle_t vf_dll
Definition snd_ogg.c:249
static int ovcb_close(void *ov_decode)
Definition snd_ogg.c:382
static dllfunction_t vorbisfuncs[]
Definition snd_ogg.c:241
static long ovcb_tell(void *ov_decode)
Definition snd_ogg.c:387
static char *(* qvorbis_comment_query)(vorbis_comment *vc, const char *tag, int count)
Definition snd_ogg.c:220
static int(* qov_clear)(OggVorbis_File *vf)
Definition snd_ogg.c:217
static int(* qov_open_callbacks)(void *datasource, OggVorbis_File *vf, char *initial, long ibytes, ov_callbacks callbacks)
Definition snd_ogg.c:221
static size_t ovcb_read(void *ptr, size_t size, size_t nb, void *datasource)
Definition snd_ogg.c:342
static dllhandle_t vo_dll
Definition snd_ogg.c:248
void OGG_CloseLibrary(void)
Definition snd_ogg.c:320
static void OGG_FreeSfx(sfx_t *sfx)
Definition snd_ogg.c:528
static dllfunction_t vorbisfilefuncs[]
Definition snd_ogg.c:229
static void OGG_GetSamplesFloat(channel_t *ch, sfx_t *sfx, int firstsampleframe, int numsampleframes, float *outsamplesfloat)
Definition snd_ogg.c:418
static void OGG_DecodeTags(vorbis_comment *vc, unsigned int *start, unsigned int *length, unsigned int numsamples, double *peak, double *gaindb)
Definition snd_ogg.c:540
qbool OGG_LoadVorbisFile(const char *filename, sfx_t *sfx)
Definition snd_ogg.c:598
static int(* qov_pcm_seek)(OggVorbis_File *vf, int64_t pos)
Definition snd_ogg.c:224
static int64_t(* qov_pcm_total)(OggVorbis_File *vf, int i)
Definition snd_ogg.c:225
static vorbis_comment *(* qov_comment)(OggVorbis_File *vf, int link)
Definition snd_ogg.c:219
const snd_fetcher_t wav_fetcher
Definition snd_wav.c:260
vorbis_block vb
Definition snd_ogg.c:203
int64_t end
Definition snd_ogg.c:186
int64_t offset
Definition snd_ogg.c:185
double samptrack
Definition snd_ogg.c:200
vorbis_comment * vc
Definition snd_ogg.c:194
void * datasource
Definition snd_ogg.c:183
int64_t * dataoffsets
Definition snd_ogg.c:190
ogg_stream_state os
Definition snd_ogg.c:201
int64_t pcm_offset
Definition snd_ogg.c:195
vorbis_info * vi
Definition snd_ogg.c:193
double bittrack
Definition snd_ogg.c:199
long * serialnos
Definition snd_ogg.c:191
vorbis_dsp_state vd
Definition snd_ogg.c:202
int64_t * offsets
Definition snd_ogg.c:189
int64_t * pcmlengths
Definition snd_ogg.c:192
long current_serialno
Definition snd_ogg.c:197
ogg_sync_state oy
Definition snd_ogg.c:187
ov_callbacks callbacks
Definition snd_ogg.c:204
void * fetcher_data
Per-channel data for the sound fetching function.
Definition snd_main.h:96
float value
Definition cvar.h:74
int integer
Definition cvar.h:73
OggVorbis_File vf
Definition snd_ogg.c:402
ov_decode_t ov_decode
Definition snd_ogg.c:403
unsigned char buffer[STREAM_BUFFERSIZE *4]
Definition snd_ogg.c:407
unsigned char * file
Definition snd_ogg.c:395
int64_t buffsize
Definition snd_ogg.c:339
unsigned char * buffer
Definition snd_ogg.c:338
int64_t ind
Definition snd_ogg.c:339
void * reap
Definition snd_ogg.c:165
long rate
Definition cap_ogg.c:121
int channels
Definition cap_ogg.c:120
void * dllhandle_t
Definition sys.h:169
qbool Sys_LoadDependency(const char **dllnames, dllhandle_t *handle, const dllfunction_t *fcts)
Definition sys_shared.c:131
void Sys_FreeLibrary(dllhandle_t *handle)
Definition sys_shared.c:245
int Sys_CheckParm(const char *parm)
Definition sys_shared.c:327
qbool mem_bigendian
Definition zone.c:34
#define Mem_Free(mem)
Definition zone.h:96
#define Mem_Alloc(pool, size)
Definition zone.h:92