Quake II RTX doxygen  1.0 dev
ogg.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or modify
3  * it under the terms of the GNU General Public License as published by
4  * the Free Software Foundation; either version 2 of the License, or (at
5  * your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful, but
8  * WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10  *
11  * See the GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
16  * USA.
17  *
18  * =======================================================================
19  *
20  * This file implements an interface to libvorbis for decoding
21  * OGG/Vorbis files. Strongly spoken this file isn't part of the sound
22  * system but part of the main client. It justs converts Vorbis streams
23  * into normal, raw Wave stream which are injected into the backends as
24  * if they were normal "raw" samples. At this moment only background
25  * music playback and in theory .cin movie file playback is supported.
26  *
27  * =======================================================================
28  */
29 
30 // This file has been adapted from Yamagi Quake 2:
31 // https://github.com/yquake2/yquake2/blob/master/src/client/sound/ogg.c
32 
33 #ifndef _WIN32
34 #include <sys/time.h>
35 #endif
36 
37 #include <errno.h>
38 
39 #include "shared/shared.h"
40 #include "sound.h"
41 #include "client/sound/vorbis.h"
42 
43 #define STB_VORBIS_NO_PUSHDATA_API
44 #include "stb_vorbis.c"
45 
46 static cvar_t *ogg_shuffle; /* Shuffle playback */
47 static cvar_t *ogg_ignoretrack0; /* Toggle track 0 playing */
48 static cvar_t *ogg_volume; /* Music volume. */
49 static cvar_t* ogg_enable; /* Music enable flag to toggle from the menu. */
50 static int ogg_curfile; /* Index of currently played file. */
51 static int ogg_numbufs; /* Number of buffers for OpenAL */
52 static int ogg_numsamples; /* Number of sambles read from the current file */
53 static ogg_status_t ogg_status; /* Status indicator. */
54 static stb_vorbis *ogg_file; /* Ogg Vorbis file. */
55 static qboolean ogg_started; /* Initialization flag. */
56 
57 enum { MAX_NUM_OGGTRACKS = 32 };
59 static int ogg_maxfileindex;
60 
61 
62 enum GameType {
63  other, // incl. baseq2
66 };
67 
68 struct {
69  qboolean saved;
70  int curfile;
73 
74 // --------
75 
76 /*
77  * The GOG version of Quake2 has the music tracks in music/TrackXX.ogg
78  * That music/ dir is next to baseq2/ (not in it) and contains Track02.ogg to Track21.ogg
79  * There
80  * - Track02 to Track11 correspond to Quake2 (baseq2) CD tracks 2-11
81  * - Track12 to Track21 correspond to the Ground Zero (rogue) addon's CD tracks 2-11
82  * - The "The Reckoning" (xatrix) addon also had 11 tracks, that were a mix of the ones
83  * from the main game (baseq2) and the rogue addon.
84  * See below how the CD track is mapped to GOG track numbers
85  */
86 static int getMappedGOGtrack(int track, enum GameType gameType)
87 {
88  if(track <= 0)
89  return 0;
90 
91  if(track == 1)
92  return 0; // 1 is illegal (=> data track on CD), 0 means "no track"
93 
94  if(gameType == other)
95  return track;
96  if(gameType == rogue)
97  return track + 10;
98 
99  // apparently it's xatrix => map the track to the corresponding TrackXX.ogg from GOG
100  switch(track)
101  {
102  case 2: return 9; // baseq2 9
103  case 3: return 13; // rogue 3
104  case 4: return 14; // rogue 4
105  case 5: return 7; // baseq2 6
106  case 6: return 16; // rogue 6
107  case 7: return 2; // baseq2 2
108  case 8: return 15; // rogue 5
109  case 9: return 3; // baseq2 3
110  case 10: return 4; // baseq2 4
111  case 11: return 18; // rogue 8
112  default:
113  return track;
114  }
115 }
116 
117 /*
118  * Load list of Ogg Vorbis files in "music/".
119  */
120 void
122 {
123  for (int i=0; i<MAX_NUM_OGGTRACKS; ++i)
124  {
125  if (ogg_tracks[i] != NULL)
126  {
127  free(ogg_tracks[i]);
128  ogg_tracks[i] = NULL;
129  }
130  }
131 
132  ogg_maxfileindex = 0;
133 
134  const char* potMusicDirs[3] = {0};
135  char gameMusicDir[MAX_QPATH] = {0}; // e.g. "xatrix/music"
136  cvar_t* gameCvar = Cvar_Get("game", "", CVAR_LATCH | CVAR_SERVERINFO);
137 
138  potMusicDirs[0] = "music/"; // $mod/music/
139  potMusicDirs[1] = "../music/"; // global music dir (GOG)
140  potMusicDirs[2] = "../" BASEGAME "/music/"; // baseq2/music/
141 
142  enum GameType gameType = other;
143 
144  if (strcmp("xatrix", gameCvar->string) == 0)
145  {
146  gameType = xatrix;
147  }
148  else if (strcmp("rogue", gameCvar->string) == 0)
149  {
150  gameType = rogue;
151  }
152 
153  for (int potMusicDirIdx = 0; potMusicDirIdx < sizeof(potMusicDirs)/sizeof(potMusicDirs[0]); ++potMusicDirIdx)
154  {
155  const char* musicDir = potMusicDirs[potMusicDirIdx];
156 
157  if (musicDir == NULL)
158  {
159  break;
160  }
161 
162  char fullMusicPath[MAX_OSPATH] = {0};
163  snprintf(fullMusicPath, MAX_OSPATH, "%s/%s", fs_gamedir, musicDir);
164 
165  if(!Sys_IsDir(fullMusicPath))
166  {
167  continue;
168  }
169 
170  char testFileName[MAX_OSPATH];
171  char testFileName2[MAX_OSPATH];
172 
173  // the simple case (like before: $mod/music/02.ogg - 11.ogg or whatever)
174  snprintf(testFileName, MAX_OSPATH, "%s02.ogg", fullMusicPath);
175 
176  if(Sys_IsFile(testFileName))
177  {
178  ogg_tracks[2] = strdup(testFileName);
179 
180  for(int i=3; i<MAX_NUM_OGGTRACKS; ++i)
181  {
182  snprintf(testFileName, MAX_OSPATH, "%s%02i.ogg", fullMusicPath, i);
183 
184  if(Sys_IsFile(testFileName))
185  {
186  ogg_tracks[i] = strdup(testFileName);
187  ogg_maxfileindex = i;
188  }
189  }
190 
191  return;
192  }
193 
194  // the GOG case: music/Track02.ogg to Track21.ogg
195  int gogTrack = getMappedGOGtrack(8, gameType);
196 
197  snprintf(testFileName, MAX_OSPATH, "%sTrack%02i.ogg", fullMusicPath, gogTrack); // uppercase T
198  snprintf(testFileName2, MAX_OSPATH, "%strack%02i.ogg", fullMusicPath, gogTrack); // lowercase t
199 
200  if(Sys_IsFile(testFileName) || Sys_IsFile(testFileName2))
201  {
202  for(int i=2; i<MAX_NUM_OGGTRACKS; ++i)
203  {
204  int gogTrack = getMappedGOGtrack(i, gameType);
205 
206  snprintf(testFileName, MAX_OSPATH, "%sTrack%02i.ogg", fullMusicPath, gogTrack); // uppercase T
207  snprintf(testFileName2, MAX_OSPATH, "%strack%02i.ogg", fullMusicPath, gogTrack); // lowercase t
208 
209  if(Sys_IsFile(testFileName))
210  {
211  ogg_tracks[i] = strdup(testFileName);
212  ogg_maxfileindex = i;
213  }
214  else if (Sys_IsFile(testFileName2))
215  {
216  ogg_tracks[i] = strdup(testFileName2);
217  ogg_maxfileindex = i;
218  }
219  }
220 
221  return;
222  }
223  }
224 
225  // if tracks have been found above, we would've returned there
226  Com_Printf("No Ogg Vorbis music tracks have been found, so there will be no music.\n");
227 }
228 
229 // --------
230 
231 /*
232  * Play a portion of the currently opened file.
233  */
234 void
235 static OGG_Read(void)
236 {
237  short samples[4096] = {0};
238 
239  int read_samples = stb_vorbis_get_samples_short_interleaved(ogg_file, ogg_file->channels, samples,
240  sizeof(samples) / ogg_file->channels);
241 
242  if (read_samples > 0)
243  {
244  ogg_numsamples += read_samples;
245 
246  S_RawSamples(read_samples, ogg_file->sample_rate, ogg_file->channels, ogg_file->channels,
247  (byte *)samples, S_GetLinearVolume(ogg_volume->value));
248  }
249  else
250  {
251  // We cannot call OGG_Stop() here. It flushes the OpenAL sample
252  // queue, thus about 12 seconds of music are lost. Instead we
253  // just set the OGG state to stop and open a new file. The new
254  // files content is added to the sample queue after the remaining
255  // samples from the old file.
256  stb_vorbis_close(ogg_file);
257  ogg_status = STOP;
258  ogg_numbufs = 0;
259  ogg_numsamples = 0;
260 
262  }
263 }
264 
265 /*
266  * Stream music.
267  */
268 void
270 {
271  if (!ogg_started)
272  {
273  return;
274  }
275 
276  if (ogg_status == PLAY)
277  {
278 #ifdef USE_OPENAL
279  if (s_started == SS_OAL)
280  {
281  /* Calculate the number of buffers used
282  for storing decoded OGG/Vorbis data.
283  We take the number of active buffers
284  and add 256. 256 are about 12 seconds
285  worth of sound, more than enough to
286  be resilent against underruns. */
287  if (ogg_numbufs == 0 || active_buffers < ogg_numbufs - 256)
288  {
289  ogg_numbufs = active_buffers + 256;
290  }
291 
292  /* active_buffers are all active OpenAL buffers,
293  buffering normal sfx _and_ ogg/vorbis samples. */
294  while (active_buffers <= ogg_numbufs)
295  {
296  OGG_Read();
297  }
298  }
299  else /* using SDL */
300 #endif
301  {
302  if (s_started == SS_DMA)
303  {
304  /* Read that number samples into the buffer, that
305  were played since the last call to this function.
306  This keeps the buffer at all times at an "optimal"
307  fill level. */
308  while (paintedtime + S_MAX_RAW_SAMPLES - 2048 > s_rawend)
309  {
310  OGG_Read();
311  }
312  }
313  }
314  }
315 }
316 
317 // --------
318 
319 /*
320  * play the ogg file that corresponds to the CD track with the given number
321  */
322 void
323 OGG_PlayTrack(int trackNo)
324 {
325  if (s_started == SS_NOT)
326  return;
327 
328  // Track 0 means "stop music".
329  if(trackNo == 0)
330  {
331  if(ogg_ignoretrack0->value == 0)
332  {
333  OGG_Stop();
334  }
335 
336  // Special case: If ogg_ignoretrack0 is 0 we stopped the music (see above)
337  // and ogg_curfile is still holding the last track played (track >1). So
338  // this triggers and we return. If ogg_ignoretrack is 1 we didn't stop the
339  // music, as soon as the tracks ends OGG_Read() starts it over. Until here
340  // everything's okay.
341  // But if ogg_ignoretrack0 is 1, the game was just restarted and a save game
342  // load send us trackNo 0, we would end up without music. Since we have no
343  // way to get the last track before trackNo 0 was set just fall through and
344  // shuffle a random track (see below).
345  if (ogg_curfile > 0)
346  {
347  return;
348  }
349  }
350 
351  // Player has requested shuffle playback.
352  if((trackNo == 0) || ogg_shuffle->value)
353  {
354  if(ogg_maxfileindex > 0)
355  {
356  trackNo = rand() % (ogg_maxfileindex+1);
357  int retries = 100;
358  while(ogg_tracks[trackNo] == NULL && retries-- > 0)
359  {
360  trackNo = rand() % (ogg_maxfileindex+1);
361  }
362  }
363  }
364 
365  if(ogg_maxfileindex == 0)
366  {
367  return; // no ogg files at all, ignore this silently instead of printing warnings all the time
368  }
369 
370  if ((trackNo < 2) || (trackNo > ogg_maxfileindex))
371  {
372  Com_Printf("OGG_PlayTrack: %d out of range.\n", trackNo);
373  return;
374  }
375 
376  if(ogg_tracks[trackNo] == NULL)
377  {
378  Com_Printf("OGG_PlayTrack: Don't have a .ogg file for track %d\n", trackNo);
379  }
380 
381  /* Check running music. */
382  if (ogg_status == PLAY)
383  {
384  if (ogg_curfile == trackNo)
385  {
386  return;
387  }
388  else
389  {
390  OGG_Stop();
391  }
392  }
393 
394  if (ogg_tracks[trackNo] == NULL)
395  {
396  Com_Printf("OGG_PlayTrack: I don't have a file for track %d!\n", trackNo);
397 
398  return;
399  }
400 
401  /* Open ogg vorbis file. */
402  FILE* f = fopen(ogg_tracks[trackNo], "rb");
403 
404  if (f == NULL)
405  {
406  Com_Printf("OGG_PlayTrack: could not open file %s for track %d: %s.\n", ogg_tracks[trackNo], trackNo, strerror(errno));
407  ogg_tracks[trackNo] = NULL;
408 
409  return;
410  }
411 
412  int res = 0;
413  ogg_file = stb_vorbis_open_file(f, qtrue, &res, NULL);
414 
415  if (res != 0)
416  {
417  Com_Printf("OGG_PlayTrack: '%s' is not a valid Ogg Vorbis file (error %i).\n", ogg_tracks[trackNo], res);
418  fclose(f);
419 
420  return;
421  }
422 
423  /* Play file. */
424  ogg_curfile = trackNo;
425  ogg_numsamples = 0;
426  if (ogg_enable->integer)
427  ogg_status = PLAY;
428  else
429  ogg_status = PAUSE;
430 }
431 
432 // ----
433 
434 /*
435  * List Ogg Vorbis files and print current playback state.
436  */
437 static void
438 OGG_Info(void)
439 {
440  Com_Printf("Tracks:\n");
441  int numFiles = 0;
442 
443  for (int i = 2; i <= ogg_maxfileindex; i++)
444  {
445  if(ogg_tracks[i])
446  {
447  Com_Printf(" - %02d %s\n", i, ogg_tracks[i]);
448  ++numFiles;
449  }
450  else
451  {
452  Com_Printf(" - %02d <none>\n", i);
453  }
454  }
455 
456  Com_Printf("Total: %d Ogg/Vorbis files.\n", ogg_maxfileindex+1);
457 
458  switch (ogg_status)
459  {
460  case PLAY:
461  Com_Printf("State: Playing file %d (%s) at %i samples.\n",
462  ogg_curfile, ogg_tracks[ogg_curfile], stb_vorbis_get_sample_offset(ogg_file));
463  break;
464 
465  case PAUSE:
466  Com_Printf("State: Paused file %d (%s) at %i samples.\n",
467  ogg_curfile, ogg_tracks[ogg_curfile], stb_vorbis_get_sample_offset(ogg_file));
468  break;
469 
470  case STOP:
471  if (ogg_curfile == -1)
472  {
473  Com_Printf("State: Stopped.\n");
474  }
475  else
476  {
477  Com_Printf("State: Stopped file %d (%s).\n", ogg_curfile, ogg_tracks[ogg_curfile]);
478  }
479 
480  break;
481  }
482 }
483 
484 /*
485  * Stop playing the current file.
486  */
487 void
488 OGG_Stop(void)
489 {
490  if (ogg_status == STOP)
491  {
492  return;
493  }
494 
495 #ifdef USE_OPENAL
496  if (s_started == SS_OAL)
497  {
499  }
500 #endif
501 
502  stb_vorbis_close(ogg_file);
503  ogg_status = STOP;
504  ogg_numbufs = 0;
505 }
506 
507 /*
508  * Pause or resume playback.
509  */
510 static void
512 {
513  if (ogg_status == PLAY)
514  {
515  ogg_status = PAUSE;
516  ogg_numbufs = 0;
517 
518 #ifdef USE_OPENAL
519  if (s_started == SS_OAL)
520  {
522  }
523 #endif
524  }
525  else if (ogg_status == PAUSE)
526  {
527  ogg_status = PLAY;
528  }
529 }
530 
531 /*
532  * Prints a help message for the 'ogg' cmd.
533  */
534 void
536 {
537  Com_Printf("Unknown sub command %s\n\n", Cmd_Argv(1));
538  Com_Printf("Commands:\n");
539  Com_Printf(" - info: Print information about playback state and tracks\n");
540  Com_Printf(" - play <track>: Play track number <track>\n");
541  Com_Printf(" - stop: Stop playback\n");
542  Com_Printf(" - toggle: Toggle pause\n");
543 }
544 
545 /*
546  * The 'ogg' cmd. Gives some control and information about the playback state.
547  */
548 void
549 OGG_Cmd(void)
550 {
551  if (Cmd_Argc() < 2)
552  {
553  OGG_HelpMsg();
554  return;
555  }
556 
557  if (Q_stricmp(Cmd_Argv(1), "info") == 0)
558  {
559  OGG_Info();
560  }
561  else if (Q_stricmp(Cmd_Argv(1), "play") == 0)
562  {
563  if (Cmd_Argc() != 3)
564  {
565  Com_Printf("ogg play <track> : Play <track>");
566  return;
567  }
568 
569  int track = (int)strtol(Cmd_Argv(2), NULL, 10);
570 
571  if (track < 2 || track > ogg_maxfileindex)
572  {
573  Com_Printf("invalid track %s, must be an number between 2 and %d\n", Cmd_Argv(1), ogg_maxfileindex);
574  return;
575  }
576  else
577  {
578  OGG_PlayTrack(track);
579  }
580  }
581  else if (Q_stricmp(Cmd_Argv(1), "stop") == 0)
582  {
583  OGG_Stop();
584  }
585  else if (Q_stricmp(Cmd_Argv(1), "toggle") == 0)
586  {
588  }
589  else
590  {
591  OGG_HelpMsg();
592  }
593 }
594 
595 /*
596  * Saves the current state of the subsystem.
597  */
598 void
600 {
601  if (ogg_status != PLAY)
602  {
603  ogg_saved_state.saved = qfalse;
604 
605  return;
606  }
607 
608  ogg_saved_state.saved = qtrue;
609  ogg_saved_state.curfile = ogg_curfile;
610  ogg_saved_state.numsamples = ogg_numsamples;
611 }
612 
613 /*
614  * Recover the previously saved state.
615  */
616 void
618 {
619  if (!ogg_saved_state.saved)
620  {
621  return;
622  }
623 
624  // Mkay, ultra evil hack to recover the state in case of
625  // shuffled playback. OGG_PlayTrack() does the shuffeling,
626  // so switch it of before and enable after state recovery.
627  int shuffle_state = ogg_shuffle->value;
628  Cvar_SetValue(ogg_shuffle, 0, FROM_CODE);
629 
631  stb_vorbis_seek_frame(ogg_file, ogg_saved_state.numsamples);
632  ogg_numsamples = ogg_saved_state.numsamples;
633 
634  Cvar_SetValue(ogg_shuffle, shuffle_state, FROM_CODE);
635 }
636 
637 // --------
638 
639 static void ogg_enable_changed(cvar_t *self)
640 {
641  if (ogg_enable->integer && ogg_status == PAUSE || !ogg_enable->integer && ogg_status == PLAY)
642  {
644  }
645 }
646 
647 
648 /*
649  * Initialize the Ogg Vorbis subsystem.
650  */
651 void
652 OGG_Init(void)
653 {
654  // Cvars
655  ogg_shuffle = Cvar_Get("ogg_shuffle", "0", CVAR_ARCHIVE);
656  ogg_ignoretrack0 = Cvar_Get("ogg_ignoretrack0", "0", CVAR_ARCHIVE);
657  ogg_volume = Cvar_Get("ogg_volume", "1.0", CVAR_ARCHIVE);
658  ogg_enable = Cvar_Get("ogg_enable", "1", CVAR_ARCHIVE);
659  ogg_enable->changed = ogg_enable_changed;
660 
661  // Commands
662  Cmd_AddCommand("ogg", OGG_Cmd);
663 
664  // Global variables
665  ogg_curfile = -1;
666  ogg_numsamples = 0;
667  ogg_status = STOP;
668 
669  ogg_started = qtrue;
670 }
671 
672 /*
673  * Shutdown the Ogg Vorbis subsystem.
674  */
675 void
677 {
678  if (!ogg_started)
679  {
680  return;
681  }
682 
683  // Music must be stopped.
684  OGG_Stop();
685 
686  // Free file lsit.
687  for(int i=0; i<MAX_NUM_OGGTRACKS; ++i)
688  {
689  if(ogg_tracks[i] != NULL)
690  {
691  free(ogg_tracks[i]);
692  ogg_tracks[i] = NULL;
693  }
694  }
695  ogg_maxfileindex = 0;
696 
697  // Remove console commands
698  Cmd_RemoveCommand("ogg");
699 
700  ogg_started = qfalse;
701 }
OGG_RecoverState
void OGG_RecoverState(void)
Definition: ogg.c:617
Cmd_AddCommand
void Cmd_AddCommand(const char *name, xcommand_t function)
Definition: cmd.c:1562
Cvar_Get
cvar_t * Cvar_Get(const char *var_name, const char *var_value, int flags)
Definition: cvar.c:257
OGG_TogglePlayback
static void OGG_TogglePlayback(void)
Definition: ogg.c:511
saved
qboolean saved
Definition: ogg.c:69
ogg_tracks
static char * ogg_tracks[MAX_NUM_OGGTRACKS]
Definition: ogg.c:58
ogg_enable
static cvar_t * ogg_enable
Definition: ogg.c:49
ogg_enable_changed
static void ogg_enable_changed(cvar_t *self)
Definition: ogg.c:639
paintedtime
int paintedtime
Definition: main.c:43
other
@ other
Definition: ogg.c:63
ogg_numsamples
static int ogg_numsamples
Definition: ogg.c:52
ogg_maxfileindex
static int ogg_maxfileindex
Definition: ogg.c:59
Cmd_Argv
char * Cmd_Argv(int arg)
Definition: cmd.c:899
Cmd_Argc
int Cmd_Argc(void)
Definition: cmd.c:889
Sys_IsDir
qboolean Sys_IsDir(const char *path)
Definition: system.c:659
curfile
int curfile
Definition: ogg.c:70
AL_UnqueueRawSamples
void AL_UnqueueRawSamples()
Definition: al.c:562
ogg_shuffle
static cvar_t * ogg_shuffle
Definition: ogg.c:46
xatrix
@ xatrix
Definition: ogg.c:64
Cmd_RemoveCommand
void Cmd_RemoveCommand(const char *name)
Definition: cmd.c:1593
rogue
@ rogue
Definition: ogg.c:65
OGG_Read
static void OGG_Read(void)
Definition: ogg.c:235
ogg_status
static ogg_status_t ogg_status
Definition: ogg.c:53
Cvar_SetValue
void Cvar_SetValue(cvar_t *var, float value, from_t from)
Definition: cvar.c:487
ogg_numbufs
static int ogg_numbufs
Definition: ogg.c:51
Sys_IsFile
qboolean Sys_IsFile(const char *path)
Definition: system.c:674
ogg_volume
static cvar_t * ogg_volume
Definition: ogg.c:48
OGG_PlayTrack
void OGG_PlayTrack(int trackNo)
Definition: ogg.c:323
ogg_ignoretrack0
static cvar_t * ogg_ignoretrack0
Definition: ogg.c:47
OGG_HelpMsg
void OGG_HelpMsg(void)
Definition: ogg.c:535
ogg_file
static stb_vorbis * ogg_file
Definition: ogg.c:54
OGG_Stop
void OGG_Stop(void)
Definition: ogg.c:488
OGG_Stream
void OGG_Stream(void)
Definition: ogg.c:269
s_rawend
int s_rawend
Definition: mix.c:28
OGG_Shutdown
void OGG_Shutdown(void)
Definition: ogg.c:676
numsamples
int numsamples
Definition: ogg.c:71
MAX_NUM_OGGTRACKS
@ MAX_NUM_OGGTRACKS
Definition: ogg.c:57
OGG_Init
void OGG_Init(void)
Definition: ogg.c:652
samples
unsigned samples[LAG_WIDTH]
Definition: screen.c:528
S_MAX_RAW_SAMPLES
#define S_MAX_RAW_SAMPLES
Definition: sound.h:154
OGG_Cmd
void OGG_Cmd(void)
Definition: ogg.c:549
S_GetLinearVolume
float S_GetLinearVolume(float perceptual)
Definition: main.c:1171
ogg_started
static qboolean ogg_started
Definition: ogg.c:55
getMappedGOGtrack
static int getMappedGOGtrack(int track, enum GameType gameType)
Definition: ogg.c:86
GameType
GameType
Definition: ogg.c:62
s_started
sndstarted_t s_started
Definition: main.c:32
int
CONST PIXELFORMATDESCRIPTOR int
Definition: wgl.c:26
fs_gamedir
char fs_gamedir[MAX_OSPATH]
Definition: files.c:171
sound.h
OGG_InitTrackList
void OGG_InitTrackList(void)
Definition: ogg.c:121
OGG_Info
static void OGG_Info(void)
Definition: ogg.c:438
OGG_SaveState
void OGG_SaveState(void)
Definition: ogg.c:599
ogg_saved_state
struct @7 ogg_saved_state
S_RawSamples
void S_RawSamples(int samples, int rate, int width, int channels, byte *data, float volume)
Definition: mix.c:303
active_buffers
int active_buffers
Definition: al.c:34
ogg_curfile
static int ogg_curfile
Definition: ogg.c:50