snd_shader.cpp (9981B)
1 /* 2 =========================================================================== 3 4 Doom 3 BFG Edition GPL Source Code 5 Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company. 6 7 This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code"). 8 9 Doom 3 BFG Edition 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 BFG Edition 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 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>. 21 22 In addition, the Doom 3 BFG Edition 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 BFG Edition 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 #pragma hdrstop 30 #include "../idlib/precompiled.h" 31 32 #include "snd_local.h" 33 34 extern idCVar s_maxSamples; 35 36 typedef enum { 37 SPEAKER_LEFT = 0, 38 SPEAKER_RIGHT, 39 SPEAKER_CENTER, 40 SPEAKER_LFE, 41 SPEAKER_BACKLEFT, 42 SPEAKER_BACKRIGHT 43 } speakerLabel; 44 45 /* 46 =============== 47 idSoundShader::Init 48 =============== 49 */ 50 void idSoundShader::Init() { 51 leadin = false; 52 leadinVolume = 0; 53 altSound = NULL; 54 } 55 56 /* 57 =============== 58 idSoundShader::idSoundShader 59 =============== 60 */ 61 idSoundShader::idSoundShader() { 62 Init(); 63 } 64 65 /* 66 =============== 67 idSoundShader::~idSoundShader 68 =============== 69 */ 70 idSoundShader::~idSoundShader() { 71 } 72 73 /* 74 ================= 75 idSoundShader::Size 76 ================= 77 */ 78 size_t idSoundShader::Size() const { 79 return sizeof( idSoundShader ); 80 } 81 82 /* 83 =============== 84 idSoundShader::idSoundShader::FreeData 85 =============== 86 */ 87 void idSoundShader::FreeData() { 88 } 89 90 /* 91 =================== 92 idSoundShader::SetDefaultText 93 =================== 94 */ 95 bool idSoundShader::SetDefaultText() { 96 idStr wavname; 97 98 wavname = GetName(); 99 wavname.DefaultFileExtension( ".wav" ); // if the name has .ogg in it, that will stay 100 101 // if there exists a wav file with the same name 102 if ( 1 ) { //fileSystem->ReadFile( wavname, NULL ) != -1 ) { 103 char generated[2048]; 104 idStr::snPrintf( generated, sizeof( generated ), 105 "sound %s // IMPLICITLY GENERATED\n" 106 "{\n" 107 "%s\n" 108 "}\n", GetName(), wavname.c_str() ); 109 SetText( generated ); 110 return true; 111 } else { 112 return false; 113 } 114 } 115 116 /* 117 =================== 118 DefaultDefinition 119 =================== 120 */ 121 const char *idSoundShader::DefaultDefinition() const { 122 return 123 "{\n" 124 "\t" "_default.wav\n" 125 "}"; 126 } 127 128 /* 129 =============== 130 idSoundShader::Parse 131 132 this is called by the declManager 133 =============== 134 */ 135 bool idSoundShader::Parse( const char *text, const int textLength, bool allowBinaryVersion ) { 136 idLexer src; 137 138 src.LoadMemory( text, textLength, GetFileName(), GetLineNum() ); 139 src.SetFlags( DECL_LEXER_FLAGS ); 140 src.SkipUntilString( "{" ); 141 142 if ( !ParseShader( src ) ) { 143 MakeDefault(); 144 return false; 145 } 146 return true; 147 } 148 149 /* 150 =============== 151 idSoundShader::ParseShader 152 =============== 153 */ 154 bool idSoundShader::ParseShader( idLexer &src ) { 155 idToken token; 156 157 parms.minDistance = 1; 158 parms.maxDistance = 10; 159 parms.volume = 1; 160 parms.shakes = 0; 161 parms.soundShaderFlags = 0; 162 parms.soundClass = 0; 163 164 speakerMask = 0; 165 altSound = NULL; 166 167 entries.Clear(); 168 169 while ( 1 ) { 170 if ( !src.ExpectAnyToken( &token ) ) { 171 return false; 172 } 173 // end of definition 174 else if ( token == "}" ) { 175 break; 176 } 177 // minimum number of sounds 178 else if ( !token.Icmp( "minSamples" ) ) { 179 src.ParseInt(); 180 } 181 // description 182 else if ( !token.Icmp( "description" ) ) { 183 src.ReadTokenOnLine( &token ); 184 } 185 // mindistance 186 else if ( !token.Icmp( "mindistance" ) ) { 187 parms.minDistance = src.ParseFloat(); 188 } 189 // maxdistance 190 else if ( !token.Icmp( "maxdistance" ) ) { 191 parms.maxDistance = src.ParseFloat(); 192 } 193 // shakes screen 194 else if ( !token.Icmp( "shakes" ) ) { 195 src.ExpectAnyToken( &token ); 196 if ( token.type == TT_NUMBER ) { 197 parms.shakes = token.GetFloatValue(); 198 } else { 199 src.UnreadToken( &token ); 200 parms.shakes = 1.0f; 201 } 202 } 203 // reverb 204 else if ( !token.Icmp( "reverb" ) ) { 205 src.ParseFloat(); 206 if ( !src.ExpectTokenString( "," ) ) { 207 src.FreeSource(); 208 return false; 209 } 210 src.ParseFloat(); 211 // no longer supported 212 } 213 // volume 214 else if ( !token.Icmp( "volume" ) ) { 215 parms.volume = src.ParseFloat(); 216 } 217 // leadinVolume is used to allow light breaking leadin sounds to be much louder than the broken loop 218 else if ( !token.Icmp( "leadinVolume" ) ) { 219 leadinVolume = src.ParseFloat(); 220 leadin = true; 221 } 222 // speaker mask 223 else if ( !token.Icmp( "mask_center" ) ) { 224 speakerMask |= 1<<SPEAKER_CENTER; 225 } 226 // speaker mask 227 else if ( !token.Icmp( "mask_left" ) ) { 228 speakerMask |= 1<<SPEAKER_LEFT; 229 } 230 // speaker mask 231 else if ( !token.Icmp( "mask_right" ) ) { 232 speakerMask |= 1<<SPEAKER_RIGHT; 233 } 234 // speaker mask 235 else if ( !token.Icmp( "mask_backright" ) ) { 236 speakerMask |= 1<<SPEAKER_BACKRIGHT; 237 } 238 // speaker mask 239 else if ( !token.Icmp( "mask_backleft" ) ) { 240 speakerMask |= 1<<SPEAKER_BACKLEFT; 241 } 242 // speaker mask 243 else if ( !token.Icmp( "mask_lfe" ) ) { 244 speakerMask |= 1<<SPEAKER_LFE; 245 } 246 // soundClass 247 else if ( !token.Icmp( "soundClass" ) ) { 248 parms.soundClass = src.ParseInt(); 249 if ( parms.soundClass < 0 || parms.soundClass >= SOUND_MAX_CLASSES ) { 250 src.Warning( "SoundClass out of range" ); 251 return false; 252 } 253 } 254 // altSound 255 else if ( !token.Icmp( "altSound" ) ) { 256 if ( !src.ExpectAnyToken( &token ) ) { 257 return false; 258 } 259 altSound = declManager->FindSound( token.c_str() ); 260 } 261 // ordered 262 else if ( !token.Icmp( "ordered" ) ) { 263 // no longer supported 264 } 265 // no_dups 266 else if ( !token.Icmp( "no_dups" ) ) { 267 parms.soundShaderFlags |= SSF_NO_DUPS; 268 } 269 // no_flicker 270 else if ( !token.Icmp( "no_flicker" ) ) { 271 parms.soundShaderFlags |= SSF_NO_FLICKER; 272 } 273 // plain 274 else if ( !token.Icmp( "plain" ) ) { 275 // no longer supported 276 } 277 // looping 278 else if ( !token.Icmp( "looping" ) ) { 279 parms.soundShaderFlags |= SSF_LOOPING; 280 } 281 // no occlusion 282 else if ( !token.Icmp( "no_occlusion" ) ) { 283 parms.soundShaderFlags |= SSF_NO_OCCLUSION; 284 } 285 // private 286 else if ( !token.Icmp( "private" ) ) { 287 parms.soundShaderFlags |= SSF_PRIVATE_SOUND; 288 } 289 // antiPrivate 290 else if ( !token.Icmp( "antiPrivate" ) ) { 291 parms.soundShaderFlags |= SSF_ANTI_PRIVATE_SOUND; 292 } 293 // once 294 else if ( !token.Icmp( "playonce" ) ) { 295 parms.soundShaderFlags |= SSF_PLAY_ONCE; 296 } 297 // global 298 else if ( !token.Icmp( "global" ) ) { 299 parms.soundShaderFlags |= SSF_GLOBAL; 300 } 301 // unclamped 302 else if ( !token.Icmp( "unclamped" ) ) { 303 parms.soundShaderFlags |= SSF_UNCLAMPED; 304 } 305 // omnidirectional 306 else if ( !token.Icmp( "omnidirectional" ) ) { 307 parms.soundShaderFlags |= SSF_OMNIDIRECTIONAL; 308 } 309 else if ( !token.Icmp( "onDemand" ) ) { 310 // no longer loading sounds on demand 311 } 312 // the wave files 313 else if ( !token.Icmp( "leadin" ) ) { 314 leadin = true; 315 } else if ( token.Find( ".wav", false ) != -1 || token.Find( ".ogg", false ) != -1 ) { 316 if ( token.IcmpPrefixPath( "sound/vo/" ) == 0 || token.IcmpPrefixPath( "sound/guis/" ) == 0 ) { 317 parms.soundShaderFlags |= SSF_VO; 318 } 319 if ( token.IcmpPrefixPath( "sound/musical/" ) == 0 ) { 320 parms.soundShaderFlags |= SSF_MUSIC; 321 } 322 // add to the wav list 323 if ( s_maxSamples.GetInteger() == 0 || ( s_maxSamples.GetInteger() > 0 && entries.Num() < s_maxSamples.GetInteger() ) ) { 324 entries.Append( soundSystemLocal.LoadSample( token.c_str() ) ); 325 } 326 } else { 327 src.Warning( "unknown token '%s'", token.c_str() ); 328 return false; 329 } 330 } 331 332 return true; 333 } 334 335 /* 336 =============== 337 idSoundShader::List 338 =============== 339 */ 340 void idSoundShader::List() const { 341 idStrList shaders; 342 343 common->Printf( "%4i: %s\n", Index(), GetName() ); 344 for( int k = 0; k < entries.Num(); k++ ) { 345 const idSoundSample *objectp = entries[k]; 346 if ( objectp ) { 347 common->Printf( " %5dms %4dKb %s\n", objectp->LengthInMsec(), (objectp->BufferSize()/1024), objectp->GetName() ); 348 } 349 } 350 } 351 352 /* 353 =============== 354 idSoundShader::GetAltSound 355 =============== 356 */ 357 const idSoundShader *idSoundShader::GetAltSound() const { 358 return altSound; 359 } 360 361 /* 362 =============== 363 idSoundShader::GetMinDistance 364 =============== 365 */ 366 float idSoundShader::GetMinDistance() const { 367 return parms.minDistance; 368 } 369 370 /* 371 =============== 372 idSoundShader::GetMaxDistance 373 =============== 374 */ 375 float idSoundShader::GetMaxDistance() const { 376 return parms.maxDistance; 377 } 378 379 /* 380 =============== 381 idSoundShader::HasDefaultSound 382 =============== 383 */ 384 bool idSoundShader::HasDefaultSound() const { 385 for ( int i = 0; i < entries.Num(); i++ ) { 386 if ( entries[i] && entries[i]->IsDefault() ) { 387 return true; 388 } 389 } 390 return false; 391 } 392 393 /* 394 =============== 395 idSoundShader::GetParms 396 =============== 397 */ 398 const soundShaderParms_t *idSoundShader::GetParms() const { 399 return &parms; 400 } 401 402 /* 403 =============== 404 idSoundShader::GetNumSounds 405 =============== 406 */ 407 int idSoundShader::GetNumSounds() const { 408 return entries.Num(); 409 } 410 411 /* 412 =============== 413 idSoundShader::GetSound 414 =============== 415 */ 416 const char *idSoundShader::GetSound( int index ) const { 417 if ( index >= 0 && index < entries.Num() ) { 418 return entries[index]->GetName(); 419 } 420 return ""; 421 }