soundman.c 93 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201
  1. /*********************************************************************************
  2. * SGP Digital Sound Module
  3. *
  4. * This module handles the playing of digital samples, preloaded or streamed.
  5. *
  6. * Derek Beland, May 28, 1997
  7. *********************************************************************************/
  8. #ifdef JA2_PRECOMPILED_HEADERS
  9. #include "JA2 SGP ALL.H"
  10. #elif defined( WIZ8_PRECOMPILED_HEADERS )
  11. #include "WIZ8 SGP ALL.H"
  12. #else
  13. #include <stdio.h>
  14. #include <string.h>
  15. #include "soundman.h"
  16. #include "FileMan.h"
  17. #include "debug.h"
  18. #include "MemMan.h"
  19. #include "mss.h"
  20. #include "random.h"
  21. #endif
  22. // Uncomment this to disable the startup of sound hardware
  23. //#define SOUND_DISABLE
  24. #pragma pack(push,1)
  25. // WAV file chunk definitions
  26. typedef struct {
  27. // General chunk header
  28. CHAR8 cTag[4];
  29. UINT32 uiChunkSize;
  30. } WAVCHUNK;
  31. typedef struct {
  32. // WAV header
  33. CHAR8 cRiff[4]; // "RIFF"
  34. UINT32 uiChunkSize; // Chunk length
  35. CHAR8 cFileType[4]; // "WAVE"
  36. } WAVRIFF;
  37. typedef struct {
  38. // FMT chunk
  39. CHAR8 cFormat[4]; // "FMT "
  40. UINT32 uiChunkSize; // Chunk length
  41. UINT16 uiStereo; // 1 if stereo, 0 if mono (Not reliable, use channels instead)
  42. UINT16 uiChannels; // number of channels used 1=mono, 2=stereo, etc.
  43. UINT32 uiSpeed; // Sampling Rate (speed)
  44. UINT32 uiBytesSec; // Number of bytes per sec
  45. UINT16 uiBytesSample; // Number of bytes per sample (1 = 8 bit mono,
  46. // 2 = 8 bit stereo or 16 bit mono, 4 = 16 bit stereo
  47. UINT16 uiBitsSample; // bits per sample
  48. } WAVFMT;
  49. typedef struct {
  50. // Data chunk
  51. CHAR8 cName[4]; // "DATA"
  52. UINT32 uiChunkSize; // Chunk length
  53. } WAVDATA;
  54. #pragma pack(pop)
  55. #define WAV_CHUNK_RIFF 0
  56. #define WAV_CHUNK_FMT 1
  57. #define WAV_CHUNK_DATA 2
  58. #define NUM_WAV_CHUNKS 3
  59. CHAR8 *cWAVChunks[3]={"RIFF", "FMT ", "DATA"};
  60. // global settings
  61. #define SOUND_MAX_CACHED 128 // number of cache slots
  62. #ifdef JA2
  63. #define SOUND_MAX_CHANNELS 16 // number of mixer channels
  64. #else
  65. #define SOUND_MAX_CHANNELS 32 // number of mixer channels
  66. #endif
  67. #pragma message("TEMP!")
  68. #define SOUND_DEFAULT_MEMORY (8048*1024) // default memory limit
  69. #define SOUND_DEFAULT_THRESH (256*8024) // size for sample to be double-buffered
  70. #define SOUND_DEFAULT_STREAM (64*1024) // double-buffered buffer size
  71. /*#define SOUND_DEFAULT_MEMORY (2048*1024) // default memory limit
  72. #define SOUND_DEFAULT_THRESH (256*1024) // size for sample to be double-buffered
  73. #define SOUND_DEFAULT_STREAM (64*1024) // double-buffered buffer size
  74. */
  75. // playing/random value to indicate default
  76. #define SOUND_PARMS_DEFAULT 0xffffffff
  77. // Sound status flags
  78. #define SOUND_CALLBACK 0x00000008
  79. // Local Function Prototypes
  80. BOOLEAN SoundInitCache(void);
  81. BOOLEAN SoundShutdownCache(void);
  82. UINT32 SoundLoadSample(STR pFilename);
  83. UINT32 SoundFreeSample(STR pFilename);
  84. UINT32 SoundGetCached(STR pFilename);
  85. UINT32 SoundLoadDisk(STR pFilename);
  86. // Low level
  87. UINT32 SoundGetEmptySample(void);
  88. BOOLEAN SoundProcessWAVHeader(UINT32 uiSample);
  89. UINT32 SoundFreeSampleIndex(UINT32 uiSample);
  90. UINT32 SoundGetIndexByID(UINT32 uiSoundID);
  91. static HDIGDRIVER SoundInitDriver(UINT32 uiRate, UINT16 uiBits, UINT16 uiChans);
  92. BOOLEAN SoundInitHardware(void);
  93. BOOLEAN SoundGetDriverName(HDIGDRIVER DIG, CHAR8 *cBuf);
  94. BOOLEAN SoundShutdownHardware(void);
  95. UINT32 SoundGetFreeChannel(void);
  96. UINT32 SoundStartSample(UINT32 uiSample, UINT32 uiChannel, SOUNDPARMS *pParms);
  97. UINT32 SoundStartStream(STR pFilename, UINT32 uiChannel, SOUNDPARMS *pParms);
  98. UINT32 SoundGetUniqueID(void);
  99. BOOLEAN SoundPlayStreamed(STR pFilename);
  100. BOOLEAN SoundCleanCache(void);
  101. BOOLEAN SoundSampleIsPlaying(UINT32 uiSample);
  102. BOOLEAN SoundIndexIsPlaying(UINT32 uiSound);
  103. BOOLEAN SoundStopIndex(UINT32 uiSound);
  104. UINT32 SoundGetVolumeIndex(UINT32 uiChannel);
  105. BOOLEAN SoundSetVolumeIndex(UINT32 uiChannel, UINT32 uiVolume);
  106. // Global variables
  107. UINT32 guiSoundDefaultVolume = 127;
  108. UINT32 guiSoundMemoryLimit=SOUND_DEFAULT_MEMORY; // Maximum memory used for sounds
  109. UINT32 guiSoundMemoryUsed=0; // Memory currently in use
  110. UINT32 guiSoundCacheThreshold=SOUND_DEFAULT_THRESH; // Double-buffered threshold
  111. HDIGDRIVER hSoundDriver; // Sound driver handle
  112. BOOLEAN fDirectSound=TRUE; // Using Direct Sound
  113. // Local module variables
  114. BOOLEAN fSoundSystemInit=FALSE; // Startup called T/F
  115. BOOLEAN gfEnableStartup=TRUE; // Allow hardware to starup
  116. // Sample cache list for files loaded
  117. SAMPLETAG pSampleList[SOUND_MAX_CACHED];
  118. // Sound channel list for output channels
  119. SOUNDTAG pSoundList[SOUND_MAX_CHANNELS];
  120. // 3D sound globals
  121. CHAR8 *gpProviderName=NULL;
  122. HPROVIDER gh3DProvider=0;
  123. H3DPOBJECT gh3DListener=0;
  124. BOOLEAN gfUsingEAX=TRUE;
  125. UINT32 guiRoomTypeIndex=0;
  126. CHAR8* pEAXRoomTypes[EAXROOMTYPE_NUM_TYPES] =
  127. {
  128. // None
  129. "PLAIN",
  130. // S,M,L Cave
  131. "STONECORRIDOR",
  132. "CAVE",
  133. "CONCERTHALL",
  134. // S,M,L Room
  135. "LIVINGROOM",
  136. "ROOM",
  137. "AUDITORIUM",
  138. // Flat open, valley
  139. "CITY",
  140. "MOUNTAINS",
  141. // Swimming
  142. "UNDERWATER"
  143. };
  144. //*******************************************************************************
  145. // High Level Interface
  146. //*******************************************************************************
  147. //*******************************************************************************
  148. // SoundEnableSound
  149. //
  150. // Allows or disallows the startup of the sound hardware.
  151. //
  152. // Returns: Nothing.
  153. //
  154. //*******************************************************************************
  155. void SoundEnableSound(BOOLEAN fEnable)
  156. {
  157. gfEnableStartup=fEnable;
  158. }
  159. //*******************************************************************************
  160. // InitializeSoundManager
  161. //
  162. // Zeros out the structs for the system info, and initializes the cache.
  163. //
  164. // Returns: TRUE always
  165. //
  166. //*******************************************************************************
  167. BOOLEAN InitializeSoundManager(void)
  168. {
  169. UINT32 uiCount;
  170. if(fSoundSystemInit)
  171. ShutdownSoundManager();
  172. for(uiCount=0; uiCount < SOUND_MAX_CHANNELS; uiCount++)
  173. memset(&pSoundList[uiCount], 0, sizeof(SOUNDTAG));
  174. #ifndef SOUND_DISABLE
  175. if(gfEnableStartup && SoundInitHardware())
  176. fSoundSystemInit=TRUE;
  177. #endif
  178. SoundInitCache();
  179. guiSoundMemoryLimit=SOUND_DEFAULT_MEMORY;
  180. guiSoundMemoryUsed=0;
  181. guiSoundCacheThreshold=SOUND_DEFAULT_THRESH;
  182. if(gpProviderName && !gh3DProvider)
  183. Sound3DInitProvider(gpProviderName);
  184. return(TRUE);
  185. }
  186. //*******************************************************************************
  187. // ShutdownSoundManager
  188. //
  189. // Silences all currently playing sound, deallocates any memory allocated,
  190. // and releases the sound hardware.
  191. //
  192. //*******************************************************************************
  193. void ShutdownSoundManager(void)
  194. {
  195. if(gh3DProvider)
  196. Sound3DShutdownProvider();
  197. SoundStopAll();
  198. SoundStopMusic();
  199. SoundShutdownCache();
  200. Sleep(1000);
  201. SoundShutdownHardware();
  202. //Sleep(1000);
  203. fSoundSystemInit=FALSE;
  204. }
  205. //*******************************************************************************
  206. // SoundPlay
  207. //
  208. // Starts a sample playing. If the sample is not loaded in the cache, it will
  209. // be found and loaded. The pParms structure is used to
  210. // override the attributes of the sample such as playback speed, and to specify
  211. // a volume. Any entry containing SOUND_PARMS_DEFAULT will be set by the system.
  212. //
  213. // Returns: If the sound was started, it returns a sound ID unique to that
  214. // instance of the sound
  215. // If an error occured, SOUND_ERROR will be returned
  216. //
  217. //
  218. // !!Note: Can no longer play streamed files
  219. //
  220. //*******************************************************************************
  221. UINT32 SoundPlay(STR pFilename, SOUNDPARMS *pParms)
  222. {
  223. UINT32 uiSample, uiChannel;
  224. if( fSoundSystemInit )
  225. {
  226. if( !SoundPlayStreamed(pFilename) )
  227. {
  228. if((uiSample=SoundLoadSample(pFilename))!=NO_SAMPLE)
  229. {
  230. if((uiChannel=SoundGetFreeChannel())!=SOUND_ERROR)
  231. {
  232. return(SoundStartSample(uiSample, uiChannel, pParms));
  233. }
  234. }
  235. }
  236. else
  237. {
  238. //Trying to play a sound which is bigger then the 'guiSoundCacheThreshold'
  239. // This line was causing a page fault in the Wiz 8 project, so
  240. // I changed it to the second line, which works OK. -- DB
  241. //DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("\n*******\nSoundPlay(): ERROR: trying to play %s which is bigger then the 'guiSoundCacheThreshold', use SoundPlayStreamedFile() instead\n", pFilename ) );
  242. FastDebugMsg(String("SoundPlay: ERROR: Trying to play %s sound is too lardge to load into cache, use SoundPlayStreamedFile() instead\n", pFilename ) );
  243. }
  244. }
  245. return(SOUND_ERROR);
  246. }
  247. //*******************************************************************************
  248. // SoundPlayStreamedFile
  249. //
  250. // The sample will
  251. // be played as a double-buffered sample. The pParms structure is used to
  252. // override the attributes of the sample such as playback speed, and to specify
  253. // a volume. Any entry containing SOUND_PARMS_DEFAULT will be set by the system.
  254. //
  255. // Returns: If the sound was started, it returns a sound ID unique to that
  256. // instance of the sound
  257. // If an error occured, SOUND_ERROR will be returned
  258. //
  259. //*******************************************************************************
  260. UINT32 SoundPlayStreamedFile( STR pFilename, SOUNDPARMS *pParms )
  261. {
  262. UINT32 uiChannel;
  263. HANDLE hRealFileHandle;
  264. CHAR8 pFileHandlefileName[ 128 ];
  265. HWFILE hFile;
  266. UINT32 uiRetVal=FALSE;
  267. if( fSoundSystemInit )
  268. {
  269. if((uiChannel=SoundGetFreeChannel())!=SOUND_ERROR)
  270. {
  271. //Open the file
  272. hFile = FileOpen( pFilename, FILE_ACCESS_READ | FILE_OPEN_EXISTING, FALSE );
  273. if( !hFile )
  274. {
  275. FastDebugMsg(String("\n*******\nSoundPlayStreamedFile(): ERROR: Couldnt open '%s' in SoundPlayStreamedFile()\n", pFilename ) );
  276. return( SOUND_ERROR );
  277. }
  278. // MSS cannot determine which provider to play if you don't give it a real filename
  279. // so if the file isn't in a library, play it normally
  280. if(DB_EXTRACT_LIBRARY(hFile) == REAL_FILE_LIBRARY_ID)
  281. {
  282. FileClose(hFile);
  283. return(SoundStartStream( pFilename, uiChannel, pParms));
  284. }
  285. //Get the real file handle of the file
  286. hRealFileHandle = GetRealFileHandleFromFileManFileHandle( hFile );
  287. if( hRealFileHandle == 0 )
  288. {
  289. FastDebugMsg(String("\n*******\nSoundPlayStreamedFile(): ERROR: Couldnt get a real file handle for '%s' in SoundPlayStreamedFile()\n", pFilename ) );
  290. return( SOUND_ERROR );
  291. }
  292. //Convert the file handle into a 'name'
  293. sprintf( pFileHandlefileName, "\\\\\\\\%d", hRealFileHandle );
  294. //Start the sound stream
  295. uiRetVal = SoundStartStream( pFileHandlefileName, uiChannel, pParms);
  296. //if it succeeded, record the file handle
  297. if( uiRetVal != SOUND_ERROR )
  298. pSoundList[uiChannel].hFile = hFile;
  299. else
  300. FileClose( hFile );
  301. return( uiRetVal );
  302. }
  303. }
  304. return(SOUND_ERROR);
  305. }
  306. //*******************************************************************************
  307. // SoundPlayRandom
  308. //
  309. // Registers a sample to be played randomly within the specified parameters.
  310. // Parameters are passed in through pParms. Any parameter containing
  311. // SOUND_PARMS_DEFAULT will be set by the system. Only the uiTimeMin entry may
  312. // NOT be defaulted.
  313. //
  314. // * Samples designated "random" are ALWAYS loaded into the cache, and locked
  315. // in place. They are never double-buffered, and this call will fail if they
  316. // cannot be loaded. *
  317. //
  318. // Returns: If successful, it returns the sample index it is loaded to, else
  319. // SOUND_ERROR is returned.
  320. //
  321. //*******************************************************************************
  322. UINT32 SoundPlayRandom(STR pFilename, RANDOMPARMS *pParms)
  323. {
  324. UINT32 uiSample, uiTicks;
  325. if(fSoundSystemInit)
  326. {
  327. if((uiSample=SoundLoadSample(pFilename))!=NO_SAMPLE)
  328. {
  329. pSampleList[uiSample].uiFlags|=(SAMPLE_RANDOM|SAMPLE_LOCKED);
  330. if(pParms->uiTimeMin==SOUND_PARMS_DEFAULT)
  331. return(SOUND_ERROR);
  332. else
  333. pSampleList[uiSample].uiTimeMin=pParms->uiTimeMin;
  334. if(pParms->uiTimeMax==SOUND_PARMS_DEFAULT)
  335. pSampleList[uiSample].uiTimeMax=pParms->uiTimeMin;
  336. else
  337. pSampleList[uiSample].uiTimeMax=pParms->uiTimeMax;
  338. pSampleList[uiSample].uiSpeedMin=pParms->uiSpeedMin;
  339. pSampleList[uiSample].uiSpeedMax=pParms->uiSpeedMax;
  340. if(pParms->uiVolMin==SOUND_PARMS_DEFAULT)
  341. pSampleList[uiSample].uiVolMin=guiSoundDefaultVolume;
  342. else
  343. pSampleList[uiSample].uiVolMin=pParms->uiVolMin;
  344. if(pParms->uiVolMax==SOUND_PARMS_DEFAULT)
  345. pSampleList[uiSample].uiVolMax=guiSoundDefaultVolume;
  346. else
  347. pSampleList[uiSample].uiVolMax=pParms->uiVolMax;
  348. if(pParms->uiPanMin==SOUND_PARMS_DEFAULT)
  349. pSampleList[uiSample].uiPanMin=64;
  350. else
  351. pSampleList[uiSample].uiPanMin=pParms->uiPanMin;
  352. if(pParms->uiPanMax==SOUND_PARMS_DEFAULT)
  353. pSampleList[uiSample].uiPanMax=64;
  354. else
  355. pSampleList[uiSample].uiPanMax=pParms->uiPanMax;
  356. if(pParms->uiMaxInstances==SOUND_PARMS_DEFAULT)
  357. pSampleList[uiSample].uiMaxInstances=1;
  358. else
  359. pSampleList[uiSample].uiMaxInstances=pParms->uiMaxInstances;
  360. if(pParms->uiPriority==SOUND_PARMS_DEFAULT)
  361. pSampleList[uiSample].uiPriority=PRIORITY_RANDOM;
  362. else
  363. pSampleList[uiSample].uiPriority=pParms->uiPriority;
  364. pSampleList[uiSample].uiInstances=0;
  365. uiTicks=GetTickCount();
  366. pSampleList[uiSample].uiTimeNext=GetTickCount()+pSampleList[uiSample].uiTimeMin+Random(pSampleList[uiSample].uiTimeMax-pSampleList[uiSample].uiTimeMin);
  367. return(uiSample);
  368. }
  369. }
  370. return(SOUND_ERROR);
  371. }
  372. //*******************************************************************************
  373. // SoundStreamCallback
  374. //
  375. // Plays a sound through streaming, and executes a callback for each buffer
  376. // loaded.
  377. //
  378. // Returns: If successful, it returns the sample index it is loaded to, else
  379. // SOUND_ERROR is returned.
  380. //
  381. //*******************************************************************************
  382. UINT32 SoundStreamCallback(STR pFilename, SOUNDPARMS *pParms, void (*pCallback)(UINT8 *, UINT32, UINT32, UINT32, void *), void *pData)
  383. {
  384. UINT32 uiChannel, uiSoundID;
  385. if(fSoundSystemInit)
  386. {
  387. if((uiChannel=SoundGetFreeChannel())!=SOUND_ERROR)
  388. {
  389. uiSoundID=SoundStartStream(pFilename, uiChannel, pParms);
  390. if(uiSoundID!=SOUND_ERROR)
  391. {
  392. AIL_auto_service_stream(pSoundList[uiChannel].hMSSStream, FALSE);
  393. pSoundList[uiChannel].pCallback=pCallback;
  394. pSoundList[uiChannel].pData=pData;
  395. pSoundList[uiChannel].uiFlags|=SOUND_CALLBACK;
  396. return(uiSoundID);
  397. }
  398. }
  399. }
  400. return(SOUND_ERROR);
  401. }
  402. //*******************************************************************************
  403. // SoundIsPlaying
  404. //
  405. // Returns TRUE/FALSE that an instance of a sound is still playing.
  406. //
  407. //*******************************************************************************
  408. BOOLEAN SoundIsPlaying(UINT32 uiSoundID)
  409. {
  410. UINT32 uiSound;
  411. if(fSoundSystemInit)
  412. {
  413. uiSound=SoundGetIndexByID(uiSoundID);
  414. if(uiSound!=NO_SAMPLE)
  415. return(SoundIndexIsPlaying(uiSound));
  416. }
  417. return(FALSE);
  418. }
  419. //*****************************************************************************************
  420. // SoundIndexIsPlaying
  421. //
  422. // Returns TRUE/FALSE whether a sound channel's sample is currently playing.
  423. //
  424. // Returns BOOLEAN - TRUE = playing, FALSE = stopped or nothing allocated
  425. //
  426. // UINT32 uiSound - Channel number of sound
  427. //
  428. // Created: 2/24/00 Derek Beland
  429. //*****************************************************************************************
  430. BOOLEAN SoundIndexIsPlaying(UINT32 uiSound)
  431. {
  432. INT32 iStatus=SMP_DONE;
  433. if(fSoundSystemInit)
  434. {
  435. if(pSoundList[uiSound].hMSS!=NULL)
  436. iStatus = AIL_sample_status(pSoundList[uiSound].hMSS);
  437. if(pSoundList[uiSound].hMSSStream!=NULL)
  438. iStatus = AIL_stream_status(pSoundList[uiSound].hMSSStream);
  439. if(pSoundList[uiSound].hM3D!=NULL)
  440. iStatus = AIL_3D_sample_status(pSoundList[uiSound].hM3D);
  441. return((iStatus!=SMP_DONE) && (iStatus!=SMP_STOPPED));
  442. }
  443. return(FALSE);
  444. }
  445. //*******************************************************************************
  446. // SoundStop
  447. //
  448. // Stops the playing of a sound instance, if still playing.
  449. //
  450. // Returns: TRUE if the sample was actually stopped, FALSE if it could not be
  451. // found, or was not playing.
  452. //
  453. //*******************************************************************************
  454. BOOLEAN SoundStop(UINT32 uiSoundID)
  455. {
  456. UINT32 uiSound;
  457. if(fSoundSystemInit)
  458. {
  459. if(SoundIsPlaying(uiSoundID))
  460. {
  461. uiSound=SoundGetIndexByID(uiSoundID);
  462. if(uiSound!=NO_SAMPLE)
  463. {
  464. SoundStopIndex(uiSound);
  465. return(TRUE);
  466. }
  467. }
  468. }
  469. return(FALSE);
  470. }
  471. //*******************************************************************************
  472. // SoundStopGroup
  473. //
  474. // Stops multiple instances of sounds that have the indicated priority. This
  475. // is useful for silencing all ambient sounds when switching to menus, etc.
  476. //
  477. // Returns: TRUE if samples were actually stopped, FALSE if none were found
  478. //
  479. //*******************************************************************************
  480. BOOLEAN SoundStopGroup(UINT32 uiPriority)
  481. {
  482. UINT32 uiCount;
  483. BOOLEAN fStopped=FALSE;
  484. if(fSoundSystemInit)
  485. {
  486. for(uiCount=0; uiCount < SOUND_MAX_CHANNELS; uiCount++)
  487. {
  488. if((pSoundList[uiCount].hMSS!=NULL) || (pSoundList[uiCount].hMSSStream!=NULL) || (pSoundList[uiCount].hM3D!=NULL))
  489. {
  490. if(pSoundList[uiCount].uiPriority==uiPriority)
  491. {
  492. SoundStop(pSoundList[uiCount].uiSoundID);
  493. fStopped=TRUE;
  494. }
  495. }
  496. }
  497. }
  498. return(fStopped);
  499. }
  500. //*******************************************************************************
  501. // SoundSetMemoryLimit
  502. //
  503. // Specifies how much memory the sound system is allowed to dynamically
  504. // allocate. Once this limit is reached, the cache code will start dropping the
  505. // least-used samples. You should always set the limit higher by a good margin
  506. // than your actual memory requirements, to give the cache some elbow room.
  507. //
  508. // Returns: TRUE if the limit was set, or FALSE if the memory already used is
  509. // greater than the limit requested.
  510. //
  511. //*******************************************************************************
  512. BOOLEAN SoundSetMemoryLimit(UINT32 uiLimit)
  513. {
  514. if(guiSoundMemoryLimit < guiSoundMemoryUsed)
  515. return(FALSE);
  516. guiSoundMemoryLimit=uiLimit;
  517. return(TRUE);
  518. }
  519. //*******************************************************************************
  520. // SoundGetSystemInfo
  521. //
  522. // Returns information about the capabilities of the hardware. Currently does
  523. // nothing.
  524. //
  525. // Returns: FALSE, always
  526. //
  527. //*******************************************************************************
  528. BOOLEAN SoundGetSystemInfo(void)
  529. {
  530. return(FALSE);
  531. }
  532. //*******************************************************************************
  533. // SoundSetDigitalVolume
  534. //
  535. // Sets the master volume for the digital section. All sample volumes will be
  536. // affected by this setting.
  537. //
  538. // Returns: TRUE, always
  539. //
  540. //*******************************************************************************
  541. BOOLEAN SoundSetDigitalVolume(UINT32 uiVolume)
  542. {
  543. UINT32 uiVolClip;
  544. if(fSoundSystemInit)
  545. {
  546. uiVolClip=__min(uiVolume, 127);
  547. AIL_set_digital_master_volume(hSoundDriver, uiVolClip);
  548. }
  549. return(TRUE);
  550. }
  551. //*******************************************************************************
  552. // SoundGetDigitalVolume
  553. //
  554. // Returns the current value of the digital master volume.
  555. //
  556. // Returns: 0-127
  557. //
  558. //*******************************************************************************
  559. UINT32 SoundGetDigitalVolume(UINT32 uiVolume)
  560. {
  561. if(fSoundSystemInit)
  562. return((UINT32)AIL_digital_master_volume(hSoundDriver));
  563. else
  564. return(0);
  565. }
  566. //*****************************************************************************************
  567. // SoundSetDefaultVolume
  568. //
  569. // Sets the volume to use when a default is not chosen.
  570. //
  571. // Returns BOOLEAN -
  572. //
  573. // UINT32 uiVolume -
  574. //
  575. // Created: 3/28/00 Derek Beland
  576. //*****************************************************************************************
  577. void SoundSetDefaultVolume(UINT32 uiVolume)
  578. {
  579. guiSoundDefaultVolume=__min(uiVolume, 127);
  580. }
  581. //*****************************************************************************************
  582. // SoundGetDefaultVolume
  583. //
  584. //
  585. //
  586. // Returns UINT32 -
  587. //
  588. // UINT32 uiVolume -
  589. //
  590. // Created: 3/28/00 Derek Beland
  591. //*****************************************************************************************
  592. UINT32 SoundGetDefaultVolume(void)
  593. {
  594. return(guiSoundDefaultVolume);
  595. }
  596. //*******************************************************************************
  597. // SoundStopAll
  598. //
  599. // Stops all currently playing sounds.
  600. //
  601. // Returns: TRUE, always
  602. //
  603. //*******************************************************************************
  604. BOOLEAN SoundStopAll(void)
  605. {
  606. UINT32 uiCount;
  607. if(fSoundSystemInit)
  608. {
  609. for(uiCount=0; uiCount < SOUND_MAX_CHANNELS; uiCount++)
  610. if(!pSoundList[uiCount].fMusic)
  611. SoundStopIndex(uiCount);
  612. }
  613. return(TRUE);
  614. }
  615. //*****************************************************************************************
  616. // SoundSetFadeVolume
  617. //
  618. // Sets a target volume to fade towards. The fade volume is updated in SoundServiceStreams.
  619. //
  620. // Returns BOOLEAN - TRUE if the fading volume was set, FALSE otherwise
  621. //
  622. // UINT32 uiSoundID - ID of sound
  623. // UINT32 uiVolume - Volume to fade towards (0-127)
  624. // UINT32 uiRate - Total time taken to change volume
  625. // BOOLEAN fStopAtZero - If TRUE, sample is stopped when volume reaches zero
  626. //
  627. // Created: 3/17/00 Derek Beland
  628. //*****************************************************************************************
  629. BOOLEAN SoundSetFadeVolume(UINT32 uiSoundID, UINT32 uiVolume, UINT32 uiRate, BOOLEAN fStopAtZero)
  630. {
  631. UINT32 uiSound, uiVolCap, uiVolumeDiff;
  632. if(fSoundSystemInit)
  633. {
  634. uiVolCap=__min(uiVolume, 127);
  635. if((uiSound=SoundGetIndexByID(uiSoundID))!=NO_SAMPLE)
  636. {
  637. uiVolumeDiff = abs(uiVolCap - SoundGetVolumeIndex(uiSound));
  638. if(!uiVolumeDiff)
  639. return(FALSE);
  640. pSoundList[uiSound].uiFadeVolume = uiVolCap;
  641. pSoundList[uiSound].fStopAtZero = fStopAtZero;
  642. pSoundList[uiSound].uiFadeRate = uiRate / uiVolumeDiff;
  643. pSoundList[uiSound].uiFadeTime = GetTickCount();
  644. return(TRUE);
  645. }
  646. }
  647. return(FALSE);
  648. }
  649. //*******************************************************************************
  650. // SoundSetVolume
  651. //
  652. // Sets the volume on a currently playing sound.
  653. //
  654. // Returns: TRUE if the volume was actually set on the sample, FALSE if the
  655. // sample had already expired or couldn't be found
  656. //
  657. //*******************************************************************************
  658. BOOLEAN SoundSetVolume(UINT32 uiSoundID, UINT32 uiVolume)
  659. {
  660. UINT32 uiSound, uiVolCap;
  661. if(fSoundSystemInit)
  662. {
  663. uiVolCap=__min(uiVolume, 127);
  664. if((uiSound=SoundGetIndexByID(uiSoundID))!=NO_SAMPLE)
  665. {
  666. pSoundList[uiSound].uiFadeVolume = uiVolume;
  667. return(SoundSetVolumeIndex(uiSound, uiVolume));
  668. }
  669. }
  670. return(FALSE);
  671. }
  672. //*****************************************************************************************
  673. // SoundSetVolumeIndex
  674. //
  675. // Sounds the volume on a sound channel.
  676. //
  677. // Returns BOOLEAN - TRUE if the volume was set
  678. //
  679. // UINT32 uiChannel - Sound channel
  680. // UINT32 uiVolume - New volume 0-127
  681. //
  682. // Created: 3/17/00 Derek Beland
  683. //*****************************************************************************************
  684. BOOLEAN SoundSetVolumeIndex(UINT32 uiChannel, UINT32 uiVolume)
  685. {
  686. UINT32 uiVolCap;
  687. if(fSoundSystemInit)
  688. {
  689. uiVolCap=__min(uiVolume, 127);
  690. if(pSoundList[uiChannel].hMSS!=NULL)
  691. AIL_set_sample_volume(pSoundList[uiChannel].hMSS, uiVolCap);
  692. if(pSoundList[uiChannel].hMSSStream!=NULL)
  693. AIL_set_stream_volume(pSoundList[uiChannel].hMSSStream, uiVolCap);
  694. if(pSoundList[uiChannel].hM3D!=NULL)
  695. AIL_set_3D_sample_volume(pSoundList[uiChannel].hM3D, uiVolCap);
  696. return(TRUE);
  697. }
  698. return(FALSE);
  699. }
  700. //*******************************************************************************
  701. // SoundSetPan
  702. //
  703. // Sets the pan on a currently playing sound.
  704. //
  705. // Returns: TRUE if the pan was actually set on the sample, FALSE if the
  706. // sample had already expired or couldn't be found
  707. //
  708. //*******************************************************************************
  709. BOOLEAN SoundSetPan(UINT32 uiSoundID, UINT32 uiPan)
  710. {
  711. UINT32 uiSound, uiPanCap;
  712. if(fSoundSystemInit)
  713. {
  714. uiPanCap=__min(uiPan, 127);
  715. if((uiSound=SoundGetIndexByID(uiSoundID))!=NO_SAMPLE)
  716. {
  717. if(pSoundList[uiSound].hMSS!=NULL)
  718. AIL_set_sample_pan(pSoundList[uiSound].hMSS, uiPanCap);
  719. if(pSoundList[uiSound].hMSSStream!=NULL)
  720. AIL_set_stream_pan(pSoundList[uiSound].hMSSStream, uiPanCap);
  721. return(TRUE);
  722. }
  723. }
  724. return(FALSE);
  725. }
  726. //*******************************************************************************
  727. // SoundSetFrequency
  728. //
  729. // Sets the frequency on a currently playing sound.
  730. //
  731. // Returns: TRUE if the frequency was actually set on the sample, FALSE if the
  732. // sample had already expired or couldn't be found
  733. //
  734. //*******************************************************************************
  735. BOOLEAN SoundSetFrequency(UINT32 uiSoundID, UINT32 uiFreq)
  736. {
  737. UINT32 uiSound, uiFreqCap;
  738. if(fSoundSystemInit)
  739. {
  740. uiFreqCap=__min(uiFreq, 44100);
  741. if((uiSound=SoundGetIndexByID(uiSoundID))!=NO_SAMPLE)
  742. {
  743. if(pSoundList[uiSound].hMSS!=NULL)
  744. AIL_set_sample_playback_rate(pSoundList[uiSound].hMSS, uiFreqCap);
  745. if(pSoundList[uiSound].hMSSStream!=NULL)
  746. AIL_set_stream_playback_rate(pSoundList[uiSound].hMSSStream, uiFreqCap);
  747. if(pSoundList[uiSound].hM3D!=NULL)
  748. AIL_set_3D_sample_playback_rate(pSoundList[uiSound].hM3D, uiFreqCap);
  749. return(TRUE);
  750. }
  751. }
  752. return(FALSE);
  753. }
  754. //*******************************************************************************
  755. // SoundSetLoop
  756. //
  757. // Sets the loop on a currently playing sound.
  758. //
  759. // Returns: TRUE if the loop was actually set on the sample, FALSE if the
  760. // sample had already expired or couldn't be found
  761. //
  762. //*******************************************************************************
  763. BOOLEAN SoundSetLoop(UINT32 uiSoundID, UINT32 uiLoop)
  764. {
  765. UINT32 uiSound, uiLoopCap;
  766. if(fSoundSystemInit)
  767. {
  768. uiLoopCap=__min(uiLoop, 10000);
  769. if((uiSound=SoundGetIndexByID(uiSoundID))!=NO_SAMPLE)
  770. {
  771. if(pSoundList[uiSound].hMSS!=NULL)
  772. AIL_set_sample_loop_count(pSoundList[uiSound].hMSS, uiLoopCap);
  773. if(pSoundList[uiSound].hMSSStream!=NULL)
  774. AIL_set_stream_loop_count(pSoundList[uiSound].hMSSStream, uiLoopCap);
  775. if(pSoundList[uiSound].hM3D!=NULL)
  776. AIL_set_3D_sample_loop_count(pSoundList[uiSound].hM3D, uiLoopCap);
  777. return(TRUE);
  778. }
  779. }
  780. return(FALSE);
  781. }
  782. //*******************************************************************************
  783. // SoundGetVolume
  784. //
  785. // Returns the current volume setting of a sound that is playing. If the sound
  786. // has expired, or could not be found, SOUND_ERROR is returned.
  787. //
  788. //*******************************************************************************
  789. UINT32 SoundGetVolume(UINT32 uiSoundID)
  790. {
  791. UINT32 uiSound;
  792. if(fSoundSystemInit)
  793. {
  794. if((uiSound=SoundGetIndexByID(uiSoundID))!=NO_SAMPLE)
  795. return(SoundGetVolumeIndex(uiSound));
  796. }
  797. return(SOUND_ERROR);
  798. }
  799. //*****************************************************************************************
  800. // SoundGetVolumeIndex
  801. //
  802. // Returns the current volume of a sound channel.
  803. //
  804. // Returns UINT32 - Volume 0-127
  805. //
  806. // UINT32 uiChannel - Channel
  807. //
  808. // Created: 3/17/00 Derek Beland
  809. //*****************************************************************************************
  810. UINT32 SoundGetVolumeIndex(UINT32 uiChannel)
  811. {
  812. if(fSoundSystemInit)
  813. {
  814. if(pSoundList[uiChannel].hMSS!=NULL)
  815. return((UINT32)AIL_sample_volume(pSoundList[uiChannel].hMSS));
  816. if(pSoundList[uiChannel].hMSSStream!=NULL)
  817. return((UINT32)AIL_stream_volume(pSoundList[uiChannel].hMSSStream));
  818. if(pSoundList[uiChannel].hM3D!=NULL)
  819. return((UINT32)AIL_3D_sample_volume(pSoundList[uiChannel].hM3D));
  820. }
  821. return(SOUND_ERROR);
  822. }
  823. //*******************************************************************************
  824. // SoundGetPan
  825. //
  826. // Returns the current pan setting of a sound that is playing. If the sound
  827. // has expired, or could not be found, SOUND_ERROR is returned.
  828. //
  829. //*******************************************************************************
  830. UINT32 SoundGetPan(UINT32 uiSoundID)
  831. {
  832. UINT32 uiSound;
  833. if(fSoundSystemInit)
  834. {
  835. if((uiSound=SoundGetIndexByID(uiSoundID))!=NO_SAMPLE)
  836. {
  837. if(pSoundList[uiSound].hMSS!=NULL)
  838. return((UINT32)AIL_sample_pan(pSoundList[uiSound].hMSS));
  839. if(pSoundList[uiSound].hMSSStream!=NULL)
  840. return((UINT32)AIL_stream_pan(pSoundList[uiSound].hMSSStream));
  841. }
  842. }
  843. return(SOUND_ERROR);
  844. }
  845. //*******************************************************************************
  846. // SoundGetFrequency
  847. //
  848. // Returns the current frequency setting of a sound that is playing. If the sound
  849. // has expired, or could not be found, SOUND_ERROR is returned.
  850. //
  851. //*******************************************************************************
  852. UINT32 SoundGetFrequency(UINT32 uiSoundID)
  853. {
  854. UINT32 uiSound;
  855. if(fSoundSystemInit)
  856. {
  857. if((uiSound=SoundGetIndexByID(uiSoundID))!=NO_SAMPLE)
  858. {
  859. if(pSoundList[uiSound].hMSS!=NULL)
  860. return((UINT32)AIL_sample_playback_rate(pSoundList[uiSound].hMSS));
  861. if(pSoundList[uiSound].hMSSStream!=NULL)
  862. return((UINT32)AIL_stream_playback_rate(pSoundList[uiSound].hMSSStream));
  863. if(pSoundList[uiSound].hM3D!=NULL)
  864. return((UINT32)AIL_3D_sample_playback_rate(pSoundList[uiSound].hM3D));
  865. }
  866. }
  867. return(SOUND_ERROR);
  868. }
  869. //*******************************************************************************
  870. // SoundGetLoop
  871. //
  872. // Returns the current loop count of a sound that is playing. If the sound
  873. // has expired, or could not be found, SOUND_ERROR is returned.
  874. //
  875. //*******************************************************************************
  876. UINT32 SoundGetLoop(UINT32 uiSoundID)
  877. {
  878. UINT32 uiSound;
  879. if(fSoundSystemInit)
  880. {
  881. if((uiSound=SoundGetIndexByID(uiSoundID))!=NO_SAMPLE)
  882. {
  883. if(pSoundList[uiSound].hMSS!=NULL)
  884. return((UINT32)AIL_sample_loop_count(pSoundList[uiSound].hMSS));
  885. if(pSoundList[uiSound].hMSSStream!=NULL)
  886. return((UINT32)AIL_stream_loop_count(pSoundList[uiSound].hMSSStream));
  887. if(pSoundList[uiSound].hM3D!=NULL)
  888. return((UINT32)AIL_3D_sample_loop_count(pSoundList[uiSound].hM3D));
  889. }
  890. }
  891. return(SOUND_ERROR);
  892. }
  893. //*******************************************************************************
  894. // SoundServiceRandom
  895. //
  896. // This function should be polled by the application if random samples are
  897. // used. The time marks on each are checked and if it is time to spawn a new
  898. // instance of the sound, the number already in existance are checked, and if
  899. // there is room, a new one is made and the count updated.
  900. // If random samples are not being used, there is no purpose in polling this
  901. // function.
  902. //
  903. // Returns: TRUE if a new random sound was created, FALSE if nothing was done.
  904. //
  905. //*******************************************************************************
  906. BOOLEAN SoundServiceRandom(void)
  907. {
  908. UINT32 uiCount;
  909. for(uiCount=0; uiCount < SOUND_MAX_CACHED; uiCount++)
  910. {
  911. if(!(pSampleList[uiCount].uiFlags&SAMPLE_RANDOM_MANUAL) && SoundRandomShouldPlay(uiCount))
  912. SoundStartRandom(uiCount);
  913. }
  914. return(FALSE);
  915. }
  916. //*******************************************************************************
  917. // SoundRandomShouldPlay
  918. //
  919. // Determines whether a random sound is ready for playing or not.
  920. //
  921. // Returns: TRUE if a the sample should be played.
  922. //
  923. //*******************************************************************************
  924. BOOLEAN SoundRandomShouldPlay(UINT32 uiSample)
  925. {
  926. UINT32 uiTicks;
  927. uiTicks=GetTickCount();
  928. if(pSampleList[uiSample].uiFlags&SAMPLE_RANDOM)
  929. if(pSampleList[uiSample].uiTimeNext <= GetTickCount())
  930. if(pSampleList[uiSample].uiInstances < pSampleList[uiSample].uiMaxInstances)
  931. return(TRUE);
  932. return(FALSE);
  933. }
  934. //*******************************************************************************
  935. // SoundStartRandom
  936. //
  937. // Starts an instance of a random sample.
  938. //
  939. // Returns: TRUE if a new random sound was created, FALSE if nothing was done.
  940. //
  941. //*******************************************************************************
  942. UINT32 SoundStartRandom(UINT32 uiSample)
  943. {
  944. UINT32 uiChannel, uiSoundID;
  945. SOUNDPARMS spParms;
  946. if((uiChannel=SoundGetFreeChannel())!=SOUND_ERROR)
  947. {
  948. memset(&spParms, 0xff, sizeof(SOUNDPARMS));
  949. // spParms.uiSpeed=pSampleList[uiSample].uiSpeedMin+Random(pSampleList[uiSample].uiSpeedMax-pSampleList[uiSample].uiSpeedMin);
  950. spParms.uiVolume=pSampleList[uiSample].uiVolMin+Random(pSampleList[uiSample].uiVolMax-pSampleList[uiSample].uiVolMin);
  951. spParms.uiPan=pSampleList[uiSample].uiPanMin+Random(pSampleList[uiSample].uiPanMax-pSampleList[uiSample].uiPanMin);
  952. spParms.uiLoop=1;
  953. spParms.uiPriority=pSampleList[uiSample].uiPriority;
  954. if((uiSoundID=SoundStartSample(uiSample, uiChannel, &spParms))!=SOUND_ERROR)
  955. {
  956. pSampleList[uiSample].uiTimeNext=GetTickCount()+pSampleList[uiSample].uiTimeMin+Random(pSampleList[uiSample].uiTimeMax-pSampleList[uiSample].uiTimeMin);
  957. pSampleList[uiSample].uiInstances++;
  958. return(uiSoundID);
  959. }
  960. }
  961. return(NO_SAMPLE);
  962. }
  963. //*******************************************************************************
  964. // SoundStopAllRandom
  965. //
  966. // This function should be polled by the application if random samples are
  967. // used. The time marks on each are checked and if it is time to spawn a new
  968. // instance of the sound, the number already in existance are checked, and if
  969. // there is room, a new one is made and the count updated.
  970. // If random samples are not being used, there is no purpose in polling this
  971. // function.
  972. //
  973. // Returns: TRUE if a new random sound was created, FALSE if nothing was done.
  974. //
  975. //*******************************************************************************
  976. BOOLEAN SoundStopAllRandom(void)
  977. {
  978. UINT32 uiChannel, uiSample;
  979. // Stop all currently playing random sounds
  980. for(uiChannel=0; uiChannel < SOUND_MAX_CHANNELS; uiChannel++)
  981. {
  982. if((pSoundList[uiChannel].hMSS!=NULL) || (pSoundList[uiChannel].hM3D!=NULL))
  983. {
  984. uiSample=pSoundList[uiChannel].uiSample;
  985. // if this was a random sample, decrease the iteration count
  986. if(pSampleList[uiSample].uiFlags&SAMPLE_RANDOM)
  987. SoundStopIndex(uiChannel);
  988. }
  989. }
  990. // Unlock all random sounds so they can be dumped from the cache, and
  991. // take the random flag off so they won't be serviced/played
  992. for(uiSample=0; uiSample < SOUND_MAX_CACHED; uiSample++)
  993. {
  994. if(pSampleList[uiSample].uiFlags & SAMPLE_RANDOM)
  995. pSampleList[uiSample].uiFlags &= (~(SAMPLE_RANDOM | SAMPLE_LOCKED));
  996. }
  997. return(FALSE);
  998. }
  999. //*******************************************************************************
  1000. // SoundServiceStreams
  1001. //
  1002. // Can be polled in tight loops where sound buffers might starve due to heavy
  1003. // hardware use, etc. Streams DO NOT normally need to be serviced manually, but
  1004. // in some cases (heavy file loading) it might be desirable.
  1005. //
  1006. // If you are using the end of sample callbacks, you must call this function
  1007. // periodically to check the sample's status.
  1008. //
  1009. // Returns: TRUE always.
  1010. //
  1011. //*******************************************************************************
  1012. BOOLEAN SoundServiceStreams(void)
  1013. {
  1014. UINT32 uiCount, uiSpeed, uiBuffLen, uiBytesPerSample;
  1015. UINT8 *pBuffer;
  1016. void *pData;
  1017. if(fSoundSystemInit)
  1018. {
  1019. for(uiCount=0; uiCount < SOUND_MAX_CHANNELS; uiCount++)
  1020. {
  1021. if(pSoundList[uiCount].hMSSStream!=NULL)
  1022. {
  1023. if(AIL_service_stream(pSoundList[uiCount].hMSSStream, 0))
  1024. {
  1025. if(pSoundList[uiCount].uiFlags&SOUND_CALLBACK)
  1026. {
  1027. uiSpeed=pSoundList[uiCount].hMSSStream->datarate;
  1028. uiBuffLen=pSoundList[uiCount].hMSSStream->bufsize;
  1029. pBuffer=pSoundList[uiCount].hMSSStream->bufs[pSoundList[uiCount].hMSSStream->buf1];
  1030. uiBytesPerSample=pSoundList[uiCount].hMSSStream->samp->format;
  1031. pData=pSoundList[uiCount].pData;
  1032. pSoundList[uiCount].pCallback(pBuffer, uiBuffLen, uiSpeed, uiBytesPerSample, pData);
  1033. }
  1034. }
  1035. }
  1036. if(pSoundList[uiCount].hMSS || pSoundList[uiCount].hMSSStream || pSoundList[uiCount].hM3D)
  1037. {
  1038. // If a sound has a handle, but isn't playing, stop it and free up the handle
  1039. if(!SoundIsPlaying(pSoundList[uiCount].uiSoundID))
  1040. SoundStopIndex(uiCount);
  1041. else
  1042. { // Check the volume fades on currently playing sounds
  1043. UINT32 uiVolume = SoundGetVolumeIndex(uiCount);
  1044. UINT32 uiTime = GetTickCount();
  1045. if((uiVolume != pSoundList[uiCount].uiFadeVolume) && (uiTime >= (pSoundList[uiCount].uiFadeTime + pSoundList[uiCount].uiFadeRate)) )
  1046. {
  1047. if(uiVolume < pSoundList[uiCount].uiFadeVolume)
  1048. SoundSetVolumeIndex(uiCount, ++uiVolume);
  1049. else if(uiVolume > pSoundList[uiCount].uiFadeVolume)
  1050. {
  1051. uiVolume--;
  1052. if(!uiVolume && pSoundList[uiCount].fStopAtZero)
  1053. SoundStopIndex(uiCount);
  1054. else
  1055. SoundSetVolumeIndex(uiCount, uiVolume);
  1056. }
  1057. pSoundList[uiCount].uiFadeTime = uiTime;
  1058. }
  1059. }
  1060. }
  1061. }
  1062. }
  1063. return(TRUE);
  1064. }
  1065. //*******************************************************************************
  1066. // SoundGetPosition
  1067. //
  1068. // Reports the current time position of the sample.
  1069. //
  1070. // Note: You should be checking SoundIsPlaying very carefully while
  1071. // calling this function.
  1072. //
  1073. // Returns: The current time of the sample in milliseconds.
  1074. //
  1075. //*******************************************************************************
  1076. UINT32 SoundGetPosition(UINT32 uiSoundID)
  1077. {
  1078. //UINT32 uiSound, uiFreq=0, uiPosition=0, uiBytesPerSample=0, uiFormat=0;
  1079. UINT32 uiSound, uiTime, uiPosition;
  1080. if(fSoundSystemInit)
  1081. {
  1082. if((uiSound=SoundGetIndexByID(uiSoundID))!=NO_SAMPLE)
  1083. {
  1084. /* if(pSoundList[uiSound].hMSSStream!=NULL)
  1085. {
  1086. uiPosition=(UINT32)AIL_stream_position(pSoundList[uiSound].hMSSStream);
  1087. uiFreq=(UINT32)pSoundList[uiSound].hMSSStream->samp->playback_rate;
  1088. uiFormat=(UINT32)pSoundList[uiSound].hMSSStream->samp->format;
  1089. }
  1090. else if(pSoundList[uiSound].hMSS!=NULL)
  1091. {
  1092. uiPosition=(UINT32)AIL_sample_position(pSoundList[uiSound].hMSS);
  1093. uiFreq=(UINT32)pSoundList[uiSound].hMSS->playback_rate;
  1094. uiFormat=(UINT32)pSoundList[uiSound].hMSS->format;
  1095. }
  1096. }
  1097. switch(uiFormat)
  1098. {
  1099. case DIG_F_MONO_8: uiBytesPerSample=1;
  1100. break;
  1101. case DIG_F_MONO_16: uiBytesPerSample=2;
  1102. break;
  1103. case DIG_F_STEREO_8: uiBytesPerSample=2;
  1104. break;
  1105. case DIG_F_STEREO_16: uiBytesPerSample=4;
  1106. break;
  1107. }
  1108. if(uiFreq)
  1109. {
  1110. return((uiPosition/uiBytesPerSample)/(uiFreq/1000));
  1111. }
  1112. }
  1113. */
  1114. uiTime=GetTickCount();
  1115. // check for rollover
  1116. if(uiTime < pSoundList[uiSound].uiTimeStamp)
  1117. uiPosition=(0-pSoundList[uiSound].uiTimeStamp)+uiTime;
  1118. else
  1119. uiPosition=(uiTime-pSoundList[uiSound].uiTimeStamp);
  1120. return(uiPosition);
  1121. }
  1122. }
  1123. return(0);
  1124. }
  1125. //*****************************************************************************************
  1126. //
  1127. // SoundGetMilliSecondPosition
  1128. //
  1129. // Get the sounds total length and our current position within that
  1130. // sound in milliseconds
  1131. //
  1132. //
  1133. // Returns BOOLEAN: TRUE if the sound exists.
  1134. //
  1135. // Created by: Gilles Beauparlant
  1136. // Created on: 7/23/99
  1137. //
  1138. //*****************************************************************************************
  1139. BOOLEAN SoundGetMilliSecondPosition(UINT32 uiSoundID, UINT32 *puiTotalMilliseconds, UINT32 *puiCurrentMilliseconds)
  1140. {
  1141. UINT32 uiSound;
  1142. if(fSoundSystemInit)
  1143. {
  1144. uiSound=SoundGetIndexByID(uiSoundID);
  1145. if(uiSound!=NO_SAMPLE)
  1146. {
  1147. if(pSoundList[uiSound].hMSS!=NULL)
  1148. {
  1149. AIL_sample_ms_position(pSoundList[uiSound].hMSS, puiTotalMilliseconds, puiCurrentMilliseconds);
  1150. return TRUE;
  1151. }
  1152. if(pSoundList[uiSound].hMSSStream!=NULL)
  1153. {
  1154. AIL_stream_ms_position(pSoundList[uiSound].hMSSStream, puiTotalMilliseconds, puiCurrentMilliseconds);
  1155. return TRUE;
  1156. }
  1157. }
  1158. }
  1159. *puiTotalMilliseconds = 0;
  1160. *puiCurrentMilliseconds = 0;
  1161. return FALSE;
  1162. }
  1163. //*******************************************************************************
  1164. // Cacheing Subsystem
  1165. //*******************************************************************************
  1166. //*******************************************************************************
  1167. // SoundInitCache
  1168. //
  1169. // Zeros out the structures of the sample list.
  1170. //
  1171. //*******************************************************************************
  1172. BOOLEAN SoundInitCache(void)
  1173. {
  1174. UINT32 uiCount;
  1175. for(uiCount=0; uiCount < SOUND_MAX_CACHED; uiCount++)
  1176. memset(&pSampleList[uiCount], 0, sizeof(SAMPLETAG));
  1177. return(TRUE);
  1178. }
  1179. //*******************************************************************************
  1180. // SoundShutdownCache
  1181. //
  1182. // Empties out the cache.
  1183. //
  1184. // Returns: TRUE, always
  1185. //
  1186. //*******************************************************************************
  1187. BOOLEAN SoundShutdownCache(void)
  1188. {
  1189. SoundEmptyCache();
  1190. return(TRUE);
  1191. }
  1192. //*******************************************************************************
  1193. // SoundSetCacheThreshold
  1194. //
  1195. // Sets the sound size above which samples will be played double-buffered,
  1196. // below which they will be loaded into the cache.
  1197. //
  1198. // Returns: TRUE, always
  1199. //
  1200. //*******************************************************************************
  1201. BOOLEAN SoundSetCacheThreshhold(UINT32 uiThreshold)
  1202. {
  1203. if(uiThreshold==0)
  1204. guiSoundCacheThreshold=SOUND_DEFAULT_THRESH;
  1205. else
  1206. guiSoundCacheThreshold=uiThreshold;
  1207. return(TRUE);
  1208. }
  1209. //*******************************************************************************
  1210. // SoundEmptyCache
  1211. //
  1212. // Frees up all samples in the cache.
  1213. //
  1214. // Returns: TRUE, always
  1215. //
  1216. //*******************************************************************************
  1217. BOOLEAN SoundEmptyCache(void)
  1218. {
  1219. UINT32 uiCount;
  1220. SoundStopAll();
  1221. for(uiCount=0; uiCount < SOUND_MAX_CACHED; uiCount++)
  1222. SoundFreeSampleIndex(uiCount);
  1223. return(TRUE);
  1224. }
  1225. //*******************************************************************************
  1226. // SoundLoadSample
  1227. //
  1228. // Frees up all samples in the cache.
  1229. //
  1230. // Returns: TRUE, always
  1231. //
  1232. //*******************************************************************************
  1233. UINT32 SoundLoadSample(STR pFilename)
  1234. {
  1235. UINT32 uiSample=NO_SAMPLE;
  1236. if((uiSample=SoundGetCached(pFilename))!=NO_SAMPLE)
  1237. return(uiSample);
  1238. return(SoundLoadDisk(pFilename));
  1239. }
  1240. //*******************************************************************************
  1241. // SoundLockSample
  1242. //
  1243. // Locks a sample into cache memory, so the cacheing system won't release it
  1244. // when it needs room.
  1245. //
  1246. // Returns: The sample index if successful, NO_SAMPLE if the file wasn't found
  1247. // in the cache.
  1248. //
  1249. //*******************************************************************************
  1250. UINT32 SoundLockSample(STR pFilename)
  1251. {
  1252. UINT32 uiSample;
  1253. if((uiSample=SoundGetCached(pFilename))!=NO_SAMPLE)
  1254. {
  1255. pSampleList[uiSample].uiFlags|=SAMPLE_LOCKED;
  1256. return(uiSample);
  1257. }
  1258. return(NO_SAMPLE);
  1259. }
  1260. //*******************************************************************************
  1261. // SoundUnlockSample
  1262. //
  1263. // Removes the lock on a sample so the cache is free to dump it when necessary.
  1264. //
  1265. // Returns: The sample index if successful, NO_SAMPLE if the file wasn't found
  1266. // in the cache.
  1267. //
  1268. //*******************************************************************************
  1269. UINT32 SoundUnlockSample(STR pFilename)
  1270. {
  1271. UINT32 uiSample;
  1272. if((uiSample=SoundGetCached(pFilename))!=NO_SAMPLE)
  1273. {
  1274. pSampleList[uiSample].uiFlags&=(~SAMPLE_LOCKED);
  1275. return(uiSample);
  1276. }
  1277. return(NO_SAMPLE);
  1278. }
  1279. //*******************************************************************************
  1280. // SoundFreeSample
  1281. //
  1282. // Releases the resources associated with a sample from the cache.
  1283. //
  1284. // Returns: The sample index if successful, NO_SAMPLE if the file wasn't found
  1285. // in the cache.
  1286. //
  1287. //*******************************************************************************
  1288. UINT32 SoundFreeSample(STR pFilename)
  1289. {
  1290. UINT32 uiSample;
  1291. if((uiSample=SoundGetCached(pFilename))!=NO_SAMPLE)
  1292. {
  1293. if(!SoundSampleIsPlaying(uiSample))
  1294. {
  1295. SoundFreeSampleIndex(uiSample);
  1296. return(uiSample);
  1297. }
  1298. }
  1299. return(NO_SAMPLE);
  1300. }
  1301. //*******************************************************************************
  1302. // SoundFreeGroup
  1303. //
  1304. // Releases a group of samples with a given priority. Does not take into
  1305. // account locked/unlocked status.
  1306. //
  1307. // Returns: TRUE if samples were freed, FALSE if none
  1308. //
  1309. // NOTE:
  1310. // This function is going to be removed! If you are attempting to stop all
  1311. // random sounds, call SoundStopAllRandom instead.
  1312. //
  1313. //*******************************************************************************
  1314. BOOLEAN SoundFreeGroup(UINT32 uiPriority)
  1315. {
  1316. BOOLEAN fFreed=FALSE;
  1317. SoundStopGroup(uiPriority);
  1318. return(fFreed);
  1319. }
  1320. //*******************************************************************************
  1321. // SoundGetCached
  1322. //
  1323. // Tries to locate a sound by looking at what is currently loaded in the
  1324. // cache.
  1325. //
  1326. // Returns: The sample index if successful, NO_SAMPLE if the file wasn't found
  1327. // in the cache.
  1328. //
  1329. //*******************************************************************************
  1330. UINT32 SoundGetCached(STR pFilename)
  1331. {
  1332. UINT32 uiCount;
  1333. for(uiCount=0; uiCount < SOUND_MAX_CACHED; uiCount++)
  1334. {
  1335. if(_stricmp(pSampleList[uiCount].pName, pFilename)==0)
  1336. return(uiCount);
  1337. }
  1338. return(NO_SAMPLE);
  1339. }
  1340. //*******************************************************************************
  1341. // SoundLoadDisk
  1342. //
  1343. // Loads a sound file from disk into the cache, allocating memory and a slot
  1344. // for storage.
  1345. //
  1346. //
  1347. // Returns: The sample index if successful, NO_SAMPLE if the file wasn't found
  1348. // in the cache.
  1349. //
  1350. //*******************************************************************************
  1351. UINT32 SoundLoadDisk(STR pFilename)
  1352. {
  1353. HWFILE hFile;
  1354. UINT32 uiSize, uiSample;
  1355. BOOLEAN fRemoved=TRUE;
  1356. Assert(pFilename!=NULL);
  1357. if((hFile=FileOpen(pFilename, FILE_ACCESS_READ, FALSE))!=0)
  1358. {
  1359. uiSize=FileGetSize(hFile);
  1360. // if insufficient memory, start unloading old samples until either
  1361. // there's nothing left to unload, or we fit
  1362. fRemoved=TRUE;
  1363. while(((uiSize + guiSoundMemoryUsed) > guiSoundMemoryLimit) && (fRemoved))
  1364. fRemoved=SoundCleanCache();
  1365. // if we still don't fit
  1366. if((uiSize + guiSoundMemoryUsed) > guiSoundMemoryLimit)
  1367. {
  1368. FastDebugMsg(String("SoundLoadDisk: ERROR: trying to play %s, not enough memory\n", pFilename ) );
  1369. FileClose(hFile);
  1370. return(NO_SAMPLE);
  1371. }
  1372. // if all the sample slots are full, unloading one
  1373. if((uiSample=SoundGetEmptySample())==NO_SAMPLE)
  1374. {
  1375. SoundCleanCache();
  1376. uiSample=SoundGetEmptySample();
  1377. }
  1378. // if we still don't have a sample slot
  1379. if(uiSample==NO_SAMPLE)
  1380. {
  1381. FastDebugMsg(String("SoundLoadDisk: ERROR: Trying to play %s, sound channels are full\n", pFilename ) );
  1382. FileClose(hFile);
  1383. return(NO_SAMPLE);
  1384. }
  1385. memset(&pSampleList[uiSample], 0, sizeof(SAMPLETAG));
  1386. if((pSampleList[uiSample].pData=AIL_mem_alloc_lock(uiSize))==NULL)
  1387. {
  1388. FastDebugMsg(String("SoundLoadDisk: ERROR: Trying to play %s, AIL channels are full\n", pFilename ) );
  1389. FileClose(hFile);
  1390. return(NO_SAMPLE);
  1391. }
  1392. guiSoundMemoryUsed+=uiSize;
  1393. FileRead(hFile, pSampleList[uiSample].pData, uiSize, NULL);
  1394. FileClose(hFile);
  1395. strcpy(pSampleList[uiSample].pName, pFilename);
  1396. strupr(pSampleList[uiSample].pName);
  1397. pSampleList[uiSample].uiSize=uiSize;
  1398. pSampleList[uiSample].uiFlags|=SAMPLE_ALLOCATED;
  1399. /* if(!strstr(pFilename, ".MP3"))
  1400. SoundProcessWAVHeader(uiSample);
  1401. */ return(uiSample);
  1402. }
  1403. return(NO_SAMPLE);
  1404. }
  1405. //*******************************************************************************
  1406. // SoundCleanCache
  1407. //
  1408. // Removes the least-used sound from the cache to make room.
  1409. //
  1410. // Returns: TRUE if a sample was freed, FALSE if none
  1411. //
  1412. //*******************************************************************************
  1413. BOOLEAN SoundCleanCache(void)
  1414. {
  1415. UINT32 uiCount, uiLowestHits=NO_SAMPLE, uiLowestHitsCount=0;
  1416. for(uiCount=0; uiCount < SOUND_MAX_CACHED; uiCount++)
  1417. {
  1418. if((pSampleList[uiCount].uiFlags&SAMPLE_ALLOCATED) &&
  1419. !(pSampleList[uiCount].uiFlags&SAMPLE_LOCKED))
  1420. {
  1421. if((uiLowestHits==NO_SAMPLE) || (uiLowestHitsCount < pSampleList[uiCount].uiCacheHits))
  1422. {
  1423. if(!SoundSampleIsPlaying(uiCount))
  1424. {
  1425. uiLowestHits=uiCount;
  1426. uiLowestHitsCount=pSampleList[uiCount].uiCacheHits;
  1427. }
  1428. }
  1429. }
  1430. }
  1431. if(uiLowestHits!=NO_SAMPLE)
  1432. {
  1433. SoundFreeSampleIndex(uiLowestHits);
  1434. return(TRUE);
  1435. }
  1436. return(FALSE);
  1437. }
  1438. //*******************************************************************************
  1439. // Low Level Interface (Local use only)
  1440. //*******************************************************************************
  1441. //*******************************************************************************
  1442. // SoundSampleIsPlaying
  1443. //
  1444. // Returns TRUE/FALSE that a sample is currently in use for playing a sound.
  1445. //
  1446. //*******************************************************************************
  1447. BOOLEAN SoundSampleIsPlaying(UINT32 uiSample)
  1448. {
  1449. UINT32 uiCount;
  1450. for(uiCount=0; uiCount < SOUND_MAX_CHANNELS; uiCount++)
  1451. {
  1452. if(pSoundList[uiCount].uiSample==uiSample)
  1453. return(TRUE);
  1454. }
  1455. return(FALSE);
  1456. }
  1457. //*******************************************************************************
  1458. // SoundGetEmptySample
  1459. //
  1460. // Returns the slot number of an available sample index.
  1461. //
  1462. // Returns: A free sample index, or NO_SAMPLE if none are left.
  1463. //
  1464. //*******************************************************************************
  1465. UINT32 SoundGetEmptySample(void)
  1466. {
  1467. UINT32 uiCount;
  1468. for(uiCount=0; uiCount < SOUND_MAX_CACHED; uiCount++)
  1469. {
  1470. if(!(pSampleList[uiCount].uiFlags&SAMPLE_ALLOCATED))
  1471. return(uiCount);
  1472. }
  1473. return(NO_SAMPLE);
  1474. }
  1475. //*******************************************************************************
  1476. // SoundProcessWAVHeader
  1477. //
  1478. // Reads the information contained in the header of a loaded WAV file, and
  1479. // transfers it to the system structures for that slot.
  1480. //
  1481. // Returns: TRUE if a good header was processed, FALSE if an error occurred.
  1482. //
  1483. //*******************************************************************************
  1484. BOOLEAN SoundProcessWAVHeader(UINT32 uiSample)
  1485. {
  1486. CHAR8 *pChunk;
  1487. AILSOUNDINFO ailInfo;
  1488. pChunk=(CHAR8 *)pSampleList[uiSample].pData;
  1489. if(!AIL_WAV_info((void *)pChunk, &ailInfo))
  1490. return(FALSE);
  1491. pSampleList[uiSample].uiSpeed=ailInfo.rate;
  1492. pSampleList[uiSample].fStereo=(BOOLEAN)(ailInfo.channels==2);
  1493. pSampleList[uiSample].ubBits=(UINT8)ailInfo.bits;
  1494. pSampleList[uiSample].pSoundStart=(PTR)ailInfo.data_ptr;
  1495. pSampleList[uiSample].uiSoundSize=ailInfo.data_len;
  1496. pSampleList[uiSample].uiAilWaveFormat=ailInfo.format;
  1497. pSampleList[uiSample].uiADPCMBlockSize=ailInfo.block_size;
  1498. return(TRUE);
  1499. }
  1500. //*******************************************************************************
  1501. // SoundFreeSampleIndex
  1502. //
  1503. // Frees up a sample referred to by it's index slot number.
  1504. //
  1505. // Returns: Slot number if something was free, NO_SAMPLE otherwise.
  1506. //
  1507. //*******************************************************************************
  1508. UINT32 SoundFreeSampleIndex(UINT32 uiSample)
  1509. {
  1510. if(pSampleList[uiSample].uiFlags&SAMPLE_ALLOCATED)
  1511. {
  1512. if(pSampleList[uiSample].pData!=NULL)
  1513. {
  1514. guiSoundMemoryUsed-=pSampleList[uiSample].uiSize;
  1515. AIL_mem_free_lock(pSampleList[uiSample].pData);
  1516. }
  1517. memset(&pSampleList[uiSample], 0, sizeof(SAMPLETAG));
  1518. return(uiSample);
  1519. }
  1520. return(NO_SAMPLE);
  1521. }
  1522. //*******************************************************************************
  1523. // SoundGetIndexByID
  1524. //
  1525. // Searches out a sound instance referred to by it's ID number.
  1526. //
  1527. // Returns: If the instance was found, the slot number. NO_SAMPLE otherwise.
  1528. //
  1529. //*******************************************************************************
  1530. UINT32 SoundGetIndexByID(UINT32 uiSoundID)
  1531. {
  1532. UINT32 uiCount;
  1533. for(uiCount=0; uiCount < SOUND_MAX_CHANNELS; uiCount++)
  1534. {
  1535. if(pSoundList[uiCount].uiSoundID==uiSoundID)
  1536. return(uiCount);
  1537. }
  1538. return(NO_SAMPLE);
  1539. }
  1540. //*******************************************************************************
  1541. // SoundInitHardware
  1542. //
  1543. // Initializes the sound hardware through Windows/DirectX. THe highest possible
  1544. // mixing rate and capabilities set are searched out and used.
  1545. //
  1546. // Returns: TRUE if the hardware was initialized, FALSE otherwise.
  1547. //
  1548. //*******************************************************************************
  1549. BOOLEAN SoundInitHardware(void)
  1550. {
  1551. UINT32 uiCount;
  1552. CHAR8 cDriverName[128];
  1553. // Try to start up the Miles Sound System
  1554. if(!AIL_startup())
  1555. return(FALSE);
  1556. // Initialize the driver handle
  1557. hSoundDriver = NULL;
  1558. // Set up preferences, to try to use DirectSound and to set the
  1559. // maximum number of handles that we are allowed to allocate. Note
  1560. // that this is not the number we may have playing at one time--
  1561. // that number is set by SOUND_MAX_CHANNELS
  1562. AIL_set_preference(DIG_MIXER_CHANNELS, SOUND_MAX_CHANNELS);
  1563. fDirectSound=TRUE;
  1564. AIL_set_preference(DIG_USE_WAVEOUT,NO);
  1565. // startup with DirectSound
  1566. if (hSoundDriver == NULL)
  1567. hSoundDriver = SoundInitDriver(44100, 16, 2);
  1568. if (hSoundDriver == NULL)
  1569. hSoundDriver = SoundInitDriver(44100, 8, 2);
  1570. if (hSoundDriver == NULL)
  1571. hSoundDriver = SoundInitDriver(22050, 8, 2);
  1572. if (hSoundDriver == NULL)
  1573. hSoundDriver = SoundInitDriver(11025, 8, 1);
  1574. if(hSoundDriver)
  1575. {
  1576. // Detect if the driver is emulated or not
  1577. SoundGetDriverName(hSoundDriver, cDriverName);
  1578. _strlwr(cDriverName);
  1579. // If it is, we don't want to use it, since the extra
  1580. // code layer can slow us down by up to 40% under NT
  1581. if(strstr(cDriverName, "emulated"))
  1582. {
  1583. AIL_waveOutClose(hSoundDriver);
  1584. hSoundDriver=NULL;
  1585. }
  1586. }
  1587. // nothing in DirectSound worked, so try waveOut
  1588. if (hSoundDriver == NULL)
  1589. {
  1590. fDirectSound=FALSE;
  1591. AIL_set_preference(DIG_USE_WAVEOUT,YES);
  1592. }
  1593. if (hSoundDriver == NULL)
  1594. hSoundDriver = SoundInitDriver(44100, 16, 2);
  1595. if (hSoundDriver == NULL)
  1596. hSoundDriver = SoundInitDriver(44100, 8, 2);
  1597. if (hSoundDriver == NULL)
  1598. hSoundDriver = SoundInitDriver(22050, 8, 2);
  1599. if (hSoundDriver == NULL)
  1600. hSoundDriver = SoundInitDriver(11025, 8, 1);
  1601. if (hSoundDriver!=NULL)
  1602. {
  1603. for(uiCount = 0; uiCount < SOUND_MAX_CHANNELS; uiCount++)
  1604. memset(&pSoundList[uiCount], 0, sizeof(SOUNDTAG));
  1605. return(TRUE);
  1606. }
  1607. return(FALSE);
  1608. /*
  1609. // midi startup
  1610. if (hSoundDriver!=NULL)
  1611. {
  1612. soundMDI = MIDI_init_driver();
  1613. if (soundMDI==NULL)
  1614. {
  1615. _RPT1(_CRT_WARN, "MIDI: %s", AIL_last_error());
  1616. }
  1617. else
  1618. {
  1619. soundSEQ = MIDI_load_sequence(soundMDI, "SOUNDS\\DEMO.XMI");
  1620. if (soundSEQ==NULL)
  1621. _RPT1(_CRT_WARN, "MIDI: %s", AIL_last_error());
  1622. }
  1623. }
  1624. */
  1625. }
  1626. //*******************************************************************************
  1627. // SoundShutdownHardware
  1628. //
  1629. // Shuts down the system hardware.
  1630. //
  1631. // Returns: TRUE always.
  1632. //
  1633. //*******************************************************************************
  1634. BOOLEAN SoundShutdownHardware(void)
  1635. {
  1636. if(fSoundSystemInit)
  1637. AIL_shutdown();
  1638. return(TRUE);
  1639. }
  1640. //*******************************************************************************
  1641. // SoundInitDriver
  1642. //
  1643. // Tries to initialize the sound driver using the specified settings.
  1644. //
  1645. // Returns: Pointer to the driver if successful, NULL otherwise.
  1646. //
  1647. //*******************************************************************************
  1648. static HDIGDRIVER SoundInitDriver(UINT32 uiRate, UINT16 uiBits, UINT16 uiChans)
  1649. {
  1650. static PCMWAVEFORMAT sPCMWF;
  1651. HDIGDRIVER DIG;
  1652. CHAR8 cBuf[128];
  1653. memset(&sPCMWF, 0, sizeof(PCMWAVEFORMAT));
  1654. sPCMWF.wf.wFormatTag = WAVE_FORMAT_PCM;
  1655. sPCMWF.wf.nChannels = uiChans;
  1656. sPCMWF.wf.nSamplesPerSec = uiRate;
  1657. sPCMWF.wf.nAvgBytesPerSec = uiRate * (uiBits / 8) * uiChans;
  1658. sPCMWF.wf.nBlockAlign = (uiBits / 8) * uiChans;
  1659. sPCMWF.wBitsPerSample = uiBits;
  1660. if(AIL_waveOutOpen(&DIG, NULL, 0, (LPWAVEFORMAT) &sPCMWF))
  1661. return(NULL);
  1662. memset(cBuf, 0, 128);
  1663. AIL_digital_configuration(DIG,0,0,cBuf);
  1664. FastDebugMsg(String("Sound Init: %dKHz, %d uiBits, %s %s\n", uiRate, uiBits, (uiChans==1)? "Mono": "Stereo", cBuf));
  1665. return(DIG);
  1666. }
  1667. //*******************************************************************************
  1668. // SoundGetDriverName
  1669. //
  1670. // Returns the name of the AIL device.
  1671. //
  1672. // Returns: TRUE or FALSE if the string was filled.
  1673. //
  1674. //*******************************************************************************
  1675. BOOLEAN SoundGetDriverName(HDIGDRIVER DIG, CHAR8 *cBuf)
  1676. {
  1677. if(DIG)
  1678. {
  1679. cBuf[0]='\0';
  1680. AIL_digital_configuration(DIG, NULL, NULL, cBuf);
  1681. return(TRUE);
  1682. }
  1683. else
  1684. return(FALSE);
  1685. }
  1686. //*******************************************************************************
  1687. // SoundGetFreeChannel
  1688. //
  1689. // Finds an unused sound channel in the channel list.
  1690. //
  1691. // Returns: Index of a sound channel if one was found, SOUND_ERROR if not.
  1692. //
  1693. //*******************************************************************************
  1694. UINT32 SoundGetFreeChannel(void)
  1695. {
  1696. UINT32 uiCount;
  1697. for(uiCount=0; uiCount < SOUND_MAX_CHANNELS; uiCount++)
  1698. {
  1699. if(!SoundIsPlaying(pSoundList[uiCount].uiSoundID))
  1700. {
  1701. SoundStopIndex(uiCount);
  1702. }
  1703. if((pSoundList[uiCount].hMSS==NULL) && (pSoundList[uiCount].hMSSStream==NULL) && (pSoundList[uiCount].hM3D==NULL))
  1704. return(uiCount);
  1705. }
  1706. return(SOUND_ERROR);
  1707. }
  1708. //*******************************************************************************
  1709. // SoundStartSample
  1710. //
  1711. // Starts up a sample on the specified channel. Override parameters are passed
  1712. // in through the structure pointer pParms. Any entry with a value of 0xffffffff
  1713. // will be filled in by the system.
  1714. //
  1715. // Returns: Unique sound ID if successful, SOUND_ERROR if not.
  1716. //
  1717. //*******************************************************************************
  1718. UINT32 SoundStartSample(UINT32 uiSample, UINT32 uiChannel, SOUNDPARMS *pParms)
  1719. {
  1720. UINT32 uiSoundID;
  1721. CHAR8 AILString[200];
  1722. if(!fSoundSystemInit)
  1723. return(SOUND_ERROR);
  1724. if((pSoundList[uiChannel].hMSS = AIL_allocate_sample_handle(hSoundDriver))==NULL)
  1725. {
  1726. sprintf(AILString, "Sample Error: %s", AIL_last_error());
  1727. FastDebugMsg(AILString);
  1728. return(SOUND_ERROR);
  1729. }
  1730. AIL_init_sample(pSoundList[uiChannel].hMSS);
  1731. if(!AIL_set_named_sample_file(pSoundList[uiChannel].hMSS, pSampleList[uiSample].pName, pSampleList[uiSample].pData, pSampleList[uiSample].uiSize, 0))
  1732. {
  1733. AIL_release_sample_handle(pSoundList[uiChannel].hMSS);
  1734. pSoundList[uiChannel].hMSS=NULL;
  1735. sprintf(AILString, "AIL Set Sample Error: %s", AIL_last_error());
  1736. DbgMessage(TOPIC_GAME, DBG_LEVEL_0, AILString);
  1737. return(SOUND_ERROR);
  1738. }
  1739. // Store the natural playback rate before we modify it below
  1740. pSampleList[uiSample].uiSpeed=AIL_sample_playback_rate(pSoundList[uiChannel].hMSS);
  1741. if(pSampleList[uiSample].uiFlags & SAMPLE_RANDOM)
  1742. {
  1743. if((pSampleList[uiSample].uiSpeedMin != SOUND_PARMS_DEFAULT) && (pSampleList[uiSample].uiSpeedMin != SOUND_PARMS_DEFAULT))
  1744. {
  1745. UINT32 uiSpeed = pSampleList[uiSample].uiSpeedMin+Random(pSampleList[uiSample].uiSpeedMax-pSampleList[uiSample].uiSpeedMin);
  1746. AIL_set_sample_playback_rate(pSoundList[uiChannel].hMSS, uiSpeed);
  1747. }
  1748. }
  1749. else
  1750. {
  1751. if((pParms!=NULL) && (pParms->uiSpeed!=SOUND_PARMS_DEFAULT))
  1752. {
  1753. Assert((pParms->uiSpeed > 0) && (pParms->uiSpeed <= 60000));
  1754. AIL_set_sample_playback_rate(pSoundList[uiChannel].hMSS, pParms->uiSpeed);
  1755. }
  1756. }
  1757. if((pParms!=NULL) && (pParms->uiPitchBend!=SOUND_PARMS_DEFAULT))
  1758. {
  1759. UINT32 uiRate = AIL_sample_playback_rate(pSoundList[uiChannel].hMSS);
  1760. UINT32 uiBend = uiRate * pParms->uiPitchBend/100;
  1761. AIL_set_sample_playback_rate(pSoundList[uiChannel].hMSS, uiRate + (Random(uiBend*2)-uiBend));
  1762. }
  1763. if((pParms!=NULL) && (pParms->uiVolume!=SOUND_PARMS_DEFAULT))
  1764. AIL_set_sample_volume(pSoundList[uiChannel].hMSS, pParms->uiVolume);
  1765. else
  1766. AIL_set_sample_volume(pSoundList[uiChannel].hMSS, guiSoundDefaultVolume);
  1767. if((pParms!=NULL) && (pParms->uiLoop!=SOUND_PARMS_DEFAULT))
  1768. {
  1769. AIL_set_sample_loop_count(pSoundList[uiChannel].hMSS, pParms->uiLoop);
  1770. // If looping infinately, lock the sample so it can't be unloaded
  1771. // and mark it as a looping sound
  1772. if(pParms->uiLoop==0)
  1773. {
  1774. pSampleList[uiSample].uiFlags|=SAMPLE_LOCKED;
  1775. pSoundList[uiChannel].fLooping=TRUE;
  1776. }
  1777. }
  1778. if((pParms!=NULL) && (pParms->uiPan!=SOUND_PARMS_DEFAULT))
  1779. AIL_set_sample_pan(pSoundList[uiChannel].hMSS, pParms->uiPan);
  1780. if((pParms!=NULL) && (pParms->uiPriority!=SOUND_PARMS_DEFAULT))
  1781. pSoundList[uiChannel].uiPriority=pParms->uiPriority;
  1782. else
  1783. pSoundList[uiChannel].uiPriority=PRIORITY_MAX;
  1784. if((pParms!=NULL) && ((UINT32)pParms->EOSCallback!=SOUND_PARMS_DEFAULT))
  1785. {
  1786. pSoundList[uiChannel].EOSCallback=pParms->EOSCallback;
  1787. pSoundList[uiChannel].pCallbackData=pParms->pCallbackData;
  1788. }
  1789. else
  1790. {
  1791. pSoundList[uiChannel].EOSCallback=NULL;
  1792. pSoundList[uiChannel].pCallbackData=NULL;
  1793. }
  1794. uiSoundID=SoundGetUniqueID();
  1795. pSoundList[uiChannel].uiSoundID=uiSoundID;
  1796. pSoundList[uiChannel].uiSample=uiSample;
  1797. pSoundList[uiChannel].uiTimeStamp=GetTickCount();
  1798. pSoundList[uiChannel].uiFadeVolume = SoundGetVolumeIndex(uiChannel);
  1799. pSampleList[uiSample].uiCacheHits++;
  1800. AIL_start_sample(pSoundList[uiChannel].hMSS);
  1801. return(uiSoundID);
  1802. }
  1803. //*******************************************************************************
  1804. // SoundStartStream
  1805. //
  1806. // Starts up a stream on the specified channel. Override parameters are passed
  1807. // in through the structure pointer pParms. Any entry with a value of 0xffffffff
  1808. // will be filled in by the system.
  1809. //
  1810. // Returns: Unique sound ID if successful, SOUND_ERROR if not.
  1811. //
  1812. //*******************************************************************************
  1813. UINT32 SoundStartStream(STR pFilename, UINT32 uiChannel, SOUNDPARMS *pParms)
  1814. {
  1815. UINT32 uiSoundID, uiSpeed;
  1816. CHAR8 AILString[200];
  1817. if(!fSoundSystemInit)
  1818. return(SOUND_ERROR);
  1819. if((pSoundList[uiChannel].hMSSStream=AIL_open_stream(hSoundDriver, pFilename, SOUND_DEFAULT_STREAM))==NULL)
  1820. {
  1821. SoundCleanCache();
  1822. pSoundList[uiChannel].hMSSStream=AIL_open_stream(hSoundDriver, pFilename, SOUND_DEFAULT_STREAM);
  1823. }
  1824. if(pSoundList[uiChannel].hMSSStream==NULL)
  1825. {
  1826. sprintf(AILString, "Stream Error: %s", AIL_last_error());
  1827. DbgMessage(TOPIC_GAME, DBG_LEVEL_0, AILString);
  1828. return(SOUND_ERROR);
  1829. }
  1830. if((pParms!=NULL) && (pParms->uiSpeed!=SOUND_PARMS_DEFAULT))
  1831. uiSpeed=pParms->uiSpeed;
  1832. else
  1833. uiSpeed=AIL_stream_playback_rate(pSoundList[uiChannel].hMSSStream);
  1834. if((pParms!=NULL) && (pParms->uiPitchBend!=SOUND_PARMS_DEFAULT))
  1835. {
  1836. UINT32 uiBend = uiSpeed * pParms->uiPitchBend/100;
  1837. uiSpeed+=(Random(uiBend*2)-uiBend);
  1838. }
  1839. AIL_set_stream_playback_rate(pSoundList[uiChannel].hMSSStream, uiSpeed);
  1840. if((pParms!=NULL) && (pParms->uiVolume!=SOUND_PARMS_DEFAULT))
  1841. AIL_set_stream_volume(pSoundList[uiChannel].hMSSStream, pParms->uiVolume);
  1842. else
  1843. AIL_set_stream_volume(pSoundList[uiChannel].hMSSStream, guiSoundDefaultVolume);
  1844. if( pParms!=NULL )
  1845. {
  1846. if (pParms->uiLoop!=SOUND_PARMS_DEFAULT )
  1847. AIL_set_stream_loop_count(pSoundList[uiChannel].hMSSStream, pParms->uiLoop);
  1848. }
  1849. if((pParms!=NULL) && (pParms->uiPan!=SOUND_PARMS_DEFAULT))
  1850. AIL_set_stream_pan(pSoundList[uiChannel].hMSSStream, pParms->uiPan);
  1851. AIL_start_stream(pSoundList[uiChannel].hMSSStream);
  1852. uiSoundID=SoundGetUniqueID();
  1853. pSoundList[uiChannel].uiSoundID=uiSoundID;
  1854. if(pParms)
  1855. pSoundList[uiChannel].uiPriority=pParms->uiPriority;
  1856. else
  1857. pSoundList[uiChannel].uiPriority=SOUND_PARMS_DEFAULT;
  1858. if((pParms!=NULL) && ((UINT32)pParms->EOSCallback!=SOUND_PARMS_DEFAULT))
  1859. {
  1860. pSoundList[uiChannel].EOSCallback=pParms->EOSCallback;
  1861. pSoundList[uiChannel].pCallbackData=pParms->pCallbackData;
  1862. }
  1863. else
  1864. {
  1865. pSoundList[uiChannel].EOSCallback=NULL;
  1866. pSoundList[uiChannel].pCallbackData=NULL;
  1867. }
  1868. pSoundList[uiChannel].uiTimeStamp=GetTickCount();
  1869. pSoundList[uiChannel].uiFadeVolume = SoundGetVolumeIndex(uiChannel);
  1870. return(uiSoundID);
  1871. }
  1872. //*******************************************************************************
  1873. // SoundGetUniqueID
  1874. //
  1875. // Returns a unique ID number with every call. Basically it's just a 32-bit
  1876. // static value that is incremented each time.
  1877. //
  1878. //*******************************************************************************
  1879. UINT32 SoundGetUniqueID(void)
  1880. {
  1881. static UINT32 uiNextID=0;
  1882. if(uiNextID==SOUND_ERROR)
  1883. uiNextID++;
  1884. return(uiNextID++);
  1885. }
  1886. //*******************************************************************************
  1887. // SoundPlayStreamed
  1888. //
  1889. // Returns TRUE/FALSE whether a sound file should be played as a streamed
  1890. // sample, or loaded into the cache. The decision is based on the size of the
  1891. // file compared to the guiSoundCacheThreshold.
  1892. //
  1893. // Returns: TRUE if it should be streamed, FALSE if loaded.
  1894. //
  1895. //*******************************************************************************
  1896. BOOLEAN SoundPlayStreamed(STR pFilename)
  1897. {
  1898. HWFILE hDisk;
  1899. UINT32 uiFilesize;
  1900. if((hDisk=FileOpen(pFilename, FILE_ACCESS_READ, FALSE))!=0)
  1901. {
  1902. uiFilesize=FileGetSize(hDisk);
  1903. FileClose(hDisk);
  1904. return(uiFilesize >= guiSoundCacheThreshold);
  1905. }
  1906. return(FALSE);
  1907. }
  1908. //*******************************************************************************
  1909. // SoundStopIndex
  1910. //
  1911. // Stops a sound referred to by it's slot number. This function is the only
  1912. // one that should be deallocating sample handles. The random sounds have to have
  1913. // their counters maintained, and using this as the central function ensures
  1914. // that they stay in sync.
  1915. //
  1916. // Returns: TRUE if the sample was stopped, FALSE if it could not be found.
  1917. //
  1918. //*******************************************************************************
  1919. BOOLEAN SoundStopIndex(UINT32 uiChannel)
  1920. {
  1921. UINT32 uiSample;
  1922. if(fSoundSystemInit)
  1923. {
  1924. if(uiChannel!=NO_SAMPLE)
  1925. {
  1926. if(pSoundList[uiChannel].hMSS!=NULL)
  1927. {
  1928. AIL_stop_sample(pSoundList[uiChannel].hMSS);
  1929. AIL_release_sample_handle(pSoundList[uiChannel].hMSS);
  1930. pSoundList[uiChannel].hMSS=NULL;
  1931. uiSample=pSoundList[uiChannel].uiSample;
  1932. // if this was a random sample, decrease the iteration count
  1933. if(pSampleList[uiSample].uiFlags&SAMPLE_RANDOM)
  1934. pSampleList[uiSample].uiInstances--;
  1935. if(pSoundList[uiChannel].EOSCallback!=NULL)
  1936. pSoundList[uiChannel].EOSCallback(pSoundList[uiChannel].pCallbackData);
  1937. if(pSoundList[uiChannel].fLooping && !SoundSampleIsInUse(uiChannel))
  1938. SoundRemoveSampleFlags(uiSample, SAMPLE_LOCKED);
  1939. pSoundList[uiChannel].uiSample=NO_SAMPLE;
  1940. }
  1941. if(pSoundList[uiChannel].hMSSStream!=NULL)
  1942. {
  1943. AIL_close_stream(pSoundList[uiChannel].hMSSStream);
  1944. pSoundList[uiChannel].hMSSStream=NULL;
  1945. if(pSoundList[uiChannel].EOSCallback!=NULL)
  1946. pSoundList[uiChannel].EOSCallback(pSoundList[uiChannel].pCallbackData);
  1947. pSoundList[uiChannel].uiSample=NO_SAMPLE;
  1948. }
  1949. if(pSoundList[uiChannel].hM3D!=NULL)
  1950. {
  1951. AIL_stop_3D_sample(pSoundList[uiChannel].hM3D);
  1952. AIL_release_3D_sample_handle(pSoundList[uiChannel].hM3D);
  1953. pSoundList[uiChannel].hM3D=NULL;
  1954. uiSample=pSoundList[uiChannel].uiSample;
  1955. // if this was a random sample, decrease the iteration count
  1956. if(pSampleList[uiSample].uiFlags&SAMPLE_RANDOM)
  1957. pSampleList[uiSample].uiInstances--;
  1958. if(pSoundList[uiChannel].EOSCallback!=NULL)
  1959. pSoundList[uiChannel].EOSCallback(pSoundList[uiChannel].pCallbackData);
  1960. if(pSoundList[uiChannel].fLooping && !SoundSampleIsInUse(uiChannel))
  1961. SoundRemoveSampleFlags(uiSample, SAMPLE_LOCKED);
  1962. pSoundList[uiChannel].uiSample=NO_SAMPLE;
  1963. }
  1964. if( pSoundList[uiChannel].hFile != 0 )
  1965. {
  1966. FileClose( pSoundList[uiChannel].hFile );
  1967. pSoundList[uiChannel].hFile = 0;
  1968. pSoundList[uiChannel].uiSample=NO_SAMPLE;
  1969. }
  1970. return(TRUE);
  1971. }
  1972. }
  1973. return(FALSE);
  1974. }
  1975. //*******************************************************************************
  1976. // SoundGetDriverHandle
  1977. //
  1978. // Returns: Pointer to the current sound driver
  1979. //
  1980. //*******************************************************************************
  1981. HDIGDRIVER SoundGetDriverHandle(void)
  1982. {
  1983. return(hSoundDriver);
  1984. }
  1985. // FUNCTIONS TO SET / RESET SAMPLE FLAGS
  1986. void SoundSetSampleFlags( UINT32 uiSample, UINT32 uiFlags )
  1987. {
  1988. // CHECK FOR VALUE SAMPLE
  1989. if((pSampleList[ uiSample ].uiFlags&SAMPLE_ALLOCATED) )
  1990. {
  1991. // SET
  1992. pSampleList[uiSample].uiFlags |= uiFlags;
  1993. }
  1994. }
  1995. void SoundRemoveSampleFlags( UINT32 uiSample, UINT32 uiFlags )
  1996. {
  1997. // CHECK FOR VALID SAMPLE
  1998. if((pSampleList[ uiSample ].uiFlags&SAMPLE_ALLOCATED) )
  1999. {
  2000. //REMOVE
  2001. pSampleList[uiSample].uiFlags &= (~uiFlags);
  2002. }
  2003. }
  2004. //*******************************************************************************
  2005. // SoundSampleIsInUse
  2006. //
  2007. // Returns: TRUE if the sample index is currently being played by the system.
  2008. //
  2009. //*******************************************************************************
  2010. BOOLEAN SoundSampleIsInUse(UINT32 uiSample)
  2011. {
  2012. UINT32 uiCount;
  2013. for(uiCount=0; uiCount < SOUND_MAX_CHANNELS; uiCount++)
  2014. {
  2015. if((pSoundList[uiCount].uiSample==uiSample) && SoundIsPlaying(uiCount))
  2016. return(TRUE);
  2017. }
  2018. return(FALSE);
  2019. }
  2020. //*****************************************************************************************
  2021. // SoundFileIsPlaying
  2022. //
  2023. // Returns true or false on whether a certain file is currently being played. This function
  2024. // will only work on sounds loaded into the cache, it will NOT work on streamed sounds.
  2025. //
  2026. // Returns BOOLEAN -
  2027. //
  2028. // CHAR8 *pFilename -
  2029. //
  2030. // Created: 2/24/00 Derek Beland
  2031. //*****************************************************************************************
  2032. BOOLEAN SoundFileIsPlaying(CHAR8 *pFilename)
  2033. {
  2034. UINT32 uiCount;
  2035. for(uiCount=0; uiCount < SOUND_MAX_CHANNELS; uiCount++)
  2036. {
  2037. if(SoundIndexIsPlaying(uiCount))
  2038. {
  2039. if(stricmp(pSampleList[pSoundList[uiCount].uiSample].pName, pFilename)==0)
  2040. return(TRUE);
  2041. }
  2042. }
  2043. return(FALSE);
  2044. }
  2045. //*****************************************************************************************
  2046. // SoundSampleSetVolumeRange
  2047. //
  2048. // Sets the minimum and maximum volume for a sample.
  2049. //
  2050. // Returns nothing.
  2051. //
  2052. // UINT32 uiSample - Sample handle
  2053. // UINT32 uiVolMin - Minimum volume
  2054. // UINT32 uiVolMax - Maximum volume
  2055. //
  2056. // Created: 10/29/97 Andrew Emmons
  2057. //*****************************************************************************************
  2058. void SoundSampleSetVolumeRange(UINT32 uiSample, UINT32 uiVolMin, UINT32 uiVolMax)
  2059. {
  2060. Assert((uiSample >= 0) && (uiSample < SOUND_MAX_CACHED));
  2061. pSampleList[uiSample].uiVolMin=uiVolMin;
  2062. pSampleList[uiSample].uiVolMax=uiVolMax;
  2063. }
  2064. //*****************************************************************************************
  2065. // SoundSampleSetPanRange
  2066. //
  2067. // Sets the left/right pan values for a sample.
  2068. //
  2069. // Returns nothing.
  2070. //
  2071. // UINT32 uiSample - Sample handle
  2072. // UINT32 uiPanMin - Left setting
  2073. // UINT32 uiPanMax - Right setting
  2074. //
  2075. // Created: 10/29/97 Andrew Emmons
  2076. //*****************************************************************************************
  2077. void SoundSampleSetPanRange(UINT32 uiSample, UINT32 uiPanMin, UINT32 uiPanMax)
  2078. {
  2079. Assert((uiSample >= 0) && (uiSample < SOUND_MAX_CACHED));
  2080. pSampleList[uiSample].uiPanMin=uiPanMin;
  2081. pSampleList[uiSample].uiPanMax=uiPanMax;
  2082. }
  2083. //*****************************************************************************************
  2084. // SoundSetMusic
  2085. //
  2086. // Marks a sample as being music. Cannot be stopped by anything other than SoundStopMusic.
  2087. //
  2088. // Returns nothing.
  2089. //
  2090. // UINT32 uiSound - Sound instance to stop
  2091. //
  2092. // Created: 3/16/00 Derek Beland
  2093. //*****************************************************************************************
  2094. void SoundSetMusic(UINT32 uiSoundID)
  2095. {
  2096. UINT32 uiSound=SoundGetIndexByID(uiSoundID);
  2097. if(uiSound!=NO_SAMPLE)
  2098. pSoundList[uiSound].fMusic=TRUE;
  2099. }
  2100. //*****************************************************************************************
  2101. // SoundStopMusic
  2102. //
  2103. // Stops any sound instance with the music flag.
  2104. //
  2105. // Returns nothing.
  2106. //
  2107. // Created: 3/16/00 Derek Beland
  2108. //*****************************************************************************************
  2109. BOOLEAN SoundStopMusic(void)
  2110. {
  2111. UINT32 uiCount;
  2112. BOOLEAN fStopped=FALSE;
  2113. if(fSoundSystemInit)
  2114. {
  2115. for(uiCount=0; uiCount < SOUND_MAX_CHANNELS; uiCount++)
  2116. {
  2117. if((pSoundList[uiCount].hMSS!=NULL) || (pSoundList[uiCount].hMSSStream!=NULL) || (pSoundList[uiCount].hM3D!=NULL))
  2118. {
  2119. if(pSoundList[uiCount].fMusic)
  2120. {
  2121. SoundStop(pSoundList[uiCount].uiSoundID);
  2122. fStopped=TRUE;
  2123. }
  2124. }
  2125. }
  2126. }
  2127. return(fStopped);
  2128. }
  2129. //*****************************************************************************************
  2130. //
  2131. //
  2132. //
  2133. //
  2134. // New 3D Sound Code
  2135. //
  2136. //
  2137. //
  2138. //
  2139. //*****************************************************************************************
  2140. //*****************************************************************************************
  2141. // Sound3DSetProvider
  2142. //
  2143. // Sets the name of the 3D provider to initialize with.
  2144. //
  2145. // Returns nothing.
  2146. //
  2147. // CHAR8 *pProviderName - Pointer to provider name
  2148. //
  2149. // Created: 8/17/99 Derek Beland
  2150. //*****************************************************************************************
  2151. void Sound3DSetProvider(CHAR8 *pProviderName)
  2152. {
  2153. Assert(pProviderName);
  2154. if(pProviderName)
  2155. {
  2156. gpProviderName = (CHAR8 *)MemAlloc(strlen(pProviderName)+1);
  2157. strcpy(gpProviderName, pProviderName);
  2158. }
  2159. }
  2160. //*****************************************************************************************
  2161. // Sound3DInitProvider
  2162. //
  2163. // Attempt
  2164. //
  2165. // Returns BOOLEAN -
  2166. //
  2167. // CHAR8 *pProviderName -
  2168. //
  2169. // Created: 8/17/99 Derek Beland
  2170. //*****************************************************************************************
  2171. BOOLEAN Sound3DInitProvider(CHAR8 *pProviderName)
  2172. {
  2173. HPROENUM hEnum=HPROENUM_FIRST;
  2174. HPROVIDER hProvider=0;
  2175. BOOLEAN fDone=FALSE;
  2176. CHAR8 *pName;
  2177. INT32 iResult;
  2178. // 3D sound providers depend on the 2D sound system being initialized first
  2179. if(!fSoundSystemInit || !pProviderName)
  2180. return(FALSE);
  2181. // We're already booted up
  2182. if(gh3DProvider)
  2183. return(TRUE);
  2184. while(!fDone)
  2185. {
  2186. if(!AIL_enumerate_3D_providers(&hEnum, &hProvider, &pName))
  2187. fDone=TRUE;
  2188. else if(hProvider)
  2189. {
  2190. if(strcmp(pProviderName, pName)==0)
  2191. {
  2192. fDone=TRUE;
  2193. if(AIL_open_3D_provider(hProvider)==M3D_NOERR)
  2194. {
  2195. gh3DProvider = hProvider;
  2196. // Create a "listener" which represents our position in space
  2197. gh3DListener = AIL_open_3D_listener(gh3DProvider);
  2198. if(!gh3DListener)
  2199. {
  2200. AIL_close_3D_provider(gh3DProvider);
  2201. return(FALSE);
  2202. }
  2203. Sound3DSetListener(0.0f, 0.0f, 0.0f);
  2204. AIL_3D_provider_attribute(gh3DProvider, "EAX environment selection", &iResult);
  2205. if(iResult!=(-1))
  2206. gfUsingEAX = TRUE;
  2207. return(TRUE);
  2208. }
  2209. }
  2210. }
  2211. }
  2212. // We didn't find a provider with a matching name that would boot up
  2213. return(FALSE);
  2214. }
  2215. //*****************************************************************************************
  2216. // Sound3DShutdownProvider
  2217. //
  2218. // Shuts down and deallocates the 3D sound system
  2219. //
  2220. // Returns nothing.
  2221. //
  2222. // Created: 8/17/99 Derek Beland
  2223. //*****************************************************************************************
  2224. void Sound3DShutdownProvider(void)
  2225. {
  2226. Sound3DStopAll();
  2227. if(gh3DListener)
  2228. {
  2229. AIL_close_3D_listener(gh3DListener);
  2230. gh3DListener=0;
  2231. }
  2232. if(gh3DProvider)
  2233. {
  2234. AIL_close_3D_provider(gh3DProvider);
  2235. gh3DProvider=0;
  2236. }
  2237. }
  2238. //*****************************************************************************************
  2239. // Sound3DSetPosition
  2240. //
  2241. // Sets the 3-space position of a sound sample.
  2242. //
  2243. // Returns nothing.
  2244. //
  2245. // UINT32 uiSample - ID of sample
  2246. // FLOAT flX - X coordinate
  2247. // FLOAT flY - Y coordinate
  2248. // FLOAT flZ - Z coordinate
  2249. //
  2250. // Created: 8/17/99 Derek Beland
  2251. //*****************************************************************************************
  2252. void Sound3DSetPosition(UINT32 uiSample, FLOAT flX, FLOAT flY, FLOAT flZ)
  2253. {
  2254. UINT32 uiChannel;
  2255. if(fSoundSystemInit && gh3DProvider)
  2256. {
  2257. if((uiChannel=SoundGetIndexByID(uiSample))!=NO_SAMPLE)
  2258. {
  2259. if(pSoundList[uiChannel].hM3D!=NULL)
  2260. {
  2261. AIL_set_3D_position(pSoundList[uiChannel].hM3D, flX, flY, flZ);
  2262. }
  2263. }
  2264. }
  2265. }
  2266. //*****************************************************************************************
  2267. // Sound3DSetVelocity
  2268. //
  2269. // Sets the velocity of a sample. This is important for calculation of doppler effect (pitch
  2270. // shifting, think of a train whistle as it passes by you).
  2271. //
  2272. // Returns nothing.
  2273. //
  2274. // UINT32 uiSample - ID of sample
  2275. // FLOAT flX - X coordinate
  2276. // FLOAT flY - Y coordinate
  2277. // FLOAT flZ - Z coordinate
  2278. //
  2279. // Created: 8/17/99 Derek Beland
  2280. //*****************************************************************************************
  2281. void Sound3DSetVelocity(UINT32 uiSample, FLOAT flX, FLOAT flY, FLOAT flZ)
  2282. {
  2283. UINT32 uiChannel;
  2284. if(fSoundSystemInit && gh3DProvider)
  2285. {
  2286. if((uiChannel=SoundGetIndexByID(uiSample))!=NO_SAMPLE)
  2287. {
  2288. if(pSoundList[uiChannel].hM3D!=NULL)
  2289. {
  2290. }
  2291. }
  2292. }
  2293. }
  2294. //*****************************************************************************************
  2295. // Sound3DSetListener
  2296. //
  2297. // Sets the listener location. This should be set to the current camera location.
  2298. //
  2299. // Returns nothing.
  2300. //
  2301. // FLOAT flX - X coordinate
  2302. // FLOAT flY - Y coordinate
  2303. // FLOAT flZ - Z coordinate
  2304. //
  2305. // Created: 8/17/99 Derek Beland
  2306. //*****************************************************************************************
  2307. void Sound3DSetListener(FLOAT flX, FLOAT flY, FLOAT flZ)
  2308. {
  2309. if(fSoundSystemInit && gh3DListener)
  2310. AIL_set_3D_position(gh3DListener, flX, flY, flZ);
  2311. }
  2312. //*****************************************************************************************
  2313. // Sound3DSetFacing
  2314. //
  2315. // Sets the orientation of the listener. The inputs are two vectors that are *always* at
  2316. // right angles to each other. The first is the facing vector, and the second is the up
  2317. // vector, which points out of the top of the listeners head.
  2318. //
  2319. // Returns nothing.
  2320. //
  2321. // FLOAT flXFace - X coordinate facing
  2322. // FLOAT flYFace - Y coordinate facing
  2323. // FLOAT flZFace - Z coordinate facing
  2324. // FLOAT flXUp - X coordinate up
  2325. // FLOAT flYUp - Y coordinate up
  2326. // FLOAT flZUp - Z coordinate up
  2327. //
  2328. // Created: 8/17/99 Derek Beland
  2329. //*****************************************************************************************
  2330. void Sound3DSetFacing(FLOAT flXFace, FLOAT flYFace, FLOAT flZFace, FLOAT flXUp, FLOAT flYUp, FLOAT flZUp)
  2331. {
  2332. if(fSoundSystemInit && gh3DListener)
  2333. AIL_set_3D_orientation(gh3DListener, flXFace, flYFace, flZFace, flXUp, flYUp, flZUp);
  2334. }
  2335. //*****************************************************************************************
  2336. // Sound3DSetDirection
  2337. //
  2338. // Sets the orientation of the listener. The inputs are two vectors that are *always* at
  2339. // right angles to each other. The first is the facing vector, and the second is the up
  2340. // vector, which points out of the top of the listeners head.
  2341. //
  2342. // Returns nothing.
  2343. //
  2344. // FLOAT flXFace - X coordinate facing
  2345. // FLOAT flYFace - Y coordinate facing
  2346. // FLOAT flZFace - Z coordinate facing
  2347. // FLOAT flXUp - X coordinate up
  2348. // FLOAT flYUp - Y coordinate up
  2349. // FLOAT flZUp - Z coordinate up
  2350. //
  2351. // Created: 8/17/99 Derek Beland
  2352. //*****************************************************************************************
  2353. void Sound3DSetDirection(UINT32 uiSample, FLOAT flXFace, FLOAT flYFace, FLOAT flZFace, FLOAT flXUp, FLOAT flYUp, FLOAT flZUp)
  2354. {
  2355. UINT32 uiChannel;
  2356. if(fSoundSystemInit && gh3DProvider)
  2357. {
  2358. if((uiChannel=SoundGetIndexByID(uiSample))!=NO_SAMPLE)
  2359. {
  2360. if(pSoundList[uiChannel].hM3D!=NULL)
  2361. {
  2362. AIL_set_3D_orientation(pSoundList[uiChannel].hM3D, flXFace, flYFace, flZFace, flXUp, flYUp, flZUp);
  2363. }
  2364. }
  2365. }
  2366. }
  2367. //*****************************************************************************************
  2368. // Sound3DSetFalloff
  2369. //
  2370. // Sets the falloff of the sound which determines the maximum radius at which the sample
  2371. // produces any sound, and the minimum distance before the sound volume begins to fall off
  2372. // towards zero.
  2373. //
  2374. // Returns nothing.
  2375. //
  2376. // UINT32 uiSample - Sample index
  2377. // FLOAT flMax - Point at which the sound volume is zero
  2378. // FLOAT flMin - Point at which the sound volume begins to fall off
  2379. //
  2380. // Created: 8/17/99 Derek Beland
  2381. //*****************************************************************************************
  2382. void Sound3DSetFalloff(UINT32 uiSample, FLOAT flMax, FLOAT flMin)
  2383. {
  2384. UINT32 uiChannel;
  2385. // max = far
  2386. // min = near
  2387. if(fSoundSystemInit && gh3DProvider)
  2388. {
  2389. if((uiChannel=SoundGetIndexByID(uiSample))!=NO_SAMPLE)
  2390. {
  2391. if(pSoundList[uiChannel].hM3D!=NULL)
  2392. {
  2393. AIL_set_3D_sample_distances(pSoundList[uiChannel].hM3D, flMax, flMin);
  2394. }
  2395. }
  2396. }
  2397. }
  2398. //*****************************************************************************************
  2399. // Sound3DActiveSounds
  2400. //
  2401. // Returns the number of active sounds.
  2402. //
  2403. // Returns INT32 - Number of 3D sounds playing
  2404. //
  2405. // Created: 8/17/99 Derek Beland
  2406. //*****************************************************************************************
  2407. INT32 Sound3DActiveSounds(void)
  2408. {
  2409. return((INT32)AIL_active_3D_sample_count(gh3DProvider));
  2410. }
  2411. //*****************************************************************************************
  2412. // Sound3DSetEnvironment
  2413. //
  2414. // Sets the current environment type for the listener. This determines which atmospheric
  2415. // effects are applied to the 3D sounds. Eg. Caves, underwater, etc.
  2416. //
  2417. // Returns nothing.
  2418. //
  2419. // INT32 iEnvironment - Index of environment type
  2420. //
  2421. // Created: 8/17/99 Derek Beland
  2422. //*****************************************************************************************
  2423. void Sound3DSetEnvironment(INT32 iEnvironment)
  2424. {
  2425. if(fSoundSystemInit && gh3DProvider)
  2426. {
  2427. }
  2428. }
  2429. //*****************************************************************************************
  2430. // Sound3DPlay
  2431. //
  2432. // Starts a 3D sample playing.
  2433. //
  2434. // Returns UINT32 - Sound index
  2435. //
  2436. // STR pFilename - Pointer to filename of sound
  2437. // SOUNDPARMS *pParms - Parameter struct (or NULL for defaults)
  2438. //
  2439. // Created: 8/17/99 Derek Beland
  2440. //*****************************************************************************************
  2441. UINT32 Sound3DPlay(STR pFilename, SOUND3DPARMS *pParms)
  2442. {
  2443. UINT32 uiSample, uiChannel;
  2444. if(fSoundSystemInit && gh3DProvider)
  2445. {
  2446. if((uiSample=SoundLoadSample(pFilename))!=NO_SAMPLE)
  2447. {
  2448. if((uiChannel=SoundGetFreeChannel())!=SOUND_ERROR)
  2449. {
  2450. return(Sound3DStartSample(uiSample, uiChannel, pParms));
  2451. }
  2452. }
  2453. else
  2454. {
  2455. FastDebugMsg(String("Sound3DPlay: ERROR: Failed loading sample %s\n", pFilename ) );
  2456. }
  2457. }
  2458. return(SOUND_ERROR);
  2459. }
  2460. //*******************************************************************************
  2461. // Sound3DStartSample
  2462. //
  2463. // Starts up a sample on the specified channel. Override parameters are passed
  2464. // in through the structure pointer pParms. Any entry with a value of 0xffffffff
  2465. // will be filled in by the system.
  2466. //
  2467. // Returns: Unique sound ID if successful, SOUND_ERROR if not.
  2468. //
  2469. //*******************************************************************************
  2470. UINT32 Sound3DStartSample(UINT32 uiSample, UINT32 uiChannel, SOUND3DPARMS *pParms)
  2471. {
  2472. UINT32 uiSoundID;
  2473. CHAR8 AILString[200];
  2474. if(!fSoundSystemInit || !gh3DProvider)
  2475. return(SOUND_ERROR);
  2476. // Stereo samples have no purpose in 3D, nor MP3 files
  2477. if(pSampleList[uiSample].fStereo || strstr(pSampleList[uiSample].pName, ".MP3"))
  2478. return(SOUND_ERROR);
  2479. if((pSoundList[uiChannel].hM3D = AIL_allocate_3D_sample_handle(gh3DProvider))==NULL)
  2480. {
  2481. sprintf(AILString, "AIL3D Error: %s", AIL_last_error());
  2482. DbgMessage(TOPIC_GAME, DBG_LEVEL_0, AILString);
  2483. return(SOUND_ERROR);
  2484. }
  2485. if(!AIL_set_3D_sample_file(pSoundList[uiChannel].hM3D, pSampleList[uiSample].pData))
  2486. {
  2487. AIL_release_3D_sample_handle(pSoundList[uiChannel].hM3D);
  2488. pSoundList[uiChannel].hM3D=NULL;
  2489. sprintf(AILString, "AIL3D Set Sample Error: %s", AIL_last_error());
  2490. DbgMessage(TOPIC_GAME, DBG_LEVEL_0, AILString);
  2491. return(SOUND_ERROR);
  2492. }
  2493. // Store the natural playback rate before we modify it below
  2494. pSampleList[uiSample].uiSpeed=AIL_3D_sample_playback_rate(pSoundList[uiChannel].hM3D);
  2495. if(pSampleList[uiSample].uiFlags & SAMPLE_RANDOM)
  2496. {
  2497. if((pSampleList[uiSample].uiSpeedMin != SOUND_PARMS_DEFAULT) && (pSampleList[uiSample].uiSpeedMax != SOUND_PARMS_DEFAULT))
  2498. {
  2499. UINT32 uiSpeed = pSampleList[uiSample].uiSpeedMin+Random(pSampleList[uiSample].uiSpeedMax-pSampleList[uiSample].uiSpeedMin);
  2500. AIL_set_3D_sample_playback_rate(pSoundList[uiChannel].hM3D, uiSpeed);
  2501. }
  2502. }
  2503. else
  2504. {
  2505. if((pParms!=NULL) && (pParms->uiSpeed!=SOUND_PARMS_DEFAULT))
  2506. AIL_set_3D_sample_playback_rate(pSoundList[uiChannel].hM3D, pParms->uiSpeed);
  2507. }
  2508. if((pParms!=NULL) && (pParms->uiPitchBend!=SOUND_PARMS_DEFAULT))
  2509. {
  2510. UINT32 uiRate = AIL_3D_sample_playback_rate(pSoundList[uiChannel].hM3D);
  2511. UINT32 uiBend = uiRate * pParms->uiPitchBend/100;
  2512. AIL_set_3D_sample_playback_rate(pSoundList[uiChannel].hM3D, uiRate + (Random(uiBend*2)-uiBend));
  2513. }
  2514. if((pParms!=NULL) && (pParms->uiVolume!=SOUND_PARMS_DEFAULT))
  2515. AIL_set_3D_sample_volume(pSoundList[uiChannel].hM3D, pParms->uiVolume);
  2516. else
  2517. AIL_set_3D_sample_volume(pSoundList[uiChannel].hM3D, guiSoundDefaultVolume);
  2518. if((pParms!=NULL) && (pParms->uiLoop!=SOUND_PARMS_DEFAULT))
  2519. {
  2520. AIL_set_3D_sample_loop_count(pSoundList[uiChannel].hM3D, pParms->uiLoop);
  2521. // If looping infinately, lock the sample so it can't be unloaded
  2522. // and mark it as a looping sound
  2523. if(pParms->uiLoop==0)
  2524. {
  2525. pSampleList[uiSample].uiFlags|=SAMPLE_LOCKED;
  2526. pSoundList[uiChannel].fLooping=TRUE;
  2527. }
  2528. }
  2529. if((pParms!=NULL) && (pParms->uiPriority!=SOUND_PARMS_DEFAULT))
  2530. pSoundList[uiChannel].uiPriority=pParms->uiPriority;
  2531. else
  2532. pSoundList[uiChannel].uiPriority=PRIORITY_MAX;
  2533. if((pParms!=NULL) && ((UINT32)pParms->EOSCallback!=SOUND_PARMS_DEFAULT))
  2534. {
  2535. pSoundList[uiChannel].EOSCallback=pParms->EOSCallback;
  2536. pSoundList[uiChannel].pCallbackData=pParms->pCallbackData;
  2537. }
  2538. else
  2539. {
  2540. pSoundList[uiChannel].EOSCallback=NULL;
  2541. pSoundList[uiChannel].pCallbackData=NULL;
  2542. }
  2543. AIL_set_3D_position(pSoundList[uiChannel].hM3D, pParms->Pos.flX, pParms->Pos.flY, pParms->Pos.flZ);
  2544. AIL_set_3D_velocity_vector(pSoundList[uiChannel].hM3D, pParms->Pos.flVelX, pParms->Pos.flVelY, pParms->Pos.flVelZ);
  2545. AIL_set_3D_orientation(pSoundList[uiChannel].hM3D, pParms->Pos.flFaceX, pParms->Pos.flFaceY, pParms->Pos.flFaceZ, pParms->Pos.flUpX, pParms->Pos.flUpY, pParms->Pos.flUpZ);
  2546. // AIL_set_3D_sample_distances(pSoundList[uiChannel].hM3D, pParms->Pos.flFalloffMax, pParms->Pos.flFalloffMin);
  2547. AIL_set_3D_sample_distances(pSoundList[uiChannel].hM3D, 99999999.9f, 99999999.9f);
  2548. uiSoundID=SoundGetUniqueID();
  2549. pSoundList[uiChannel].uiSoundID=uiSoundID;
  2550. pSoundList[uiChannel].uiSample=uiSample;
  2551. pSoundList[uiChannel].uiTimeStamp=GetTickCount();
  2552. pSampleList[uiSample].uiCacheHits++;
  2553. AIL_start_3D_sample(pSoundList[uiChannel].hM3D);
  2554. return(uiSoundID);
  2555. }
  2556. //*****************************************************************************************
  2557. // Sound3DStopAll
  2558. //
  2559. // Stops all currently playing 3D samples.
  2560. //
  2561. // Returns nothing.
  2562. //
  2563. // Created: 8/17/99 Derek Beland
  2564. //*****************************************************************************************
  2565. void Sound3DStopAll(void)
  2566. {
  2567. UINT32 uiChannel;
  2568. // Stop all currently playing random sounds
  2569. for(uiChannel=0; uiChannel < SOUND_MAX_CHANNELS; uiChannel++)
  2570. {
  2571. if(pSoundList[uiChannel].hM3D!=NULL)
  2572. SoundStopIndex(uiChannel);
  2573. }
  2574. }
  2575. //*******************************************************************************
  2576. // Sound3DStartRandom
  2577. //
  2578. // Starts an instance of a random sample.
  2579. //
  2580. // Returns: TRUE if a new random sound was created, FALSE if nothing was done.
  2581. //
  2582. //*******************************************************************************
  2583. UINT32 Sound3DStartRandom(UINT32 uiSample, SOUND3DPOS *pPos)
  2584. {
  2585. UINT32 uiChannel, uiSoundID;
  2586. SOUND3DPARMS sp3DParms;
  2587. if(pPos && ((uiChannel=SoundGetFreeChannel())!=SOUND_ERROR))
  2588. {
  2589. memset(&sp3DParms, 0xff, sizeof(SOUND3DPARMS));
  2590. // sp3DParms.uiSpeed=pSampleList[uiSample].uiSpeedMin+Random(pSampleList[uiSample].uiSpeedMax-pSampleList[uiSample].uiSpeedMin);
  2591. sp3DParms.uiLoop=1;
  2592. sp3DParms.uiPriority=pSampleList[uiSample].uiPriority;
  2593. // memcpy(&sp3DParms.Pos, pPos, sizeof(SOUND3DPOS));
  2594. sp3DParms.Pos.flX=pPos->flX;
  2595. sp3DParms.Pos.flY=pPos->flY;
  2596. sp3DParms.Pos.flZ=pPos->flZ;
  2597. sp3DParms.Pos.flVelX=pPos->flVelX;
  2598. sp3DParms.Pos.flVelY=pPos->flVelY;
  2599. sp3DParms.Pos.flVelZ=pPos->flVelZ;
  2600. sp3DParms.Pos.flFaceX=pPos->flFaceX;
  2601. sp3DParms.Pos.flFaceY=pPos->flFaceY;
  2602. sp3DParms.Pos.flFaceZ=pPos->flFaceZ;
  2603. sp3DParms.Pos.flUpX=pPos->flUpX;
  2604. sp3DParms.Pos.flUpY=pPos->flUpY;
  2605. sp3DParms.Pos.flUpZ=pPos->flUpZ;
  2606. sp3DParms.Pos.flFalloffMax=pPos->flFalloffMax;
  2607. sp3DParms.Pos.flFalloffMin=pPos->flFalloffMin;
  2608. sp3DParms.Pos.uiVolume=pPos->uiVolume;
  2609. sp3DParms.uiVolume=pPos->uiVolume;
  2610. if((uiSoundID=Sound3DStartSample(uiSample, uiChannel, &sp3DParms))!=SOUND_ERROR)
  2611. {
  2612. pSampleList[uiSample].uiTimeNext=GetTickCount()+pSampleList[uiSample].uiTimeMin+Random(pSampleList[uiSample].uiTimeMax-pSampleList[uiSample].uiTimeMin);
  2613. pSampleList[uiSample].uiInstances++;
  2614. return(uiSoundID);
  2615. }
  2616. }
  2617. return(NO_SAMPLE);
  2618. }
  2619. //*****************************************************************************************
  2620. // Sound3DSetRoomType
  2621. //
  2622. // Sets the environment presets (reverb, chorus, etc) for 3D sounds. Currently only
  2623. // has effect for EAX cards.
  2624. //
  2625. // Returns nothing.
  2626. //
  2627. // UINT32 uiRoomType - Index of room type (see Soundman.h e_EAXRoomTypes)
  2628. //
  2629. // Created: 8/23/99 Derek Beland
  2630. //*****************************************************************************************
  2631. void Sound3DSetRoomType(UINT32 uiRoomType)
  2632. {
  2633. if(gh3DProvider && gfUsingEAX && (guiRoomTypeIndex!=uiRoomType))
  2634. {
  2635. CHAR8 cName[128];
  2636. sprintf(cName, "EAX_ENVIRONMENT_%s", pEAXRoomTypes[uiRoomType]);
  2637. AIL_set_3D_provider_preference(gh3DProvider, cName, (void *)(&uiRoomType));
  2638. guiRoomTypeIndex = uiRoomType;
  2639. }
  2640. }
  2641. //*****************************************************************************************
  2642. // Sound3DChannelsUsed
  2643. //
  2644. //
  2645. //
  2646. // Returns UINT32 -
  2647. //
  2648. // Created: 5/26/00 Derek Beland
  2649. //*****************************************************************************************
  2650. UINT32 Sound3DChannelsInUse(void)
  2651. {
  2652. UINT32 uiChannel, uiUsed=0;
  2653. // Stop all currently playing random sounds
  2654. for(uiChannel=0; uiChannel < SOUND_MAX_CHANNELS; uiChannel++)
  2655. {
  2656. if(pSoundList[uiChannel].hM3D!=NULL)
  2657. uiUsed++;
  2658. }
  2659. return(uiUsed);
  2660. }
  2661. //*****************************************************************************************
  2662. // SoundStreamsInUse
  2663. //
  2664. //
  2665. //
  2666. // Returns UINT32 -
  2667. //
  2668. // Created: 5/26/00 Derek Beland
  2669. //*****************************************************************************************
  2670. UINT32 SoundStreamsInUse(void)
  2671. {
  2672. UINT32 uiChannel, uiUsed=0;
  2673. // Stop all currently playing random sounds
  2674. for(uiChannel=0; uiChannel < SOUND_MAX_CHANNELS; uiChannel++)
  2675. {
  2676. if(pSoundList[uiChannel].hMSSStream!=NULL)
  2677. uiUsed++;
  2678. }
  2679. return(uiUsed);
  2680. }
  2681. //*****************************************************************************************
  2682. // Sound2DChannelsInUse
  2683. //
  2684. //
  2685. //
  2686. // Returns UINT32 -
  2687. //
  2688. // Created: 5/26/00 Derek Beland
  2689. //*****************************************************************************************
  2690. UINT32 Sound2DChannelsInUse(void)
  2691. {
  2692. UINT32 uiChannel, uiUsed=0;
  2693. // Stop all currently playing random sounds
  2694. for(uiChannel=0; uiChannel < SOUND_MAX_CHANNELS; uiChannel++)
  2695. {
  2696. if(pSoundList[uiChannel].hMSS!=NULL)
  2697. uiUsed++;
  2698. }
  2699. return(uiUsed);
  2700. }
  2701. //*****************************************************************************************
  2702. // SoundChannelsInUse
  2703. //
  2704. //
  2705. //
  2706. // Returns UINT32 -
  2707. //
  2708. // Created: 5/26/00 Derek Beland
  2709. //*****************************************************************************************
  2710. UINT32 SoundTotalChannelsInUse(void)
  2711. {
  2712. UINT32 uiChannel, uiUsed=0;
  2713. // Stop all currently playing random sounds
  2714. for(uiChannel=0; uiChannel < SOUND_MAX_CHANNELS; uiChannel++)
  2715. {
  2716. if(SoundIndexIsPlaying(uiChannel))
  2717. uiUsed++;
  2718. }
  2719. return(uiUsed);
  2720. }