DOOM-3-BFG

DOOM 3 BFG Edition
Log | Files | Refs

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 }