snd_shader.cpp 9.7 KB

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