doom3-gpl
Doom 3 GPL source release
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
snd_shader.cpp
Go to the documentation of this file.
1 /*
2 ===========================================================================
3 
4 Doom 3 GPL Source Code
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
6 
7 This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
8 
9 Doom 3 Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13 
14 Doom 3 Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
21 
22 In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
23 
24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
25 
26 ===========================================================================
27 */
28 
29 #include "../idlib/precompiled.h"
30 #pragma hdrstop
31 
32 #include "snd_local.h"
33 
34 
35 /*
36 ===============
37 idSoundShader::Init
38 ===============
39 */
40 void idSoundShader::Init( void ) {
41  desc = "<no description>";
42  errorDuringParse = false;
43  onDemand = false;
44  numEntries = 0;
45  numLeadins = 0;
46  leadinVolume = 0;
47  altSound = NULL;
48 }
49 
50 /*
51 ===============
52 idSoundShader::idSoundShader
53 ===============
54 */
56  Init();
57 }
58 
59 /*
60 ===============
61 idSoundShader::~idSoundShader
62 ===============
63 */
65 }
66 
67 /*
68 =================
69 idSoundShader::Size
70 =================
71 */
72 size_t idSoundShader::Size( void ) const {
73  return sizeof( idSoundShader );
74 }
75 
76 /*
77 ===============
78 idSoundShader::idSoundShader::FreeData
79 ===============
80 */
82  numEntries = 0;
83  numLeadins = 0;
84 }
85 
86 /*
87 ===================
88 idSoundShader::SetDefaultText
89 ===================
90 */
92  idStr wavname;
93 
94  wavname = GetName();
95  wavname.DefaultFileExtension( ".wav" ); // if the name has .ogg in it, that will stay
96 
97  // if there exists a wav file with the same name
98  if ( 1 ) { //fileSystem->ReadFile( wavname, NULL ) != -1 ) {
99  char generated[2048];
100  idStr::snPrintf( generated, sizeof( generated ),
101  "sound %s // IMPLICITLY GENERATED\n"
102  "{\n"
103  "%s\n"
104  "}\n", GetName(), wavname.c_str() );
105  SetText( generated );
106  return true;
107  } else {
108  return false;
109  }
110 }
111 
112 /*
113 ===================
114 DefaultDefinition
115 ===================
116 */
117 const char *idSoundShader::DefaultDefinition() const {
118  return
119  "{\n"
120  "\t" "_default.wav\n"
121  "}";
122 }
123 
124 /*
125 ===============
126 idSoundShader::Parse
127 
128  this is called by the declManager
129 ===============
130 */
131 bool idSoundShader::Parse( const char *text, const int textLength ) {
132  idLexer src;
133 
134  src.LoadMemory( text, textLength, GetFileName(), GetLineNum() );
135  src.SetFlags( DECL_LEXER_FLAGS );
136  src.SkipUntilString( "{" );
137 
138  // deeper functions can set this, which will cause MakeDefault() to be called at the end
139  errorDuringParse = false;
140 
141  if ( !ParseShader( src ) || errorDuringParse ) {
142  MakeDefault();
143  return false;
144  }
145  return true;
146 }
147 
148 /*
149 ===============
150 idSoundShader::ParseShader
151 ===============
152 */
154  int i;
155  idToken token;
156 
157  parms.minDistance = 1;
158  parms.maxDistance = 10;
159  parms.volume = 1;
160  parms.shakes = 0;
162  parms.soundClass = 0;
163 
164  speakerMask = 0;
165  altSound = NULL;
166 
167  for( i = 0; i < SOUND_MAX_LIST_WAVS; i++ ) {
168  leadins[i] = NULL;
169  entries[i] = NULL;
170  }
171  numEntries = 0;
172  numLeadins = 0;
173 
175  if ( com_makingBuild.GetBool() || maxSamples <= 0 || maxSamples > SOUND_MAX_LIST_WAVS ) {
176  maxSamples = SOUND_MAX_LIST_WAVS;
177  }
178 
179  while ( 1 ) {
180  if ( !src.ExpectAnyToken( &token ) ) {
181  return false;
182  }
183  // end of definition
184  else if ( token == "}" ) {
185  break;
186  }
187  // minimum number of sounds
188  else if ( !token.Icmp( "minSamples" ) ) {
189  maxSamples = idMath::ClampInt( src.ParseInt(), SOUND_MAX_LIST_WAVS, maxSamples );
190  }
191  // description
192  else if ( !token.Icmp( "description" ) ) {
193  src.ReadTokenOnLine( &token );
194  desc = token.c_str();
195  }
196  // mindistance
197  else if ( !token.Icmp( "mindistance" ) ) {
198  parms.minDistance = src.ParseFloat();
199  }
200  // maxdistance
201  else if ( !token.Icmp( "maxdistance" ) ) {
202  parms.maxDistance = src.ParseFloat();
203  }
204  // shakes screen
205  else if ( !token.Icmp( "shakes" ) ) {
206  src.ExpectAnyToken( &token );
207  if ( token.type == TT_NUMBER ) {
208  parms.shakes = token.GetFloatValue();
209  } else {
210  src.UnreadToken( &token );
211  parms.shakes = 1.0f;
212  }
213  }
214  // reverb
215  else if ( !token.Icmp( "reverb" ) ) {
216  int reg0 = src.ParseFloat();
217  if ( !src.ExpectTokenString( "," ) ) {
218  src.FreeSource();
219  return false;
220  }
221  int reg1 = src.ParseFloat();
222  // no longer supported
223  }
224  // volume
225  else if ( !token.Icmp( "volume" ) ) {
226  parms.volume = src.ParseFloat();
227  }
228  // leadinVolume is used to allow light breaking leadin sounds to be much louder than the broken loop
229  else if ( !token.Icmp( "leadinVolume" ) ) {
230  leadinVolume = src.ParseFloat();
231  }
232  // speaker mask
233  else if ( !token.Icmp( "mask_center" ) ) {
235  }
236  // speaker mask
237  else if ( !token.Icmp( "mask_left" ) ) {
239  }
240  // speaker mask
241  else if ( !token.Icmp( "mask_right" ) ) {
243  }
244  // speaker mask
245  else if ( !token.Icmp( "mask_backright" ) ) {
247  }
248  // speaker mask
249  else if ( !token.Icmp( "mask_backleft" ) ) {
251  }
252  // speaker mask
253  else if ( !token.Icmp( "mask_lfe" ) ) {
254  speakerMask |= 1<<SPEAKER_LFE;
255  }
256  // soundClass
257  else if ( !token.Icmp( "soundClass" ) ) {
258  parms.soundClass = src.ParseInt();
260  src.Warning( "SoundClass out of range" );
261  return false;
262  }
263  }
264  // altSound
265  else if ( !token.Icmp( "altSound" ) ) {
266  if ( !src.ExpectAnyToken( &token ) ) {
267  return false;
268  }
269  altSound = declManager->FindSound( token.c_str() );
270  }
271  // ordered
272  else if ( !token.Icmp( "ordered" ) ) {
273  // no longer supported
274  }
275  // no_dups
276  else if ( !token.Icmp( "no_dups" ) ) {
277  parms.soundShaderFlags |= SSF_NO_DUPS;
278  }
279  // no_flicker
280  else if ( !token.Icmp( "no_flicker" ) ) {
281  parms.soundShaderFlags |= SSF_NO_FLICKER;
282  }
283  // plain
284  else if ( !token.Icmp( "plain" ) ) {
285  // no longer supported
286  }
287  // looping
288  else if ( !token.Icmp( "looping" ) ) {
289  parms.soundShaderFlags |= SSF_LOOPING;
290  }
291  // no occlusion
292  else if ( !token.Icmp( "no_occlusion" ) ) {
293  parms.soundShaderFlags |= SSF_NO_OCCLUSION;
294  }
295  // private
296  else if ( !token.Icmp( "private" ) ) {
297  parms.soundShaderFlags |= SSF_PRIVATE_SOUND;
298  }
299  // antiPrivate
300  else if ( !token.Icmp( "antiPrivate" ) ) {
301  parms.soundShaderFlags |= SSF_ANTI_PRIVATE_SOUND;
302  }
303  // once
304  else if ( !token.Icmp( "playonce" ) ) {
305  parms.soundShaderFlags |= SSF_PLAY_ONCE;
306  }
307  // global
308  else if ( !token.Icmp( "global" ) ) {
309  parms.soundShaderFlags |= SSF_GLOBAL;
310  }
311  // unclamped
312  else if ( !token.Icmp( "unclamped" ) ) {
313  parms.soundShaderFlags |= SSF_UNCLAMPED;
314  }
315  // omnidirectional
316  else if ( !token.Icmp( "omnidirectional" ) ) {
317  parms.soundShaderFlags |= SSF_OMNIDIRECTIONAL;
318  }
319  // onDemand can't be a parms, because we must track all references and overrides would confuse it
320  else if ( !token.Icmp( "onDemand" ) ) {
321  // no longer loading sounds on demand
322  //onDemand = true;
323  }
324 
325  // the wave files
326  else if ( !token.Icmp( "leadin" ) ) {
327  // add to the leadin list
328  if ( !src.ReadToken( &token ) ) {
329  src.Warning( "Expected sound after leadin" );
330  return false;
331  }
332  if ( soundSystemLocal.soundCache && numLeadins < maxSamples ) {
334  numLeadins++;
335  }
336  } else if ( token.Find( ".wav", false ) != -1 || token.Find( ".ogg", false ) != -1 ) {
337  // add to the wav list
338  if ( soundSystemLocal.soundCache && numEntries < maxSamples ) {
339  token.BackSlashesToSlashes();
340  idStr lang = cvarSystem->GetCVarString( "sys_lang" );
341  if ( lang.Icmp( "english" ) != 0 && token.Find( "sound/vo/", false ) >= 0 ) {
342  idStr work = token;
343  work.ToLower();
344  work.StripLeading( "sound/vo/" );
345  work = va( "sound/vo/%s/%s", lang.c_str(), work.c_str() );
346  if ( fileSystem->ReadFile( work, NULL, NULL ) > 0 ) {
347  token = work;
348  } else {
349  // also try to find it with the .ogg extension
350  work.SetFileExtension( ".ogg" );
351  if ( fileSystem->ReadFile( work, NULL, NULL ) > 0 ) {
352  token = work;
353  }
354  }
355  }
357  numEntries++;
358  }
359  } else {
360  src.Warning( "unknown token '%s'", token.c_str() );
361  return false;
362  }
363  }
364 
365  if ( parms.shakes > 0.0f ) {
367  }
368 
369  return true;
370 }
371 
372 /*
373 ===============
374 idSoundShader::CheckShakesAndOgg
375 ===============
376 */
378  int i;
379  bool ret = false;
380 
381  for ( i = 0; i < numLeadins; i++ ) {
382  if ( leadins[ i ]->objectInfo.wFormatTag == WAVE_FORMAT_TAG_OGG ) {
383  common->Warning( "sound shader '%s' has shakes and uses OGG file '%s'",
384  GetName(), leadins[ i ]->name.c_str() );
385  ret = true;
386  }
387  }
388  for ( i = 0; i < numEntries; i++ ) {
389  if ( entries[ i ]->objectInfo.wFormatTag == WAVE_FORMAT_TAG_OGG ) {
390  common->Warning( "sound shader '%s' has shakes and uses OGG file '%s'",
391  GetName(), entries[ i ]->name.c_str() );
392  ret = true;
393  }
394  }
395  return ret;
396 }
397 
398 /*
399 ===============
400 idSoundShader::List
401 ===============
402 */
403 void idSoundShader::List() const {
404  idStrList shaders;
405 
406  common->Printf( "%4i: %s\n", Index(), GetName() );
407  if ( idStr::Icmp( GetDescription(), "<no description>" ) != 0 ) {
408  common->Printf( " description: %s\n", GetDescription() );
409  }
410  for( int k = 0; k < numLeadins ; k++ ) {
411  const idSoundSample *objectp = leadins[k];
412  if ( objectp ) {
413  common->Printf( " %5dms %4dKb %s (LEADIN)\n", soundSystemLocal.SamplesToMilliseconds(objectp->LengthIn44kHzSamples()), (objectp->objectMemSize/1024)
414  ,objectp->name.c_str() );
415  }
416  }
417  for( int k = 0; k < numEntries; k++ ) {
418  const idSoundSample *objectp = entries[k];
419  if ( objectp ) {
420  common->Printf( " %5dms %4dKb %s\n", soundSystemLocal.SamplesToMilliseconds(objectp->LengthIn44kHzSamples()), (objectp->objectMemSize/1024)
421  ,objectp->name.c_str() );
422  }
423  }
424 }
425 
426 /*
427 ===============
428 idSoundShader::GetAltSound
429 ===============
430 */
432  return altSound;
433 }
434 
435 /*
436 ===============
437 idSoundShader::GetMinDistance
438 ===============
439 */
441  return parms.minDistance;
442 }
443 
444 /*
445 ===============
446 idSoundShader::GetMaxDistance
447 ===============
448 */
450  return parms.maxDistance;
451 }
452 
453 /*
454 ===============
455 idSoundShader::GetDescription
456 ===============
457 */
458 const char *idSoundShader::GetDescription() const {
459  return desc;
460 }
461 
462 /*
463 ===============
464 idSoundShader::HasDefaultSound
465 ===============
466 */
468  for ( int i = 0; i < numEntries; i++ ) {
469  if ( entries[i] && entries[i]->defaultSound ) {
470  return true;
471  }
472  }
473  return false;
474 }
475 
476 /*
477 ===============
478 idSoundShader::GetParms
479 ===============
480 */
482  return &parms;
483 }
484 
485 /*
486 ===============
487 idSoundShader::GetNumSounds
488 ===============
489 */
491  return numLeadins + numEntries;
492 }
493 
494 /*
495 ===============
496 idSoundShader::GetSound
497 ===============
498 */
499 const char *idSoundShader::GetSound( int index ) const {
500  if ( index >= 0 ) {
501  if ( index < numLeadins ) {
502  return leadins[index]->name.c_str();
503  }
504  index -= numLeadins;
505  if ( index < numEntries ) {
506  return entries[index]->name.c_str();
507  }
508  }
509  return "";
510 }
int GetLineNum(void) const
Definition: DeclManager.h:168
static int snPrintf(char *dest, int size, const char *fmt,...) id_attribute((format(printf
Definition: Str.cpp:1465
int type
Definition: Token.h:77
idStr & SetFileExtension(const char *extension)
Definition: Str.cpp:743
virtual const idSoundShader * FindSound(const char *name, bool makeDefault=true)=0
virtual bool HasDefaultSound() const
Definition: snd_shader.cpp:467
float maxDistance
Definition: sound.h:62
idCVarSystem * cvarSystem
Definition: CVarSystem.cpp:487
virtual size_t Size(void) const
Definition: snd_shader.cpp:72
void ToLower(void)
Definition: Str.h:817
void StripLeading(const char c)
Definition: Str.cpp:469
const char * GetFileName(void) const
Definition: DeclManager.h:171
const int DECL_LEXER_FLAGS
Definition: DeclManager.h:93
virtual const char * DefaultDefinition(void) const
Definition: snd_shader.cpp:117
virtual float GetMaxDistance() const
Definition: snd_shader.cpp:449
virtual bool Parse(const char *text, const int textLength)
Definition: snd_shader.cpp:131
virtual const soundShaderParms_t * GetParms() const
Definition: snd_shader.cpp:481
void FreeSource(void)
Definition: Lexer.cpp:1676
virtual int ReadFile(const char *relativePath, void **buffer, ID_TIME_T *timestamp=NULL)=0
idFileSystem * fileSystem
Definition: FileSystem.cpp:500
float GetFloatValue(void)
Definition: Token.h:138
const char * GetName(void) const
Definition: DeclManager.h:140
int objectMemSize
Definition: snd_local.h:848
bool ParseShader(idLexer &src)
Definition: snd_shader.cpp:153
virtual float GetMinDistance() const
Definition: snd_shader.cpp:440
Definition: Token.h:71
void SetFlags(int flags)
Definition: Lexer.h:298
float ParseFloat(bool *errorFlag=NULL)
Definition: Lexer.cpp:1264
GLuint src
Definition: glext.h:5390
idStr & DefaultFileExtension(const char *extension)
Definition: Str.cpp:794
idSoundSample * FindSound(const idStr &fname, bool loadOnDemandOnly)
Definition: snd_cache.cpp:86
static int ClampInt(int min, int max, int value)
Definition: Math.h:883
int ReadTokenOnLine(idToken *token)
Definition: Lexer.cpp:1172
int i
Definition: process.py:33
int ParseInt(void)
Definition: Lexer.cpp:1227
bool onDemand
Definition: sound.h:118
int Icmp(const char *text) const
Definition: Str.h:667
idStr & BackSlashesToSlashes(void)
Definition: Str.cpp:727
#define TT_NUMBER
Definition: Token.h:43
int ExpectAnyToken(idToken *token)
Definition: Lexer.cpp:992
idSoundSample * leadins[SOUND_MAX_LIST_WAVS]
Definition: sound.h:125
int LengthIn44kHzSamples() const
Definition: snd_cache.cpp:317
int numLeadins
Definition: sound.h:126
idCVar com_makingBuild("com_makingBuild","0", CVAR_BOOL|CVAR_SYSTEM,"1 when making a build")
Definition: Lexer.h:137
soundShaderParms_t parms
Definition: sound.h:116
int Index(void) const
Definition: DeclManager.h:165
GLuint index
Definition: glext.h:3476
virtual bool CheckShakesAndOgg(void) const
Definition: snd_shader.cpp:377
idCommon * common
Definition: Common.cpp:206
virtual int GetNumSounds() const
Definition: snd_shader.cpp:490
#define NULL
Definition: Lib.h:88
virtual const char * GetCVarString(const char *name) const =0
int GetInteger(void) const
Definition: CVarSystem.h:143
virtual void List(void) const
Definition: snd_shader.cpp:403
float leadinVolume
Definition: sound.h:123
virtual const idSoundShader * GetAltSound() const
Definition: snd_shader.cpp:431
int Find(const char c, int start=0, int end=-1) const
Definition: Str.h:874
void UnreadToken(const idToken *token)
Definition: Lexer.cpp:1159
virtual const char * GetSound(int index) const
Definition: snd_shader.cpp:499
virtual void Printf(const char *fmt,...) id_attribute((format(printf
float shakes
Definition: sound.h:64
virtual bool SetDefaultText(void)
Definition: snd_shader.cpp:91
int numEntries
Definition: sound.h:128
int LoadMemory(const char *ptr, int length, const char *name, int startLine=1)
Definition: Lexer.cpp:1646
virtual ~idSoundShader(void)
Definition: snd_shader.cpp:64
virtual const char * GetDescription() const
Definition: snd_shader.cpp:458
void SetText(const char *text)
Definition: DeclManager.h:180
idDeclManager * declManager
idSoundSample * entries[SOUND_MAX_LIST_WAVS]
Definition: sound.h:127
int ExpectTokenString(const char *string)
Definition: Lexer.cpp:919
void void Warning(const char *str,...) id_attribute((format(printf
Definition: Lexer.cpp:241
idSoundSystemLocal soundSystemLocal
Definition: snd_system.cpp:91
int speakerMask
Definition: sound.h:119
bool GetBool(void) const
Definition: CVarSystem.h:142
static idCVar s_maxSoundsPerShader
Definition: snd_local.h:790
const GLcharARB * name
Definition: glext.h:3629
idSoundCache * soundCache
Definition: snd_local.h:736
Definition: Str.h:116
const idSoundShader * altSound
Definition: sound.h:120
idSoundShader(void)
Definition: snd_shader.cpp:55
const char * c_str(void) const
Definition: Str.h:487
int SkipUntilString(const char *string)
Definition: Lexer.cpp:1097
int SamplesToMilliseconds(int samples) const
char * va(const char *fmt,...)
Definition: Str.cpp:1568
void MakeDefault(void)
Definition: DeclManager.h:190
const int SOUND_MAX_LIST_WAVS
Definition: sound.h:70
virtual void virtual void Warning(const char *fmt,...) id_attribute((format(printf
const int SOUND_MAX_CLASSES
Definition: sound.h:74
int ReadToken(idToken *token)
Definition: Lexer.cpp:820
int soundShaderFlags
Definition: sound.h:65
void Init(void)
Definition: snd_shader.cpp:40
virtual void FreeData(void)
Definition: snd_shader.cpp:81
bool errorDuringParse
Definition: sound.h:122
float volume
Definition: sound.h:63
idStr desc
Definition: sound.h:121
float minDistance
Definition: sound.h:61