| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390 |
- /*
- ** Command & Conquer Generals Zero Hour(tm)
- ** Copyright 2025 Electronic Arts Inc.
- **
- ** This program is free software: you can redistribute it and/or modify
- ** it under the terms of the GNU General Public License as published by
- ** the Free Software Foundation, either version 3 of the License, or
- ** (at your option) any later version.
- **
- ** This program is distributed in the hope that it will be useful,
- ** but WITHOUT ANY WARRANTY; without even the implied warranty of
- ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ** GNU General Public License for more details.
- **
- ** You should have received a copy of the GNU General Public License
- ** along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- ////////////////////////////////////////////////////////////////////////////////
- // //
- // (c) 2001-2003 Electronic Arts Inc. //
- // //
- ////////////////////////////////////////////////////////////////////////////////
- // FILE: MilesAudioManager.cpp
- /*---------------------------------------------------------------------------*/
- /* EA Pacific */
- /* Confidential Information */
- /* Copyright (C) 2001 - All Rights Reserved */
- /* DO NOT DISTRIBUTE */
- /*---------------------------------------------------------------------------*/
- /* Project: RTS3 */
- /* File name: MilesAudioManager.cpp */
- /* Created: John K. McDonald, Jr., 3/21/2002 */
- /* Desc: This is the implementation for the MilesAudioManager, which */
- /* interfaces with the Miles Sound System. */
- /* Revision History: */
- /* 7/18/2002 : Initial creation */
- /*---------------------------------------------------------------------------*/
- #include <dsound.h>
- #include "Lib/Basetype.h"
- #include "MilesAudioDevice/MilesAudioManager.h"
- #include "Common/AudioAffect.h"
- #include "Common/AudioHandleSpecialValues.h"
- #include "Common/AudioRequest.h"
- #include "Common/AudioSettings.h"
- #include "Common/AsciiString.h"
- #include "Common/AudioEventInfo.h"
- #include "Common/FileSystem.h"
- #include "Common/GameCommon.h"
- #include "Common/GameSounds.h"
- #include "Common/CRCDebug.h"
- #include "Common/GlobalData.h"
- #include "Common/ScopedMutex.h"
- #include "GameClient/DebugDisplay.h"
- #include "GameClient/Drawable.h"
- #include "GameClient/GameClient.h"
- #include "GameClient/VideoPlayer.h"
- #include "GameClient/View.h"
- #include "GameLogic/GameLogic.h"
- #include "GameLogic/TerrainLogic.h"
- #include "Common/File.h"
- #ifdef _INTERNAL
- //#pragma optimize("", off)
- //#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes")
- #endif
- enum { INFINITE_LOOP_COUNT = 1000000 };
- // Callback functions useful for Miles ////////////////////////////////////////////////////////////
- static void AILCALLBACK setSampleCompleted( HSAMPLE sampleCompleted );
- static void AILCALLBACK set3DSampleCompleted( H3DSAMPLE sample3DCompleted );
- static void AILCALLBACK setStreamCompleted( HSTREAM streamCompleted );
- static U32 AILCALLBACK streamingFileOpen(char const *fileName, U32 *file_handle);
- static void AILCALLBACK streamingFileClose(U32 fileHandle);
- static S32 AILCALLBACK streamingFileSeek(U32 fileHandle, S32 offset, U32 type);
- static U32 AILCALLBACK streamingFileRead(U32 fileHandle, void *buffer, U32 bytes);
- //-------------------------------------------------------------------------------------------------
- MilesAudioManager::MilesAudioManager() :
- m_providerCount(0),
- m_selectedProvider(PROVIDER_ERROR),
- m_selectedSpeakerType(0),
- m_lastProvider(PROVIDER_ERROR),
- m_digitalHandle(NULL),
- m_num2DSamples(0),
- m_num3DSamples(0),
- m_numStreams(0),
- m_delayFilter(NULL),
- m_binkHandle(NULL),
- m_pref3DProvider(AsciiString::TheEmptyString),
- m_prefSpeaker(AsciiString::TheEmptyString)
- {
- m_audioCache = NEW AudioFileCache;
- }
- //-------------------------------------------------------------------------------------------------
- MilesAudioManager::~MilesAudioManager()
- {
- DEBUG_ASSERTCRASH(m_binkHandle == NULL, ("Leaked a Bink handle. Chuybregts"));
- releaseHandleForBink();
- closeDevice();
- delete m_audioCache;
-
- DEBUG_ASSERTCRASH(this == TheAudio, ("Umm...\n"));
- TheAudio = NULL;
- }
- //-------------------------------------------------------------------------------------------------
- #if defined(_DEBUG) || defined(_INTERNAL)
- AudioHandle MilesAudioManager::addAudioEvent( const AudioEventRTS *eventToAdd )
- {
- if (TheGlobalData->m_preloadReport) {
- if (!eventToAdd->getEventName().isEmpty()) {
- m_allEventsLoaded.insert(eventToAdd->getEventName());
- }
- }
- return AudioManager::addAudioEvent(eventToAdd);
- }
- #endif
- #if defined(_DEBUG) || defined(_INTERNAL)
- //-------------------------------------------------------------------------------------------------
- void MilesAudioManager::audioDebugDisplay(DebugDisplayInterface *dd, void *, FILE *fp )
- {
- std::list<PlayingAudio *>::iterator it;
- static char buffer[128] = { 0 };
- if (buffer[0] == 0) {
- AIL_MSS_version(buffer, 128);
- }
-
- Coord3D lookPos;
- TheTacticalView->getPosition( &lookPos );
- lookPos.z = TheTerrainLogic->getGroundHeight( lookPos.x, lookPos.y );
- const Coord3D *mikePos = TheAudio->getListenerPosition();
- Coord3D distanceVector = TheTacticalView->get3DCameraPosition();
- distanceVector.sub( mikePos );
- Int now = TheGameLogic->getFrame();
- static Int lastCheck = now;
- const Int frames = 60;
- static Int latency = 0;
- static Int worstLatency = 0;
- if( lastCheck + frames <= now )
- {
- latency = AIL_get_timer_highest_delay();
- if( latency > worstLatency )
- {
- worstLatency = latency;
- }
- lastCheck = now;
- }
- if( dd )
- {
- dd->printf("Miles Sound System version: %s ", buffer);
- dd->printf("Memory Usage : %d/%d\n", m_audioCache->getCurrentlyUsedSize(), m_audioCache->getMaxSize());
- dd->printf("Sound: %s ", (isOn(AudioAffect_Sound) ? "Yes" : "No"));
- dd->printf("3DSound: %s ", (isOn(AudioAffect_Sound3D) ? "Yes" : "No"));
- dd->printf("Speech: %s ", (isOn(AudioAffect_Speech) ? "Yes" : "No"));
- dd->printf("Music: %s\n", (isOn(AudioAffect_Music) ? "Yes" : "No"));
- dd->printf("Channels Available: ");
- dd->printf("%d Sounds ", m_sound->getAvailableSamples());
- dd->printf("%d(%d) 3D Sounds\n", m_sound->getAvailable3DSamples(), m_available3DSamples.size() );
- dd->printf("Volume: ");
- dd->printf("Sound: %d ", REAL_TO_INT(m_soundVolume * 100.0f));
- dd->printf("3DSound: %d ", REAL_TO_INT(m_sound3DVolume * 100.0f));
- dd->printf("Speech: %d ", REAL_TO_INT(m_speechVolume * 100.0f));
- dd->printf("Music: %d\n", REAL_TO_INT(m_musicVolume * 100.0f));
- dd->printf("Current 3D Provider: %s ",
-
- TheAudio->getProviderName(m_selectedProvider).str());
- dd->printf("Current Speaker Type: %s\n", TheAudio->translateUnsignedIntToSpeakerType(TheAudio->getSpeakerType()).str());
- dd->printf( "Looking at: (%d,%d,%d) -- Microphone at: (%d,%d,%d)\n",
- (Int)lookPos.x, (Int)lookPos.y, (Int)lookPos.z, (Int)mikePos->x, (Int)mikePos->y, (Int)mikePos->z );
- dd->printf( "Camera distance from microphone: %d -- Zoom Volume: %d%%\n",
- (Int)distanceVector.length(), (Int)(TheAudio->getZoomVolume()*100.0f) );
- dd->printf( "Worst latency: %d -- Current latency: %d\n", worstLatency, latency );
- dd->printf("-----------------------------------------------------------\n");
- dd->printf("Playing Audio\n");
- }
- if( fp )
- {
- fprintf( fp, "Miles Sound System version: %s ", buffer );
- fprintf( fp, "Memory Usage : %d/%d\n", m_audioCache->getCurrentlyUsedSize(), m_audioCache->getMaxSize() );
- fprintf( fp, "Sound: %s ", (isOn(AudioAffect_Sound) ? "Yes" : "No") );
- fprintf( fp, "3DSound: %s ", (isOn(AudioAffect_Sound3D) ? "Yes" : "No") );
- fprintf( fp, "Speech: %s ", (isOn(AudioAffect_Speech) ? "Yes" : "No") );
- fprintf( fp, "Music: %s\n", (isOn(AudioAffect_Music) ? "Yes" : "No") );
- fprintf( fp, "Channels Available: " );
- fprintf( fp, "%d Sounds ", m_sound->getAvailableSamples() );
- fprintf( fp, "%d 3D Sounds\n", m_sound->getAvailable3DSamples() );
- fprintf( fp, "Volume: ");
- fprintf( fp, "Sound: %d ", REAL_TO_INT(m_soundVolume * 100.0f) );
- fprintf( fp, "3DSound: %d ", REAL_TO_INT(m_sound3DVolume * 100.0f) );
- fprintf( fp, "Speech: %d ", REAL_TO_INT(m_speechVolume * 100.0f) );
- fprintf( fp, "Music: %d\n", REAL_TO_INT(m_musicVolume * 100.0f) );
- fprintf( fp, "Current 3D Provider: %s ", TheAudio->getProviderName(m_selectedProvider).str());
- fprintf( fp, "Current Speaker Type: %s\n", TheAudio->translateUnsignedIntToSpeakerType(TheAudio->getSpeakerType()).str());
- fprintf( fp, "Looking at: (%d,%d,%d) -- Microphone at: (%d,%d,%d)\n",
- (Int)lookPos.x, (Int)lookPos.y, (Int)lookPos.z, (Int)mikePos->x, (Int)mikePos->y, (Int)mikePos->z );
- fprintf( fp, "Camera distance from microphone: %d -- Zoom Volume: %d%%\n",
- (Int)distanceVector.length(), (Int)(TheAudio->getZoomVolume()*100.0f) );
- fprintf( fp, "-----------------------------------------------------------\n" );
- fprintf( fp, "Playing Audio\n" );
- }
- PlayingAudio *playing = NULL;
- Int channel;
- Int channelCount;
- Real volume = 0.0f;
- AsciiString filenameNoSlashes;
- const Int maxChannels = 64;
- PlayingAudio *playingArray[maxChannels] = { NULL };
- // 2-D Sounds
- if( dd )
- {
- dd->printf("-----------------------------------------------------Sounds\n");
- channelCount = TheAudio->getNum2DSamples();
- for (it = m_playingSounds.begin(); it != m_playingSounds.end(); ++it) {
- playing = *it;
- if (!playing) {
- continue;
- }
- playingArray[AIL_sample_user_data(playing->m_sample, 0)] = playing;
- }
- for (Int i = 1; i <= maxChannels && i <= channelCount; ++i) {
- playing = playingArray[i];
- if (!playing) {
- dd->printf("%d: Silence\n", i);
- continue;
- }
- filenameNoSlashes = playing->m_audioEventRTS->getFilename();
- filenameNoSlashes = filenameNoSlashes.reverseFind('\\') + 1;
-
- // Calculate Sample volume
- volume = 100.0f;
- volume *= getEffectiveVolume(playing->m_audioEventRTS);
- dd->printf("%2d: %-20s - (%s) Volume: %d (2D)\n", i, playing->m_audioEventRTS->getEventName().str(), filenameNoSlashes.str(), REAL_TO_INT(volume));
- playingArray[i] = NULL;
- }
- }
- if( fp )
- {
- fprintf( fp, "-----------------------------------------------------Sounds\n" );
- channelCount = TheAudio->getNum2DSamples();
- channel = 1;
- for( it = m_playingSounds.begin(); it != m_playingSounds.end(); ++it )
- {
- playing = *it;
- if( !playing )
- {
- continue;
- }
- filenameNoSlashes = playing->m_audioEventRTS->getFilename();
- filenameNoSlashes = filenameNoSlashes.reverseFind( '\\' ) + 1;
-
- // Calculate Sample volume
- volume = 100.0f;
- volume *= getEffectiveVolume( playing->m_audioEventRTS );
- fprintf( fp, "%2d: %-20s - (%s) Volume: %d (2D)\n", channel++, playing->m_audioEventRTS->getEventName().str(), filenameNoSlashes.str(), REAL_TO_INT( volume ) );
- }
- for( int i = channel; i <= channelCount; ++i )
- {
- fprintf( fp, "%d: Silence\n", i );
- }
- }
- const Coord3D *microphonePos = TheAudio->getListenerPosition();
- // Now 3D Sounds
- if( dd )
- {
- dd->printf("--------------------------------------------------3D Sounds\n");
- channelCount = TheAudio->getNum3DSamples();
- for (it = m_playing3DSounds.begin(); it != m_playing3DSounds.end(); ++it) {
- playing = *it;
- if (!playing) {
- continue;
- }
- playingArray[AIL_3D_user_data(playing->m_3DSample, 0)] = playing;
- }
- for (Int i = 1; i <= maxChannels && i <= channelCount; ++i)
- {
- playing = playingArray[i];
- if (!playing)
- {
- dd->printf("%d: Silence\n", i);
- continue;
- }
- filenameNoSlashes = playing->m_audioEventRTS->getFilename();
- filenameNoSlashes = filenameNoSlashes.reverseFind('\\') + 1;
-
- // Calculate Sample volume
- volume = 100.0f;
- volume *= getEffectiveVolume(playing->m_audioEventRTS);
- Real dist = -1.0f;
- const Coord3D *pos = playing->m_audioEventRTS->getPosition();
- char distStr[32];
- if( pos )
- {
- Coord3D vector = *microphonePos;
- vector.sub( pos );
- dist = vector.length();
- sprintf( distStr, "%d", REAL_TO_INT( dist ) );
- }
- else
- {
- sprintf( distStr, "???" );
- }
- char str[32];
- switch( playing->m_audioEventRTS->getOwnerType() )
- {
- case OT_Positional:
- sprintf( str, "(3D)" );
- break;
- case OT_Object:
- sprintf( str, "(3DObj)" );
- break;
- case OT_Drawable:
- sprintf( str, "(3DDraw)" );
- break;
- case OT_Dead:
- sprintf( str, "(3DDead)" );
- break;
- }
- dd->printf("%2d: %-20s - (%s) Volume: %d, Dist: %s, %s\n",
- i, playing->m_audioEventRTS->getEventName().str(), filenameNoSlashes.str(), REAL_TO_INT(volume), distStr, str );
- playingArray[i] = NULL;
- }
- }
- if( fp )
- {
- fprintf( fp, "--------------------------------------------------3D Sounds\n" );
- channelCount = TheAudio->getNum3DSamples();
- channel = 1;
- for( it = m_playing3DSounds.begin(); it != m_playing3DSounds.end(); ++it )
- {
- playing = *it;
- if( !playing )
- {
- continue;
- }
- filenameNoSlashes = playing->m_audioEventRTS->getFilename();
- filenameNoSlashes = filenameNoSlashes.reverseFind('\\') + 1;
-
- // Calculate Sample volume
- volume = 100.0f;
- volume *= getEffectiveVolume( playing->m_audioEventRTS );
- fprintf( fp, "%2d: %-24s - (%s) Volume: %d \n", channel++, playing->m_audioEventRTS->getEventName().str(), filenameNoSlashes.str(), REAL_TO_INT( volume ) );
- }
- for( int i = channel; i <= channelCount; ++i )
- {
- fprintf( fp, "%2d: Silence\n", i );
- }
- }
- // Now Streams
- if( dd )
- {
- dd->printf("----------------------------------------------------Streams\n");
- channelCount = TheAudio->getNumStreams();
- channel = 1;
- for (it = m_playingStreams.begin(); it != m_playingStreams.end(); ++it) {
- playing = *it;
- if (!playing) {
- continue;
- }
- filenameNoSlashes = playing->m_audioEventRTS->getFilename();
- filenameNoSlashes = filenameNoSlashes.reverseFind('\\') + 1;
-
- // Calculate Sample volume
- volume = 100.0f;
- volume *= getEffectiveVolume(playing->m_audioEventRTS);
- dd->printf("%2d: %-24s - (%s) Volume: %d (Stream)\n", channel++, playing->m_audioEventRTS->getEventName().str(), filenameNoSlashes.str(), REAL_TO_INT(volume));
- }
-
- for ( int i = channel; i <= channelCount; ++i) {
- dd->printf("%2d: Silence\n", i);
- }
- dd->printf("===========================================================\n");
- }
- if( fp )
- {
- fprintf( fp, "----------------------------------------------------Streams\n" );
- channelCount = TheAudio->getNumStreams();
- channel = 1;
- for( it = m_playingStreams.begin(); it != m_playingStreams.end(); ++it )
- {
- playing = *it;
- if( !playing )
- {
- continue;
- }
- filenameNoSlashes = playing->m_audioEventRTS->getFilename();
- filenameNoSlashes = filenameNoSlashes.reverseFind('\\') + 1;
-
- // Calculate Sample volume
- volume = 100.0f;
- volume *= getEffectiveVolume(playing->m_audioEventRTS);
- fprintf( fp, "%2d: %-24s - (%s) Volume: %d (Stream)\n", channel++, playing->m_audioEventRTS->getEventName().str(), filenameNoSlashes.str(), REAL_TO_INT( volume ) );
- }
-
- for( int i = channel; i <= channelCount; ++i )
- {
- fprintf( fp, "%2d: Silence\n", i );
- }
- fprintf( fp, "===========================================================\n" );
- }
- }
- #endif
- //-------------------------------------------------------------------------------------------------
- void MilesAudioManager::init()
- {
- AudioManager::init();
- #ifdef INTENSE_DEBUG
- DEBUG_LOG(("Sound has temporarily been disabled in debug builds only. jkmcd\n"));
- // for now, _DEBUG builds only should have no sound. ask jkmcd or srj about this.
- return;
- #endif
- // We should now know how many samples we want to load
- openDevice();
- m_audioCache->setMaxSize(getAudioSettings()->m_maxCacheSize);
- // Now, set the file callbacks to load the streams from Biggie files
- AIL_set_file_callbacks(streamingFileOpen, streamingFileClose, streamingFileSeek, streamingFileRead);
- }
- //-------------------------------------------------------------------------------------------------
- void MilesAudioManager::postProcessLoad()
- {
- AudioManager::postProcessLoad();
- }
- //-------------------------------------------------------------------------------------------------
- void MilesAudioManager::reset()
- {
- #if defined(_DEBUG) || defined(_INTERNAL)
- dumpAllAssetsUsed();
- m_allEventsLoaded.clear();
- #endif
- AudioManager::reset();
- stopAllAudioImmediately();
- removeAllAudioRequests();
- // This must come after stopAllAudioImmediately() and removeAllAudioRequests(), to ensure that
- // sounds pointing to the temporary AudioEventInfo handles are deleted before their info is deleted
- removeLevelSpecificAudioEventInfos();
- }
- //-------------------------------------------------------------------------------------------------
- void MilesAudioManager::update()
- {
- AudioManager::update();
- setDeviceListenerPosition();
- processRequestList();
- processPlayingList();
- processFadingList();
- processStoppedList();
- }
- //-------------------------------------------------------------------------------------------------
- void MilesAudioManager::stopAudio( AudioAffect which )
- {
- // All we really need to do is:
- // 1) Remove the EOS callback.
- // 2) Stop the sample, (so that when we later unload it, bad stuff doesn't happen)
- // 3) Set the status to stopped, so that when we next process the playing list, we will
- // correctly clean up the sample.
- std::list<PlayingAudio *>::iterator it;
- PlayingAudio *playing = NULL;
- if (BitTest(which, AudioAffect_Sound)) {
- for (it = m_playingSounds.begin(); it != m_playingSounds.end(); ++it) {
- playing = *it;
- if (playing) {
- AIL_register_EOS_callback(playing->m_sample, NULL);
- AIL_stop_sample(playing->m_sample);
- playing->m_status = PS_Stopped;
- }
- }
- }
- if (BitTest(which, AudioAffect_Sound3D)) {
- for (it = m_playing3DSounds.begin(); it != m_playing3DSounds.end(); ++it) {
- playing = *it;
- if (playing) {
- AIL_register_3D_EOS_callback(playing->m_3DSample, NULL);
- AIL_stop_3D_sample(playing->m_3DSample);
- playing->m_status = PS_Stopped;
- }
- }
- }
- if (BitTest(which, AudioAffect_Speech | AudioAffect_Music)) {
- for (it = m_playingStreams.begin(); it != m_playingStreams.end(); ++it) {
- playing = *it;
- if (playing) {
- if (playing->m_audioEventRTS->getAudioEventInfo()->m_soundType == AT_Music) {
- if (!BitTest(which, AudioAffect_Music)) {
- continue;
- }
- } else {
- if (!BitTest(which, AudioAffect_Speech)) {
- continue;
- }
- }
- AIL_register_stream_callback(playing->m_stream, NULL);
- AIL_pause_stream(playing->m_stream, 1);
- playing->m_status = PS_Stopped;
- }
- }
- }
- }
- //-------------------------------------------------------------------------------------------------
- void MilesAudioManager::pauseAudio( AudioAffect which )
- {
- std::list<PlayingAudio *>::iterator it;
- PlayingAudio *playing = NULL;
- if (BitTest(which, AudioAffect_Sound)) {
- for (it = m_playingSounds.begin(); it != m_playingSounds.end(); ++it) {
- playing = *it;
- if (playing) {
- AIL_stop_sample(playing->m_sample);
- }
- }
- }
- if (BitTest(which, AudioAffect_Sound3D)) {
- for (it = m_playing3DSounds.begin(); it != m_playing3DSounds.end(); ++it) {
- playing = *it;
- if (playing) {
- AIL_stop_3D_sample(playing->m_3DSample);
- }
- }
- }
- if (BitTest(which, AudioAffect_Speech | AudioAffect_Music)) {
- for (it = m_playingStreams.begin(); it != m_playingStreams.end(); ++it) {
- playing = *it;
- if (playing) {
- if (playing->m_audioEventRTS->getAudioEventInfo()->m_soundType == AT_Music) {
- if (!BitTest(which, AudioAffect_Music)) {
- continue;
- }
- } else {
- if (!BitTest(which, AudioAffect_Speech)) {
- continue;
- }
- }
- AIL_pause_stream(playing->m_stream, 1);
- }
- }
- }
-
- //Get rid of PLAY audio requests when pausing audio.
- std::list<AudioRequest*>::iterator ait;
- for (ait = m_audioRequests.begin(); ait != m_audioRequests.end(); /* empty */)
- {
- AudioRequest *req = (*ait);
- if( req && req->m_request == AR_Play )
- {
- req->deleteInstance();
- ait = m_audioRequests.erase(ait);
- }
- else
- {
- ait++;
- }
- }
- }
- //-------------------------------------------------------------------------------------------------
- void MilesAudioManager::resumeAudio( AudioAffect which )
- {
- std::list<PlayingAudio *>::iterator it;
- PlayingAudio *playing = NULL;
- if (BitTest(which, AudioAffect_Sound)) {
- for (it = m_playingSounds.begin(); it != m_playingSounds.end(); ++it) {
- playing = *it;
- if (playing) {
- AIL_resume_sample(playing->m_sample);
- }
- }
- }
- if (BitTest(which, AudioAffect_Sound3D)) {
- for (it = m_playing3DSounds.begin(); it != m_playing3DSounds.end(); ++it) {
- playing = *it;
- if (playing) {
- AIL_resume_3D_sample(playing->m_3DSample);
- }
- }
- }
- if (BitTest(which, AudioAffect_Speech | AudioAffect_Music)) {
- for (it = m_playingStreams.begin(); it != m_playingStreams.end(); ++it) {
- playing = *it;
- if (playing) {
- if (playing->m_audioEventRTS->getAudioEventInfo()->m_soundType == AT_Music) {
- if (!BitTest(which, AudioAffect_Music)) {
- continue;
- }
- } else {
- if (!BitTest(which, AudioAffect_Speech)) {
- continue;
- }
- }
- AIL_pause_stream(playing->m_stream, 0);
- }
- }
- }
- }
- //-------------------------------------------------------------------------------------------------
- void MilesAudioManager::pauseAmbient( Bool shouldPause )
- {
- }
- //-------------------------------------------------------------------------------------------------
- void MilesAudioManager::playAudioEvent( AudioEventRTS *event )
- {
- #ifdef INTENSIVE_AUDIO_DEBUG
- DEBUG_LOG(("MILES (%d) - Processing play request: %d (%s)", TheGameLogic->getFrame(), event->getPlayingHandle(), event->getEventName().str()));
- #endif
- const AudioEventInfo *info = event->getAudioEventInfo();
- if (!info) {
- return;
- }
- std::list<PlayingAudio *>::iterator it;
- PlayingAudio *playing = NULL;
- AudioHandle handleToKill = event->getHandleToKill();
- AsciiString fileToPlay = event->getFilename();
- PlayingAudio *audio = allocatePlayingAudio();
- switch(info->m_soundType)
- {
- case AT_Music:
- case AT_Streaming:
- {
- #ifdef INTENSIVE_AUDIO_DEBUG
- DEBUG_LOG(("- Stream\n"));
- #endif
-
- if ((info->m_soundType == AT_Streaming) && event->getUninterruptable()) {
- stopAllSpeech();
- }
- Real curVolume = 1.0;
- if (info->m_soundType == AT_Music) {
- curVolume = m_musicVolume;
- } else {
- curVolume = m_speechVolume;
- }
- curVolume *= event->getVolume();
- Bool foundSoundToReplace = false;
- if (handleToKill) {
- for (it = m_playingStreams.begin(); it != m_playingStreams.end(); ++it) {
- playing = (*it);
- if (!playing) {
- continue;
- }
- if (playing->m_audioEventRTS && playing->m_audioEventRTS->getPlayingHandle() == handleToKill)
- {
- //Release this streaming channel immediately because we are going to play another sound in it's place.
- releasePlayingAudio(playing);
- m_playingStreams.erase(it);
- foundSoundToReplace = true;
- break;
- }
- }
- }
- HSTREAM stream;
- if (!handleToKill || foundSoundToReplace) {
- stream = AIL_open_stream(m_digitalHandle, fileToPlay.str(), 0);
- } else {
- stream = NULL;
- }
- // Put this on here, so that the audio event RTS will be cleaned up regardless.
- audio->m_audioEventRTS = event;
- audio->m_stream = stream;
- audio->m_type = PAT_Stream;
- if (stream) {
- if ((info->m_soundType == AT_Streaming) && event->getUninterruptable()) {
- setDisallowSpeech(TRUE);
- }
- AIL_set_stream_volume_pan(stream, curVolume, 0.5f);
- playStream(event, stream);
- m_playingStreams.push_back(audio);
- audio = NULL;
- }
- break;
- }
- case AT_SoundEffect:
- {
- #ifdef INTENSIVE_AUDIO_DEBUG
- DEBUG_LOG(("- Sound"));
- #endif
-
- if (event->isPositionalAudio()) {
- // Sounds that are non-global are positional 3-D sounds. Deal with them accordingly
- #ifdef INTENSIVE_AUDIO_DEBUG
- DEBUG_LOG((" Positional"));
- #endif
- Bool foundSoundToReplace = false;
- if (handleToKill)
- {
- for (it = m_playing3DSounds.begin(); it != m_playing3DSounds.end(); ++it) {
- playing = (*it);
- if (!playing) {
- continue;
- }
- if( playing->m_audioEventRTS && playing->m_audioEventRTS->getPlayingHandle() == handleToKill )
- {
- //Release this 3D sound channel immediately because we are going to play another sound in it's place.
- releasePlayingAudio(playing);
- m_playing3DSounds.erase(it);
- foundSoundToReplace = true;
- break;
- }
- }
- }
-
- H3DSAMPLE sample3D;
- if( !handleToKill || foundSoundToReplace )
- {
- sample3D = getFirst3DSample( event );
- if( !sample3D )
- {
- //If we don't have an available sample, kill the lowest priority assuming we have one that is lower
- //than the sound we are trying to add. One possibility for strangeness is when an interrupt sound
- //that wants to kill a handle to replace it, it's possible that another request already killed it,
- //in which case we need to attempt to find another sound to kill.
- if( killLowestPrioritySoundImmediately( event ) )
- {
- sample3D = getFirst3DSample( event );
- }
- }
- }
- else
- {
- sample3D = NULL;
- }
- // Push it onto the list of playing things
- audio->m_audioEventRTS = event;
- audio->m_3DSample = sample3D;
- audio->m_file = NULL;
- audio->m_type = PAT_3DSample;
- m_playing3DSounds.push_back(audio);
- if (sample3D) {
- audio->m_file = playSample3D(event, sample3D);
- m_sound->notifyOf3DSampleStart();
- }
- if( !audio->m_file )
- {
- m_playing3DSounds.pop_back();
- #ifdef INTENSIVE_AUDIO_DEBUG
- DEBUG_LOG((" Killed (no handles available)\n"));
- #endif
- }
- else
- {
- audio = NULL;
- #ifdef INTENSIVE_AUDIO_DEBUG
- DEBUG_LOG((" Playing.\n"));
- #endif
- }
- }
- else
- {
- // UI sounds are always 2-D. All other sounds should be Positional
- // Unit acknowledgement, etc, falls into the UI category of sound.
- Bool foundSoundToReplace = false;
- if (handleToKill) {
- for (it = m_playingSounds.begin(); it != m_playingSounds.end(); ++it) {
- playing = (*it);
- if (!playing) {
- continue;
- }
- if (playing->m_audioEventRTS && playing->m_audioEventRTS->getPlayingHandle() == handleToKill)
- {
- //Release this 2D sound channel immediately because we are going to play another sound in it's place.
- releasePlayingAudio(playing);
- m_playingSounds.erase(it);
- foundSoundToReplace = true;
- break;
- }
- }
- }
- HSAMPLE sample;
- if( !handleToKill || foundSoundToReplace )
- {
- sample = getFirst2DSample(event);
- if( !sample )
- {
- //If we don't have an available sample, kill the lowest priority assuming we have one that is lower
- //than the sound we are trying to add. One possibility for strangeness is when an interrupt sound
- //that wants to kill a handle to replace it, it's possible that another request already killed it,
- //in which case we need to attempt to find another sound to kill.
- if( killLowestPrioritySoundImmediately( event ) )
- {
- sample = getFirst2DSample( event );
- }
- }
- }
- else
- {
- sample = NULL;
- }
- // Push it onto the list of playing things
- audio->m_audioEventRTS = event;
- audio->m_sample = sample;
- audio->m_file = NULL;
- audio->m_type = PAT_Sample;
- m_playingSounds.push_back(audio);
- if (sample) {
- audio->m_file = playSample(event, sample);
- m_sound->notifyOf2DSampleStart();
- }
- if (!audio->m_file) {
- #ifdef INTENSIVE_AUDIO_DEBUG
- DEBUG_LOG((" Killed (no handles available)\n"));
- #endif
- m_playingSounds.pop_back();
- } else {
- audio = NULL;
- }
- #ifdef INTENSIVE_AUDIO_DEBUG
- DEBUG_LOG((" Playing.\n"));
- #endif
- }
- break;
- }
- }
- // If we were able to successfully play audio, then we set it to NULL above. (And it will be freed
- // later. However, if audio is non-NULL at this point, then it must be freed.
- if (audio) {
- releasePlayingAudio(audio);
- }
- }
- //-------------------------------------------------------------------------------------------------
- void MilesAudioManager::stopAudioEvent( AudioHandle handle )
- {
- #ifdef INTENSIVE_AUDIO_DEBUG
- DEBUG_LOG(("MILES (%d) - Processing stop request: %d\n", TheGameLogic->getFrame(), handle));
- #endif
- std::list<PlayingAudio *>::iterator it;
- if ( handle == AHSV_StopTheMusic || handle == AHSV_StopTheMusicFade ) {
- // for music, just find the currently playing music stream and kill it.
- for ( it = m_playingStreams.begin(); it != m_playingStreams.end(); ++it ) {
- PlayingAudio *audio = (*it);
- if (!audio) {
- continue;
- }
- if( audio->m_audioEventRTS->getAudioEventInfo()->m_soundType == AT_Music )
- {
- if( handle == AHSV_StopTheMusicFade )
- {
- m_fadingAudio.push_back(audio);
- }
- else
- {
- //m_stoppedAudio.push_back(audio);
- releasePlayingAudio( audio );
- }
- m_playingStreams.erase(it);
- break;
- }
- }
- }
- for ( it = m_playingStreams.begin(); it != m_playingStreams.end(); ++it ) {
- PlayingAudio *audio = (*it);
- if (!audio) {
- continue;
- }
- if (audio->m_audioEventRTS->getPlayingHandle() == handle) {
- // found it
- audio->m_requestStop = true;
- notifyOfAudioCompletion((UnsignedInt)(audio->m_stream), PAT_Stream);
- break;
- }
- }
- for ( it = m_playingSounds.begin(); it != m_playingSounds.end(); ++it ) {
- PlayingAudio *audio = (*it);
- if (!audio) {
- continue;
- }
- if (audio->m_audioEventRTS->getPlayingHandle() == handle) {
- audio->m_requestStop = true;
- break;
- }
- }
- for ( it = m_playing3DSounds.begin(); it != m_playing3DSounds.end(); ++it ) {
- PlayingAudio *audio = (*it);
- if (!audio) {
- continue;
- }
- if (audio->m_audioEventRTS->getPlayingHandle() == handle) {
- #ifdef INTENSIVE_AUDIO_DEBUG
- DEBUG_LOG((" (%s)\n", audio->m_audioEventRTS->getEventName()));
- #endif
- audio->m_requestStop = true;
- break;
- }
- }
- }
- //-------------------------------------------------------------------------------------------------
- void MilesAudioManager::killAudioEventImmediately( AudioHandle audioEvent )
- {
- //First look for it in the request list.
- std::list<AudioRequest*>::iterator ait;
- for( ait = m_audioRequests.begin(); ait != m_audioRequests.end(); ait++ )
- {
- AudioRequest *req = (*ait);
- if( req && req->m_request == AR_Play && req->m_handleToInteractOn == audioEvent )
- {
- req->deleteInstance();
- ait = m_audioRequests.erase(ait);
- return;
- }
- }
- //Look for matching 3D sound to kill
- std::list<PlayingAudio *>::iterator it;
- for( it = m_playing3DSounds.begin(); it != m_playing3DSounds.end(); it++ )
- {
- PlayingAudio *audio = (*it);
- if( !audio )
- {
- continue;
- }
- if( audio->m_audioEventRTS->getPlayingHandle() == audioEvent )
- {
- releasePlayingAudio( audio );
- m_playing3DSounds.erase( it );
- return;
- }
- }
- //Look for matching 2D sound to kill
- for( it = m_playingSounds.begin(); it != m_playingSounds.end(); it++ )
- {
- PlayingAudio *audio = (*it);
- if( !audio )
- {
- continue;
- }
- if( audio->m_audioEventRTS->getPlayingHandle() == audioEvent )
- {
- releasePlayingAudio( audio );
- m_playingSounds.erase( it );
- return;
- }
- }
- //Look for matching steaming sound to kill
- for( it = m_playingStreams.begin(); it != m_playingStreams.end(); it++ )
- {
- PlayingAudio *audio = (*it);
- if( !audio )
- {
- continue;
- }
- if( audio->m_audioEventRTS->getPlayingHandle() == audioEvent )
- {
- releasePlayingAudio( audio );
- m_playingStreams.erase( it );
- return;
- }
- }
- }
- //-------------------------------------------------------------------------------------------------
- void MilesAudioManager::pauseAudioEvent( AudioHandle handle )
- {
- // pause audio
- }
- //-------------------------------------------------------------------------------------------------
- void *MilesAudioManager::loadFileForRead( AudioEventRTS *eventToLoadFrom )
- {
- return m_audioCache->openFile(eventToLoadFrom);
- }
- //-------------------------------------------------------------------------------------------------
- void MilesAudioManager::closeFile( void *fileRead )
- {
- m_audioCache->closeFile(fileRead);
- }
- //-------------------------------------------------------------------------------------------------
- PlayingAudio *MilesAudioManager::allocatePlayingAudio( void )
- {
- PlayingAudio *aud = NEW PlayingAudio; // poolify
- aud->m_status = PS_Playing;
- return aud;
- }
- //-------------------------------------------------------------------------------------------------
- void MilesAudioManager::releaseMilesHandles( PlayingAudio *release )
- {
- switch (release->m_type)
- {
- case PAT_Sample:
- {
- if (release->m_sample) {
- AIL_register_EOS_callback(release->m_sample, NULL);
- AIL_stop_sample(release->m_sample);
- m_availableSamples.push_back(release->m_sample);
- }
- break;
- }
- case PAT_3DSample:
- {
- if (release->m_3DSample) {
- AIL_register_3D_EOS_callback(release->m_3DSample, NULL);
- AIL_stop_3D_sample(release->m_3DSample);
- m_available3DSamples.push_back(release->m_3DSample);
- }
- break;
- }
- case PAT_Stream:
- {
- if (release->m_stream) {
- AIL_register_stream_callback(release->m_stream, NULL);
- AIL_close_stream(release->m_stream);
- }
- break;
- }
- }
- release->m_type = PAT_INVALID;
- }
- //-------------------------------------------------------------------------------------------------
- void MilesAudioManager::releasePlayingAudio( PlayingAudio *release )
- {
- if (release->m_audioEventRTS->getAudioEventInfo()->m_soundType == AT_SoundEffect) {
- if (release->m_type == PAT_Sample) {
- if (release->m_sample) {
- m_sound->notifyOf2DSampleCompletion();
- }
- } else {
- if (release->m_3DSample) {
- m_sound->notifyOf3DSampleCompletion();
- }
- }
- }
- releaseMilesHandles(release); // forces stop of this audio
- closeFile( release->m_file );
- if (release->m_cleanupAudioEventRTS) {
- releaseAudioEventRTS(release->m_audioEventRTS);
- }
- delete release;
- release = NULL;
- }
- //-------------------------------------------------------------------------------------------------
- void MilesAudioManager::stopAllAudioImmediately( void )
- {
- std::list<PlayingAudio *>::iterator it;
- PlayingAudio *playing;
- for (it = m_playingSounds.begin(); it != m_playingSounds.end(); ) {
- playing = *it;
- if (!playing) {
- continue;
- }
- releasePlayingAudio(playing);
- it = m_playingSounds.erase(it);
- }
- for (it = m_playing3DSounds.begin(); it != m_playing3DSounds.end(); ) {
- playing = *it;
- if (!playing) {
- continue;
- }
- releasePlayingAudio(playing);
- it = m_playing3DSounds.erase(it);
- }
- for (it = m_playingStreams.begin(); it != m_playingStreams.end(); ) {
- playing = (*it);
- if (!playing) {
- continue;
- }
- releasePlayingAudio(playing);
- it = m_playingStreams.erase(it);
- }
- for (it = m_fadingAudio.begin(); it != m_fadingAudio.end(); ) {
- playing = (*it);
- if (!playing) {
- continue;
- }
-
- releasePlayingAudio(playing);
- it = m_fadingAudio.erase(it);
- }
-
- std::list<HAUDIO>::iterator hit;
- for (hit = m_audioForcePlayed.begin(); hit != m_audioForcePlayed.end(); ++hit) {
- if (*hit) {
- AIL_quick_unload(*hit);
- }
- }
- m_audioForcePlayed.clear();
- }
- //-------------------------------------------------------------------------------------------------
- void MilesAudioManager::freeAllMilesHandles( void )
- {
- // First, we need to ensure that we don't have any sample handles open. To that end, we must stop
- // all of our currently playing audio.
- stopAllAudioImmediately();
- // Walks through the available 2-D and 3-D handles and releases them
- std::list<HSAMPLE>::iterator it;
- for ( it = m_availableSamples.begin(); it != m_availableSamples.end(); /* empty */ ) {
- HSAMPLE sample = *it;
- AIL_release_sample_handle(sample);
- it = m_availableSamples.erase(it);
- }
- m_num2DSamples = 0;
-
- std::list<H3DSAMPLE>::iterator it3D;
- for ( it3D = m_available3DSamples.begin(); it3D != m_available3DSamples.end(); /* empty */ ) {
- H3DSAMPLE sample3D = *it3D;
- AIL_release_3D_sample_handle(sample3D);
- it3D = m_available3DSamples.erase(it3D);
- }
- m_num3DSamples = 0;
- m_numStreams = 0;
- }
- //-------------------------------------------------------------------------------------------------
- HSAMPLE MilesAudioManager::getFirst2DSample( AudioEventRTS *event )
- {
- if (m_availableSamples.begin() != m_availableSamples.end()) {
- HSAMPLE retSample = *m_availableSamples.begin();
- m_availableSamples.erase(m_availableSamples.begin());
- return (retSample);
- }
- // Find the first sample of lower priority than my augmented priority that is interruptable and take its handle
- return NULL;
- }
- //-------------------------------------------------------------------------------------------------
- H3DSAMPLE MilesAudioManager::getFirst3DSample( AudioEventRTS *event )
- {
- if (m_available3DSamples.begin() != m_available3DSamples.end()) {
- H3DSAMPLE retSample = *m_available3DSamples.begin();
- m_available3DSamples.erase(m_available3DSamples.begin());
- return (retSample);
- }
- // Find the first sample of lower priority than my augmented priority that is interruptable and take its handle
- return NULL;
- }
- //-------------------------------------------------------------------------------------------------
- void MilesAudioManager::adjustPlayingVolume( PlayingAudio *audio )
- {
- Real desiredVolume = audio->m_audioEventRTS->getVolume() * audio->m_audioEventRTS->getVolumeShift();
- Real pan;
- if (audio->m_type == PAT_Sample) {
- AIL_sample_volume_pan(audio->m_sample, NULL, &pan);
- AIL_set_sample_volume_pan(audio->m_sample, m_soundVolume * desiredVolume, pan);
- } else if (audio->m_type == PAT_3DSample) {
- AIL_set_3D_sample_volume(audio->m_3DSample, m_sound3DVolume * desiredVolume);
- } else if (audio->m_type == PAT_Stream) {
- AIL_stream_volume_pan(audio->m_stream, NULL, &pan);
- if (audio->m_audioEventRTS->getAudioEventInfo()->m_soundType == AT_Music ) {
- AIL_set_stream_volume_pan(audio->m_stream, m_musicVolume * desiredVolume, pan);
-
- } else {
- AIL_set_stream_volume_pan(audio->m_stream, m_speechVolume * desiredVolume, pan);
-
- }
- }
- }
- //-------------------------------------------------------------------------------------------------
- void MilesAudioManager::stopAllSpeech( void )
- {
- std::list<PlayingAudio *>::iterator it;
- PlayingAudio *playing;
- for (it = m_playingStreams.begin(); it != m_playingStreams.end(); ) {
- playing = (*it);
- if (!playing) {
- continue;
- }
- if (playing->m_audioEventRTS->getAudioEventInfo()->m_soundType == AT_Streaming) {
- releasePlayingAudio(playing);
- it = m_playingStreams.erase(it);
- } else {
- ++it;
- }
- }
- }
- //-------------------------------------------------------------------------------------------------
- void MilesAudioManager::initFilters( HSAMPLE sample, const AudioEventRTS *event )
- {
- // set the sample volume
- Real volume = event->getVolume() * event->getVolumeShift() * m_soundVolume;
- AIL_set_sample_volume_pan(sample, volume, 0.5f);
- // pitch shift
- Real pitchShift = event->getPitchShift();
- if (pitchShift == 0.0f) {
- DEBUG_CRASH(("Invalid Pitch shift in sound: '%s'", event->getEventName().str()) );
- } else {
- AIL_set_sample_playback_rate(sample, REAL_TO_INT(AIL_sample_playback_rate(sample) * pitchShift));
- }
- // set up delay filter, if applicable
- if (event->getDelay() > 0.0f) {
- Real value;
- value = event->getDelay();
- AIL_set_sample_processor(sample, DP_FILTER, m_delayFilter);
- AIL_set_filter_sample_preference(sample, "Mono Delay Time", &value);
- value = 0.0;
- AIL_set_filter_sample_preference(sample, "Mono Delay", &value);
- AIL_set_filter_sample_preference(sample, "Mono Delay Mix", &value);
- }
- }
- //-------------------------------------------------------------------------------------------------
- void MilesAudioManager::initFilters3D( H3DSAMPLE sample, const AudioEventRTS *event, const Coord3D *pos )
- {
- // set the sample volume
- Real volume = event->getVolume() * event->getVolumeShift() * m_sound3DVolume;
- AIL_set_3D_sample_volume(sample, volume);
- // pitch shift
- Real pitchShift = event->getPitchShift();
- if (pitchShift == 0.0f) {
- DEBUG_CRASH(("Invalid Pitch shift in sound: '%s'", event->getEventName().str()) );
- } else {
- AIL_set_3D_sample_playback_rate(sample, REAL_TO_INT(AIL_3D_sample_playback_rate(sample) * pitchShift));
- }
-
- // Low pass filter
- if (event->getAudioEventInfo()->m_lowPassFreq > 0 && !isOnScreen(pos) ) {
- AIL_set_3D_sample_occlusion(sample, 1.0f - event->getAudioEventInfo()->m_lowPassFreq);
- }
- }
- //-------------------------------------------------------------------------------------------------
- void MilesAudioManager::nextMusicTrack( void )
- {
- AsciiString trackName;
- std::list<PlayingAudio *>::iterator it;
- PlayingAudio *playing;
- for (it = m_playingStreams.begin(); it != m_playingStreams.end(); ++it) {
- playing = *it;
- if (playing && playing->m_audioEventRTS->getAudioEventInfo()->m_soundType == AT_Music) {
- trackName = playing->m_audioEventRTS->getEventName();
- }
- }
- // Stop currently playing music
- TheAudio->removeAudioEvent(AHSV_StopTheMusic);
- trackName = nextTrackName(trackName);
- AudioEventRTS newTrack(trackName);
- TheAudio->addAudioEvent(&newTrack);
- }
- //-------------------------------------------------------------------------------------------------
- void MilesAudioManager::prevMusicTrack( void )
- {
- AsciiString trackName;
- std::list<PlayingAudio *>::iterator it;
- PlayingAudio *playing;
- for (it = m_playingStreams.begin(); it != m_playingStreams.end(); ++it) {
- playing = *it;
- if (playing && playing->m_audioEventRTS->getAudioEventInfo()->m_soundType == AT_Music) {
- trackName = playing->m_audioEventRTS->getEventName();
- }
- }
- // Stop currently playing music
- TheAudio->removeAudioEvent(AHSV_StopTheMusic);
- trackName = prevTrackName(trackName);
- AudioEventRTS newTrack(trackName);
- TheAudio->addAudioEvent(&newTrack);
- }
- //-------------------------------------------------------------------------------------------------
- Bool MilesAudioManager::isMusicPlaying( void ) const
- {
- std::list<PlayingAudio *>::const_iterator it;
- PlayingAudio *playing;
- for (it = m_playingStreams.begin(); it != m_playingStreams.end(); ++it) {
- playing = *it;
- if (playing && playing->m_audioEventRTS->getAudioEventInfo()->m_soundType == AT_Music) {
- return TRUE;
- }
- }
- return FALSE;
- }
- //-------------------------------------------------------------------------------------------------
- Bool MilesAudioManager::hasMusicTrackCompleted( const AsciiString& trackName, Int numberOfTimes ) const
- {
- std::list<PlayingAudio *>::const_iterator it;
- PlayingAudio *playing;
- for (it = m_playingStreams.begin(); it != m_playingStreams.end(); ++it) {
- playing = *it;
- if (playing && playing->m_audioEventRTS->getAudioEventInfo()->m_soundType == AT_Music) {
- if (playing->m_audioEventRTS->getEventName() == trackName) {
- if (INFINITE_LOOP_COUNT - AIL_stream_loop_count(playing->m_stream) >= numberOfTimes) {
- return TRUE;
- }
- }
- }
- }
- return FALSE;
- }
- //-------------------------------------------------------------------------------------------------
- AsciiString MilesAudioManager::getMusicTrackName( void ) const
- {
- // First check the requests. If there's one there, then report that as the currently playing track.
- std::list<AudioRequest *>::const_iterator ait;
- for (ait = m_audioRequests.begin(); ait != m_audioRequests.end(); ++ait) {
- if ((*ait)->m_request != AR_Play) {
- continue;
- }
- if (!(*ait)->m_usePendingEvent) {
- continue;
- }
- if ((*ait)->m_pendingEvent->getAudioEventInfo()->m_soundType == AT_Music) {
- return (*ait)->m_pendingEvent->getEventName();
- }
- }
- std::list<PlayingAudio *>::const_iterator it;
- PlayingAudio *playing;
- for (it = m_playingStreams.begin(); it != m_playingStreams.end(); ++it) {
- playing = *it;
- if (playing && playing->m_audioEventRTS->getAudioEventInfo()->m_soundType == AT_Music) {
- return playing->m_audioEventRTS->getEventName();
- }
- }
- return AsciiString::TheEmptyString;
- }
- //-------------------------------------------------------------------------------------------------
- void MilesAudioManager::openDevice( void )
- {
- if (!TheGlobalData->m_audioOn) {
- return;
- }
-
- AIL_set_redist_directory("MSS\\");
- AIL_startup();
- Int retval = 0;
- // AIL_quick_startup should be replaced later with a call to actually pick which device to use, etc
- const AudioSettings *audioSettings = getAudioSettings();
- m_selectedSpeakerType = TheAudio->translateSpeakerTypeToUnsignedInt(m_prefSpeaker);
- retval = AIL_quick_startup(audioSettings->m_useDigital, audioSettings->m_useMidi, audioSettings->m_outputRate, audioSettings->m_outputBits, audioSettings->m_outputChannels);
-
- // Quick handles tells us where to store the various devices. For now, we're only interested in the digital handle.
- AIL_quick_handles(&m_digitalHandle, NULL, NULL);
-
- if (retval) {
- buildProviderList();
- } else {
- // if we couldn't initialize any devices, turn sound off (fail silently)
- setOn( false, AudioAffect_All );
- }
- selectProvider(TheAudio->getProviderIndex(m_pref3DProvider));
- // Now that we're all done, update the cached variables so that everything is in sync.
- TheAudio->refreshCachedVariables();
- if (!isValidProvider()) {
- return;
- }
- initDelayFilter();
- }
- //-------------------------------------------------------------------------------------------------
- void MilesAudioManager::closeDevice( void )
- {
- freeAllMilesHandles();
- unselectProvider();
- AIL_shutdown();
- }
- //-------------------------------------------------------------------------------------------------
- Bool MilesAudioManager::isCurrentlyPlaying( AudioHandle handle )
- {
- std::list<PlayingAudio *>::iterator it;
- PlayingAudio *playing;
- for (it = m_playingSounds.begin(); it != m_playingSounds.end(); ++it) {
- playing = *it;
- if (playing && playing->m_audioEventRTS->getPlayingHandle() == handle) {
- return true;
- }
- }
- for (it = m_playing3DSounds.begin(); it != m_playing3DSounds.end(); ++it) {
- playing = *it;
- if (playing && playing->m_audioEventRTS->getPlayingHandle() == handle) {
- return true;
- }
- }
- for (it = m_playingStreams.begin(); it != m_playingStreams.end(); ++it) {
- playing = *it;
- if (playing && playing->m_audioEventRTS->getPlayingHandle() == handle) {
- return true;
- }
- }
- // if something is requested, it is also considered playing
- std::list<AudioRequest *>::iterator ait;
- AudioRequest *req = NULL;
- for (ait = m_audioRequests.begin(); ait != m_audioRequests.end(); ++ait) {
- req = *ait;
- if (req && req->m_usePendingEvent && req->m_pendingEvent->getPlayingHandle() == handle) {
- return true;
- }
- }
- return false;
- }
- //-------------------------------------------------------------------------------------------------
- void MilesAudioManager::notifyOfAudioCompletion( UnsignedInt audioCompleted, UnsignedInt flags )
- {
- PlayingAudio *playing = findPlayingAudioFrom(audioCompleted, flags);
- if (!playing) {
- DEBUG_CRASH(("Audio has completed playing, but we can't seem to find it. - jkmcd"));
- return;
- }
-
- if (getDisallowSpeech() && playing->m_audioEventRTS->getAudioEventInfo()->m_soundType == AT_Streaming) {
- setDisallowSpeech(FALSE);
- }
- if (playing->m_audioEventRTS->getAudioEventInfo()->m_control & AC_LOOP) {
- if (playing->m_audioEventRTS->getNextPlayPortion() == PP_Attack) {
- playing->m_audioEventRTS->setNextPlayPortion(PP_Sound);
- }
- if (playing->m_audioEventRTS->getNextPlayPortion() == PP_Sound) {
- // First, decrease the loop count.
- playing->m_audioEventRTS->decreaseLoopCount();
- // Now, try to start the next loop
- if (startNextLoop(playing)) {
- return;
- }
- }
- }
- playing->m_audioEventRTS->advanceNextPlayPortion();
- if (playing->m_audioEventRTS->getNextPlayPortion() != PP_Done) {
- if (playing->m_type == PAT_Sample) {
- closeFile(playing->m_file); // close it so as not to leak it.
- playing->m_file = playSample(playing->m_audioEventRTS, playing->m_sample);
-
- // If we don't have a file now, then we should drop to the stopped status so that
- // We correctly close this handle.
- if (playing->m_file) {
- return;
- }
- } else if (playing->m_type == PAT_3DSample) {
- closeFile(playing->m_file); // close it so as not to leak it.
- playing->m_file = playSample3D(playing->m_audioEventRTS, playing->m_3DSample);
- // If we don't have a file now, then we should drop to the stopped status so that
- // We correctly close this handle.
- if (playing->m_file) {
- return;
- }
- }
- }
- if (playing->m_type == PAT_Stream) {
- if (playing->m_audioEventRTS->getAudioEventInfo()->m_soundType == AT_Music) {
- playStream(playing->m_audioEventRTS, playing->m_stream);
-
- return;
- }
- }
- playing->m_status = PS_Stopped; // it will be cleaned up on the next frame update
- }
- //-------------------------------------------------------------------------------------------------
- PlayingAudio *MilesAudioManager::findPlayingAudioFrom( UnsignedInt audioCompleted, UnsignedInt flags )
- {
- std::list<PlayingAudio *>::iterator it;
- PlayingAudio *playing;
- if (flags == PAT_Sample) {
- HSAMPLE sample = (HSAMPLE) audioCompleted;
- for (it = m_playingSounds.begin(); it != m_playingSounds.end(); ++it) {
- playing = *it;
- if (playing && playing->m_sample == sample) {
- return playing;
- }
- }
- }
- if (flags == PAT_3DSample) {
- H3DSAMPLE sample3D = (H3DSAMPLE) audioCompleted;
- for (it = m_playing3DSounds.begin(); it != m_playing3DSounds.end(); ++it) {
- playing = *it;
- if (playing && playing->m_3DSample == sample3D) {
- return playing;
- }
- }
- }
- if (flags == PAT_Stream) {
- HSTREAM stream = (HSTREAM) audioCompleted;
- for (it = m_playingStreams.begin(); it != m_playingStreams.end(); ++it) {
- playing = *it;
- if (playing && playing->m_stream == stream) {
- return playing;
- }
- }
- }
- return NULL;
- }
- //-------------------------------------------------------------------------------------------------
- UnsignedInt MilesAudioManager::getProviderCount( void ) const
- {
- return m_providerCount;
- }
- //-------------------------------------------------------------------------------------------------
- AsciiString MilesAudioManager::getProviderName( UnsignedInt providerNum ) const
- {
- if (isOn(AudioAffect_Sound3D) && providerNum < m_providerCount) {
- return m_provider3D[providerNum].name;
- }
- return AsciiString::TheEmptyString;
- }
- //-------------------------------------------------------------------------------------------------
- UnsignedInt MilesAudioManager::getProviderIndex( AsciiString providerName ) const
- {
- for (UnsignedInt i = 0; i < m_providerCount; ++i) {
- if (providerName == m_provider3D[i].name) {
- return i;
- }
- }
- return PROVIDER_ERROR;
- }
- //-------------------------------------------------------------------------------------------------
- void MilesAudioManager::selectProvider( UnsignedInt providerNdx )
- {
- if (!isOn(AudioAffect_Sound3D))
- {
- return;
- }
- if (providerNdx == m_selectedProvider)
- {
- return;
- }
- if (isValidProvider())
- {
- freeAllMilesHandles();
- unselectProvider();
- }
- LPDIRECTSOUND lpDirectSoundInfo;
- AIL_get_DirectSound_info( NULL, (void**)&lpDirectSoundInfo, NULL );
- Bool useDolby = FALSE;
- if( lpDirectSoundInfo )
- {
- DWORD speakerConfig;
- lpDirectSoundInfo->GetSpeakerConfig( &speakerConfig );
- switch( DSSPEAKER_CONFIG( speakerConfig ) )
- {
- case DSSPEAKER_DIRECTOUT:
- m_selectedSpeakerType = AIL_3D_2_SPEAKER;
- break;
- case DSSPEAKER_MONO:
- m_selectedSpeakerType = AIL_3D_2_SPEAKER;
- break;
- case DSSPEAKER_STEREO:
- m_selectedSpeakerType = AIL_3D_2_SPEAKER;
- break;
- case DSSPEAKER_HEADPHONE:
- m_selectedSpeakerType = AIL_3D_HEADPHONE;
- useDolby = TRUE;
- break;
- case DSSPEAKER_QUAD:
- m_selectedSpeakerType = AIL_3D_4_SPEAKER;
- useDolby = TRUE;
- break;
- case DSSPEAKER_SURROUND:
- m_selectedSpeakerType = AIL_3D_SURROUND;
- useDolby = TRUE;
- break;
- case DSSPEAKER_5POINT1:
- m_selectedSpeakerType = AIL_3D_51_SPEAKER;
- useDolby = TRUE;
- break;
- case DSSPEAKER_7POINT1:
- m_selectedSpeakerType = AIL_3D_71_SPEAKER;
- useDolby = TRUE;
- break;
- }
- }
- Bool success = FALSE;
- if( useDolby )
- {
- providerNdx = getProviderIndex( "Dolby Surround" );
- }
- else
- {
- providerNdx = getProviderIndex( "Miles Fast 2D Positional Audio" );
- }
- success = AIL_open_3D_provider( m_provider3D[providerNdx].id ) == 0;
- //if (providerNdx < m_providerCount)
- //{
- // failed = AIL_open_3D_provider(m_provider3D[providerNdx].id);
- //}
- if( !success )
- {
- m_selectedProvider = PROVIDER_ERROR;
- // try to select a failsafe
- providerNdx = getProviderIndex( "Miles Fast 2D Positional Audio" );
- success = AIL_open_3D_provider( m_provider3D[providerNdx].id ) == 0;
- }
- if ( success )
- {
- m_selectedProvider = providerNdx;
-
- initSamplePools();
-
- createListener();
- setSpeakerType(m_selectedSpeakerType);
- if (TheVideoPlayer)
- {
- TheVideoPlayer->notifyVideoPlayerOfNewProvider(TRUE);
- }
- }
- }
- //-------------------------------------------------------------------------------------------------
- void MilesAudioManager::unselectProvider( void )
- {
- if (!(isOn(AudioAffect_Sound3D) && isValidProvider())) {
- return;
- }
- if (TheVideoPlayer) {
- TheVideoPlayer->notifyVideoPlayerOfNewProvider(FALSE);
- }
- AIL_close_3D_listener(m_listener);
- m_listener = NULL;
- AIL_close_3D_provider(m_provider3D[m_selectedProvider].id);
- m_lastProvider = m_selectedProvider;
- m_selectedProvider = PROVIDER_ERROR;
- }
- //-------------------------------------------------------------------------------------------------
- UnsignedInt MilesAudioManager::getSelectedProvider( void ) const
- {
- return m_selectedProvider;
- }
- //-------------------------------------------------------------------------------------------------
- void MilesAudioManager::setSpeakerType( UnsignedInt speakerType )
- {
- if (!isValidProvider()) {
- return;
- }
-
- AIL_set_3D_speaker_type( m_provider3D[m_selectedProvider].id, speakerType );
- m_selectedSpeakerType = speakerType;
- }
- //-------------------------------------------------------------------------------------------------
- UnsignedInt MilesAudioManager::getSpeakerType( void )
- {
- if (!isValidProvider()) {
- return 0;
- }
- return m_selectedSpeakerType;
- }
- //-------------------------------------------------------------------------------------------------
- UnsignedInt MilesAudioManager::getNum2DSamples( void ) const
- {
- return m_num2DSamples;
- }
- //-------------------------------------------------------------------------------------------------
- UnsignedInt MilesAudioManager::getNum3DSamples( void ) const
- {
- return m_num3DSamples;
- }
- //-------------------------------------------------------------------------------------------------
- UnsignedInt MilesAudioManager::getNumStreams( void ) const
- {
- return m_numStreams;
- }
- //-------------------------------------------------------------------------------------------------
- Bool MilesAudioManager::doesViolateLimit( AudioEventRTS *event ) const
- {
- Int limit = event->getAudioEventInfo()->m_limit;
- if (limit == 0) {
- return false;
- }
- Int totalCount = 0;
- Int totalRequestCount = 0;
- std::list<PlayingAudio *>::const_iterator it;
- if (!event->isPositionalAudio()) {
- // 2-D
- for ( it = m_playingSounds.begin(); it != m_playingSounds.end(); ++it ) {
- if ((*it)->m_audioEventRTS->getEventName() == event->getEventName()) {
- if (totalCount == 0) {
- // This is the oldest audio of this type playing.
- event->setHandleToKill((*it)->m_audioEventRTS->getPlayingHandle());
- }
- ++totalCount;
- }
- }
- } else {
- // 3-D
- for ( it = m_playing3DSounds.begin(); it != m_playing3DSounds.end(); ++it ) {
- if ((*it)->m_audioEventRTS->getEventName() == event->getEventName()) {
- if (totalCount == 0) {
- // This is the oldest audio of this type playing.
- event->setHandleToKill((*it)->m_audioEventRTS->getPlayingHandle());
- }
- ++totalCount;
- }
- }
- }
-
- // Also check the request list in case we've requested to play this sound.
- std::list<AudioRequest*>::const_iterator arIt;
- for (arIt = m_audioRequests.begin(); arIt != m_audioRequests.end(); ++arIt) {
- AudioRequest *req = (*arIt);
- if (req == NULL) {
- continue;
- }
- if( req->m_usePendingEvent )
- {
- if( req->m_pendingEvent->getEventName() == event->getEventName() )
- {
- totalRequestCount++;
- totalCount++;
- }
- }
- }
- //If our event is an interrupting type, then normally we would always add it. The exception is when we have requested
- //multiple sounds in the same frame and those requests violate the limit. Because we don't have any "old" sounds to
- //remove in the case of an interrupt, we need to catch it early and prevent the sound from being added if we already
- //reached the limit
- if( event->getAudioEventInfo()->m_control & AC_INTERRUPT )
- {
- if( totalRequestCount < limit )
- {
- Int totalPlayingCount = totalCount - totalRequestCount;
- if( totalRequestCount + totalPlayingCount < limit )
- {
- //We aren't exceeding the actual limit, then clear the kill handle.
- event->setHandleToKill(0);
- return false;
- }
- //We are exceeding the limit - the kill handle will kill the
- //oldest playing sound to enforce the actual limit.
- return false;
- }
- }
- if( totalCount < limit )
- {
- event->setHandleToKill(0);
- return false;
- }
- return true;
- }
- //-------------------------------------------------------------------------------------------------
- Bool MilesAudioManager::isPlayingAlready( AudioEventRTS *event ) const
- {
- std::list<PlayingAudio *>::const_iterator it;
- if (!event->isPositionalAudio()) {
- // 2-D
- for ( it = m_playingSounds.begin(); it != m_playingSounds.end(); ++it ) {
- if ((*it)->m_audioEventRTS->getEventName() == event->getEventName()) {
- return true;
- }
- }
- } else {
- // 3-D
- for ( it = m_playing3DSounds.begin(); it != m_playing3DSounds.end(); ++it ) {
- if ((*it)->m_audioEventRTS->getEventName() == event->getEventName()) {
- return true;
- }
- }
- }
- return false;
- }
- //-------------------------------------------------------------------------------------------------
- Bool MilesAudioManager::isObjectPlayingVoice( UnsignedInt objID ) const
- {
- if (objID == 0) {
- return false;
- }
- std::list<PlayingAudio *>::const_iterator it;
- // 2-D
- for ( it = m_playingSounds.begin(); it != m_playingSounds.end(); ++it ) {
- if ((*it)->m_audioEventRTS->getObjectID() == objID && (*it)->m_audioEventRTS->getAudioEventInfo()->m_type & ST_VOICE) {
- return true;
- }
- }
- // 3-D
- for ( it = m_playing3DSounds.begin(); it != m_playing3DSounds.end(); ++it ) {
- if ((*it)->m_audioEventRTS->getObjectID() == objID && (*it)->m_audioEventRTS->getAudioEventInfo()->m_type & ST_VOICE) {
- return true;
- }
- }
- return false;
- }
- //-------------------------------------------------------------------------------------------------
- AudioEventRTS* MilesAudioManager::findLowestPrioritySound( AudioEventRTS *event )
- {
- AudioPriority priority = event->getAudioEventInfo()->m_priority;
- if( priority == AP_LOWEST )
- {
- //If the event we pass in is the lowest priority, don't bother checking because
- //there is nothing lower priority than lowest.
- return NULL;
- }
- AudioEventRTS *lowestPriorityEvent = NULL;
- AudioPriority lowestPriority;
- std::list<PlayingAudio *>::const_iterator it;
- if( event->isPositionalAudio() )
- {
- //3D
- for( it = m_playing3DSounds.begin(); it != m_playing3DSounds.end(); ++it )
- {
- AudioEventRTS *itEvent = (*it)->m_audioEventRTS;
- AudioPriority itPriority = itEvent->getAudioEventInfo()->m_priority;
- if( itPriority < priority )
- {
- if( !lowestPriorityEvent || lowestPriority > itPriority )
- {
- lowestPriorityEvent = itEvent;
- lowestPriority = itPriority;
- if( lowestPriority == AP_LOWEST )
- {
- return lowestPriorityEvent;
- }
- }
- }
- }
- }
- else
- {
- //2D
- for( it = m_playingSounds.begin(); it != m_playingSounds.end(); ++it )
- {
- AudioEventRTS *itEvent = (*it)->m_audioEventRTS;
- AudioPriority itPriority = itEvent->getAudioEventInfo()->m_priority;
- if( itPriority < priority )
- {
- if( !lowestPriorityEvent || lowestPriority > itPriority )
- {
- lowestPriorityEvent = itEvent;
- lowestPriority = itPriority;
- if( lowestPriority == AP_LOWEST )
- {
- return lowestPriorityEvent;
- }
- }
- }
- }
- }
- return lowestPriorityEvent;
- }
- //-------------------------------------------------------------------------------------------------
- Bool MilesAudioManager::isPlayingLowerPriority( AudioEventRTS *event ) const
- {
- //We don't actually want to do anything to this CONST function. Remember, we're
- //just checking to see if there is a lower priority sound.
- AudioPriority priority = event->getAudioEventInfo()->m_priority;
- if( priority == AP_LOWEST )
- {
- //If the event we pass in is the lowest priority, don't bother checking because
- //there is nothing lower priority than lowest.
- return false;
- }
- std::list<PlayingAudio *>::const_iterator it;
- if (!event->isPositionalAudio()) {
- // 2-D
- for ( it = m_playingSounds.begin(); it != m_playingSounds.end(); ++it ) {
- if ((*it)->m_audioEventRTS->getAudioEventInfo()->m_priority < priority) {
- //event->setHandleToKill((*it)->m_audioEventRTS->getPlayingHandle());
- return true;
- }
- }
- } else {
- // 3-D
- for ( it = m_playing3DSounds.begin(); it != m_playing3DSounds.end(); ++it ) {
- if ((*it)->m_audioEventRTS->getAudioEventInfo()->m_priority < priority) {
- //event->setHandleToKill((*it)->m_audioEventRTS->getPlayingHandle());
- return true;
- }
- }
- }
- return false;
- }
- //-------------------------------------------------------------------------------------------------
- Bool MilesAudioManager::killLowestPrioritySoundImmediately( AudioEventRTS *event )
- {
- //Actually, we want to kill the LOWEST PRIORITY SOUND, not the first "lower" priority
- //sound we find, because it could easily be
- AudioEventRTS *lowestPriorityEvent = findLowestPrioritySound( event );
- if( lowestPriorityEvent )
- {
- std::list<PlayingAudio *>::iterator it;
- if( event->isPositionalAudio() )
- {
- for( it = m_playing3DSounds.begin(); it != m_playing3DSounds.end(); ++it )
- {
- PlayingAudio *playing = (*it);
- if( !playing )
- {
- continue;
- }
- if( playing->m_audioEventRTS && playing->m_audioEventRTS == lowestPriorityEvent )
- {
- //Release this 3D sound channel immediately because we are going to play another sound in it's place.
- releasePlayingAudio( playing );
- m_playing3DSounds.erase( it );
- return TRUE;
- }
- }
- }
- else
- {
- for( it = m_playingSounds.begin(); it != m_playingSounds.end(); ++it )
- {
- PlayingAudio *playing = (*it);
- if( !playing )
- {
- continue;
- }
- if( playing->m_audioEventRTS && playing->m_audioEventRTS == lowestPriorityEvent )
- {
- //Release this 3D sound channel immediately because we are going to play another sound in it's place.
- releasePlayingAudio( playing );
- m_playing3DSounds.erase( it );
- return TRUE;
- }
- }
- }
- }
- return FALSE;
- }
- //-------------------------------------------------------------------------------------------------
- void MilesAudioManager::adjustVolumeOfPlayingAudio(AsciiString eventName, Real newVolume)
- {
- Real pan;
- std::list<PlayingAudio *>::iterator it;
- PlayingAudio *playing = NULL;
- for (it = m_playingSounds.begin(); it != m_playingSounds.end(); ++it) {
- playing = *it;
- if (playing && playing->m_audioEventRTS->getEventName() == eventName) {
- // Adjust it
- playing->m_audioEventRTS->setVolume(newVolume);
- Real desiredVolume = playing->m_audioEventRTS->getVolume() * playing->m_audioEventRTS->getVolumeShift();
- AIL_sample_volume_pan(playing->m_sample, NULL, &pan);
- AIL_set_sample_volume_pan(playing->m_sample, desiredVolume, pan);
- }
- }
- for (it = m_playing3DSounds.begin(); it != m_playing3DSounds.end(); ++it) {
- playing = *it;
- if (playing && playing->m_audioEventRTS->getEventName() == eventName) {
- // Adjust it
- playing->m_audioEventRTS->setVolume(newVolume);
- Real desiredVolume = playing->m_audioEventRTS->getVolume() * playing->m_audioEventRTS->getVolumeShift();
- AIL_set_3D_sample_volume(playing->m_3DSample, desiredVolume);
- }
- }
- for (it = m_playingStreams.begin(); it != m_playingStreams.end(); ++it) {
- playing = *it;
- if (playing && playing->m_audioEventRTS->getEventName() == eventName) {
- // Adjust it
- playing->m_audioEventRTS->setVolume(newVolume);
- Real desiredVolume = playing->m_audioEventRTS->getVolume() * playing->m_audioEventRTS->getVolumeShift();
- AIL_stream_volume_pan(playing->m_stream, NULL, &pan);
- AIL_set_stream_volume_pan(playing->m_stream, desiredVolume, pan);
- }
- }
- }
- //-------------------------------------------------------------------------------------------------
- void MilesAudioManager::removePlayingAudio( AsciiString eventName )
- {
- std::list<PlayingAudio *>::iterator it;
- PlayingAudio *playing = NULL;
- for( it = m_playingSounds.begin(); it != m_playingSounds.end(); )
- {
- playing = *it;
- if( playing && playing->m_audioEventRTS->getEventName() == eventName )
- {
- releasePlayingAudio( playing );
- it = m_playingSounds.erase(it);
- }
- else
- {
- it++;
- }
- }
- for( it = m_playing3DSounds.begin(); it != m_playing3DSounds.end(); )
- {
- playing = *it;
- if( playing && playing->m_audioEventRTS->getEventName() == eventName )
- {
- releasePlayingAudio( playing );
- it = m_playing3DSounds.erase(it);
- }
- else
- {
- it++;
- }
- }
- for( it = m_playingStreams.begin(); it != m_playingStreams.end(); )
- {
- playing = *it;
- if( playing && playing->m_audioEventRTS->getEventName() == eventName )
- {
- releasePlayingAudio( playing );
- it = m_playingStreams.erase(it);
- }
- else
- {
- it++;
- }
- }
- }
- //-------------------------------------------------------------------------------------------------
- void MilesAudioManager::removeAllDisabledAudio()
- {
- std::list<PlayingAudio *>::iterator it;
- PlayingAudio *playing = NULL;
- for( it = m_playingSounds.begin(); it != m_playingSounds.end(); )
- {
- playing = *it;
- if( playing && playing->m_audioEventRTS->getVolume() == 0.0f )
- {
- releasePlayingAudio( playing );
- it = m_playingSounds.erase(it);
- }
- else
- {
- it++;
- }
- }
- for( it = m_playing3DSounds.begin(); it != m_playing3DSounds.end(); )
- {
- playing = *it;
- if( playing && playing->m_audioEventRTS->getVolume() == 0.0f )
- {
- releasePlayingAudio( playing );
- it = m_playing3DSounds.erase(it);
- }
- else
- {
- it++;
- }
- }
- for( it = m_playingStreams.begin(); it != m_playingStreams.end(); )
- {
- playing = *it;
- if( playing && playing->m_audioEventRTS->getVolume() == 0.0f )
- {
- releasePlayingAudio( playing );
- it = m_playingStreams.erase(it);
- }
- else
- {
- it++;
- }
- }
- }
- //-------------------------------------------------------------------------------------------------
- void MilesAudioManager::processRequestList( void )
- {
- std::list<AudioRequest*>::iterator it;
- for (it = m_audioRequests.begin(); it != m_audioRequests.end(); /* empty */) {
- AudioRequest *req = (*it);
- if (req == NULL) {
- continue;
- }
- if (!shouldProcessRequestThisFrame(req)) {
- adjustRequest(req);
- ++it;
- continue;
- }
- if (!req->m_requiresCheckForSample || checkForSample(req)) {
- processRequest(req);
- }
- req->deleteInstance();
- it = m_audioRequests.erase(it);
- }
- }
- //-------------------------------------------------------------------------------------------------
- void MilesAudioManager::processPlayingList( void )
- {
- // There are two types of processing we have to do here.
- // 1. Move the item to the stopped list if it has become stopped.
- // 2. Update the position of the audio if it is positional
- std::list<PlayingAudio *>::iterator it;
- PlayingAudio *playing;
- for (it = m_playingSounds.begin(); it != m_playingSounds.end(); /* empty */) {
- playing = (*it);
- if (!playing)
- {
- it = m_playingSounds.erase(it);
- continue;
- }
- if (playing->m_status == PS_Stopped)
- {
- //m_stoppedAudio.push_back(playing);
- releasePlayingAudio( playing );
- it = m_playingSounds.erase(it);
- }
- else
- {
- if (m_volumeHasChanged)
- {
- adjustPlayingVolume(playing);
- }
- ++it;
- }
- }
- for (it = m_playing3DSounds.begin(); it != m_playing3DSounds.end(); )
- {
- playing = (*it);
- if (!playing)
- {
- it = m_playing3DSounds.erase(it);
- continue;
- }
- if (playing->m_status == PS_Stopped)
- {
- //m_stoppedAudio.push_back(playing);
- releasePlayingAudio( playing );
- it = m_playing3DSounds.erase(it);
- }
- else
- {
- if (m_volumeHasChanged)
- {
- adjustPlayingVolume(playing);
- }
- const Coord3D *pos = getCurrentPositionFromEvent(playing->m_audioEventRTS);
- if (pos)
- {
- if( playing->m_audioEventRTS->isDead() )
- {
- stopAudioEvent( playing->m_audioEventRTS->getPlayingHandle() );
- it++;
- continue;
- }
- else
- {
- Real volForConsideration = getEffectiveVolume(playing->m_audioEventRTS);
- volForConsideration /= (m_sound3DVolume > 0.0f ? m_soundVolume : 1.0f);
- Bool playAnyways = BitTest( playing->m_audioEventRTS->getAudioEventInfo()->m_type, ST_GLOBAL) || playing->m_audioEventRTS->getAudioEventInfo()->m_priority == AP_CRITICAL;
- if( volForConsideration < m_audioSettings->m_minVolume && !playAnyways )
- {
- // don't want to get an additional callback for this sample
- AIL_register_3D_EOS_callback(playing->m_3DSample, NULL);
- //m_stoppedAudio.push_back(playing);
- releasePlayingAudio( playing );
- it = m_playing3DSounds.erase(it);
- continue;
- }
- else
- {
- Real x = pos->x;
- Real y = pos->y;
- Real z = pos->z;
- AIL_set_3D_position( playing->m_3DSample, x, y, z );
- }
- }
- }
- else
- {
- AIL_register_3D_EOS_callback(playing->m_3DSample, NULL);
- //m_stoppedAudio.push_back(playing);
- releasePlayingAudio( playing );
- it = m_playing3DSounds.erase(it);
- continue;
- }
- ++it;
- }
- }
- for (it = m_playingStreams.begin(); it != m_playingStreams.end(); ) {
- playing = (*it);
- if (!playing)
- {
- it = m_playingStreams.erase(it);
- continue;
- }
- if (playing->m_status == PS_Stopped)
- {
- //m_stoppedAudio.push_back(playing);
- releasePlayingAudio( playing );
- it = m_playingStreams.erase(it);
- }
- else
- {
- if (m_volumeHasChanged)
- {
- adjustPlayingVolume(playing);
- }
- ++it;
- }
- }
- if (m_volumeHasChanged) {
- m_volumeHasChanged = false;
- }
- }
- //Patch for a rare bug (only on about 5% of in-studio machines suffer, and not all the time) .
- //The actual mechanics of this problem are still elusive as of the date of this comment. 8/21/03
- //but the cause is clear. Some cinematics do a radical change in the microphone position, which
- //calls for a radical 3DSoundVolume adjustment. If this happens while a stereo stream is *ENDING*,
- //low-level code gets caught in a tight loop. (Hangs) on some machines.
- //To prevent this condition, we just suppress the updating of 3DSoundVolume while one of these
- //is on the list. Since the music tracks play continuously, they never *END* during these cinematics.
- //so we filter them out as, *NOT SENSITIVE*... we do want to update 3DSoundVolume during music,
- //which is almost all of the time.
- Bool MilesAudioManager::has3DSensitiveStreamsPlaying( void ) const
- {
- if ( m_playingStreams.empty() )
- return FALSE;
- for ( std::list< PlayingAudio* >::const_iterator it = m_playingStreams.begin(); it != m_playingStreams.end(); ++it )
- {
- const PlayingAudio *playing = (*it);
- if ( ! playing )
- continue;
- if ( playing->m_audioEventRTS->getAudioEventInfo()->m_soundType != AT_Music )
- {
- return TRUE;
- }
- if ( playing->m_audioEventRTS->getEventName().startsWith("Game_") == FALSE )
- {
- return TRUE;
- }
- }
-
- return FALSE;
- }
- //-------------------------------------------------------------------------------------------------
- void MilesAudioManager::processFadingList( void )
- {
- std::list<PlayingAudio *>::iterator it;
- PlayingAudio *playing;
- for (it = m_fadingAudio.begin(); it != m_fadingAudio.end(); /* emtpy */) {
- playing = *it;
- if (!playing) {
- continue;
- }
-
- if (playing->m_framesFaded >= getAudioSettings()->m_fadeAudioFrames) {
- playing->m_status = PS_Stopped;
- playing->m_requestStop = true;
- //m_stoppedAudio.push_back(playing);
- releasePlayingAudio( playing );
- it = m_fadingAudio.erase(it);
- continue;
- }
- ++playing->m_framesFaded;
- Real volume = getEffectiveVolume(playing->m_audioEventRTS);
- volume *= (1.0f - 1.0f * playing->m_framesFaded / getAudioSettings()->m_fadeAudioFrames);
- switch(playing->m_type)
- {
- case PAT_Sample:
- {
- AIL_set_sample_volume_pan(playing->m_sample, volume, 0.5f);
- break;
- }
- case PAT_3DSample:
- {
- AIL_set_3D_sample_volume(playing->m_3DSample, volume);
- break;
- }
-
- case PAT_Stream:
- {
- AIL_set_stream_volume_pan(playing->m_stream, volume, 0.5f);
- break;
- }
-
- }
-
- ++it;
- }
- }
- //-------------------------------------------------------------------------------------------------
- void MilesAudioManager::processStoppedList( void )
- {
- std::list<PlayingAudio *>::iterator it;
- PlayingAudio *playing;
- for (it = m_stoppedAudio.begin(); it != m_stoppedAudio.end(); /* emtpy */) {
- playing = *it;
- if (playing) {
- releasePlayingAudio(playing);
- }
- it = m_stoppedAudio.erase(it);
- }
- }
- //-------------------------------------------------------------------------------------------------
- Bool MilesAudioManager::shouldProcessRequestThisFrame( AudioRequest *req ) const
- {
- if (!req->m_usePendingEvent) {
- return true;
- }
- if (req->m_pendingEvent->getDelay() < MSEC_PER_LOGICFRAME_REAL) {
- return true;
- }
- return false;
- }
- //-------------------------------------------------------------------------------------------------
- void MilesAudioManager::adjustRequest( AudioRequest *req )
- {
- if (!req->m_usePendingEvent) {
- return;
- }
- req->m_pendingEvent->decrementDelay(MSEC_PER_LOGICFRAME_REAL);
- req->m_requiresCheckForSample = true;
- }
- //-------------------------------------------------------------------------------------------------
- Bool MilesAudioManager::checkForSample( AudioRequest *req )
- {
- if (!req->m_usePendingEvent) {
- return true;
- }
- if ( req->m_pendingEvent->getAudioEventInfo() == NULL )
- {
- // Fill in event info
- getInfoForAudioEvent( req->m_pendingEvent );
- }
-
- if (req->m_pendingEvent->getAudioEventInfo()->m_type != AT_SoundEffect)
- {
- return true;
- }
- return m_sound->canPlayNow(req->m_pendingEvent);
- }
- //-------------------------------------------------------------------------------------------------
- void MilesAudioManager::setHardwareAccelerated(Bool accel)
- {
- // Extends
- Bool retEarly = (accel == m_hardwareAccel);
- AudioManager::setHardwareAccelerated(accel);
- if (retEarly) {
- return;
- }
-
- if (m_hardwareAccel) {
- for (Int i = 0; i < MAX_HW_PROVIDERS; ++i) {
- UnsignedInt providerNdx = TheAudio->getProviderIndex(TheAudio->getAudioSettings()->m_preferred3DProvider[i]);
- TheAudio->selectProvider(providerNdx);
- if (getSelectedProvider() == providerNdx) {
- return;
- }
- }
- }
- // set it false
- AudioManager::setHardwareAccelerated(FALSE);
- UnsignedInt providerNdx = TheAudio->getProviderIndex(TheAudio->getAudioSettings()->m_preferred3DProvider[MAX_HW_PROVIDERS]);
- TheAudio->selectProvider(providerNdx);
- }
- //-------------------------------------------------------------------------------------------------
- void MilesAudioManager::setSpeakerSurround(Bool surround)
- {
- // Extends
- Bool retEarly = (surround == m_surroundSpeakers);
- AudioManager::setSpeakerSurround(surround);
- if (retEarly) {
- return;
- }
- UnsignedInt speakerType;
- if (m_surroundSpeakers) {
- speakerType = TheAudio->getAudioSettings()->m_defaultSpeakerType3D;
- } else {
- speakerType = TheAudio->getAudioSettings()->m_defaultSpeakerType2D;
- }
- TheAudio->setSpeakerType(speakerType);
- }
- //-------------------------------------------------------------------------------------------------
- Real MilesAudioManager::getFileLengthMS( AsciiString strToLoad ) const
- {
- if (strToLoad.isEmpty()) {
- return 0.0f;
- }
- // Load it as a stream to get the file info without actually opening the file.
- HSTREAM stream = AIL_open_stream(m_digitalHandle, strToLoad.str(), 0);
- if (!stream) {
- return 0.0f;
- }
- long retVal;
- AIL_stream_ms_position(stream, &retVal, NULL);
- // Now close the stream
- AIL_close_stream(stream);
- return INT_TO_REAL(retVal);
- }
- //-------------------------------------------------------------------------------------------------
- void MilesAudioManager::closeAnySamplesUsingFile( const void *fileToClose )
- {
- std::list<PlayingAudio *>::iterator it;
- PlayingAudio *playing;
-
- for (it = m_playingSounds.begin(); it != m_playingSounds.end(); ) {
- playing = *it;
- if (!playing) {
- continue;
- }
- if (playing->m_file == fileToClose) {
- releasePlayingAudio(playing);
- it = m_playingSounds.erase(it);
- } else {
- ++it;
- }
- }
- for (it = m_playing3DSounds.begin(); it != m_playing3DSounds.end(); ) {
- playing = *it;
- if (!playing) {
- continue;
- }
- if (playing->m_file == fileToClose) {
- releasePlayingAudio(playing);
- it = m_playing3DSounds.erase(it);
- } else {
- ++it;
- }
- }
- }
- //-------------------------------------------------------------------------------------------------
- void MilesAudioManager::setDeviceListenerPosition( void )
- {
- if (m_listener) {
- AIL_set_3D_orientation(m_listener, m_listenerOrientation.x, m_listenerOrientation.y, m_listenerOrientation.z, 0, 0, -1);
- Real x = m_listenerPosition.x;
- Real y = m_listenerPosition.y;
- Real z = m_listenerPosition.z;
- AIL_set_3D_position( m_listener, x, y, z );
- }
- }
- //-------------------------------------------------------------------------------------------------
- const Coord3D *MilesAudioManager::getCurrentPositionFromEvent( AudioEventRTS *event )
- {
- if (!event->isPositionalAudio()) {
- return NULL;
- }
- return event->getCurrentPosition();
- }
- //-------------------------------------------------------------------------------------------------
- Bool MilesAudioManager::isOnScreen( const Coord3D *pos ) const
- {
- static ICoord2D dummy;
- // WorldToScreen will return True if the point is onscreen and false if it is offscreen.
- return TheTacticalView->worldToScreen(pos, &dummy);
- }
- //-------------------------------------------------------------------------------------------------
- Real MilesAudioManager::getEffectiveVolume(AudioEventRTS *event) const
- {
- Real volume = 1.0f;
- volume *= (event->getVolume() * event->getVolumeShift());
- if (event->getAudioEventInfo()->m_soundType == AT_Music)
- {
- volume *= m_musicVolume;
- }
- else if (event->getAudioEventInfo()->m_soundType == AT_Streaming)
- {
- volume *= m_speechVolume;
- }
- else
- {
- if (event->isPositionalAudio())
- {
- volume *= m_sound3DVolume;
- Coord3D distance = m_listenerPosition;
- const Coord3D *pos = event->getCurrentPosition();
- if (pos)
- {
- distance.sub(pos);
- Real objMinDistance;
- Real objMaxDistance;
- if (event->getAudioEventInfo()->m_type & ST_GLOBAL)
- {
- objMinDistance = TheAudio->getAudioSettings()->m_globalMinRange;
- objMaxDistance = TheAudio->getAudioSettings()->m_globalMaxRange;
- }
- else
- {
- objMinDistance = event->getAudioEventInfo()->m_minDistance;
- objMaxDistance = event->getAudioEventInfo()->m_maxDistance;
- }
- Real objDistance = distance.length();
- if( objDistance > objMinDistance )
- {
- volume *= 1 / (objDistance / objMinDistance);
- }
- if( objDistance >= objMaxDistance )
- {
- volume = 0.0f;
- }
- //else if( objDistance > objMinDistance )
- //{
- // volume *= 1.0f - (objDistance - objMinDistance) / (objMaxDistance - objMinDistance);
- //}
- }
- }
- else
- {
- volume *= m_soundVolume;
- }
- }
- return volume;
- }
- //-------------------------------------------------------------------------------------------------
- Bool MilesAudioManager::startNextLoop( PlayingAudio *looping )
- {
- closeFile(looping->m_file);
- looping->m_file = NULL;
- if (looping->m_requestStop) {
- return false;
- }
- if (looping->m_audioEventRTS->hasMoreLoops()) {
- // generate a new filename, and test to see whether we can play with it now
- looping->m_audioEventRTS->generateFilename();
-
- if (looping->m_audioEventRTS->getDelay() > MSEC_PER_LOGICFRAME_REAL) {
- // fake it out so that this sound appears done, but also so that it will not
- // delete the sound on completion (which would suck)
- looping->m_cleanupAudioEventRTS = false;
- looping->m_requestStop = true;
- looping->m_status = PS_Stopped;
-
-
- AudioRequest *req = allocateAudioRequest(true);
- req->m_pendingEvent = looping->m_audioEventRTS;
- req->m_requiresCheckForSample = true;
- appendAudioRequest(req);
- return true;
- }
- if (looping->m_type == PAT_3DSample) {
- looping->m_file = playSample3D(looping->m_audioEventRTS, looping->m_3DSample);
- } else {
- looping->m_file = playSample(looping->m_audioEventRTS, looping->m_sample);
- }
-
- return looping->m_file != NULL;
- }
- return false;
- }
- //-------------------------------------------------------------------------------------------------
- void MilesAudioManager::playStream( AudioEventRTS *event, HSTREAM stream )
- {
- // Force it to the beginning
- if (event->getAudioEventInfo()->m_soundType == AT_Music) {
- AIL_set_stream_loop_count(stream, INFINITE_LOOP_COUNT);
- }
- AIL_register_stream_callback(stream, setStreamCompleted);
- AIL_start_stream(stream);
- if (event->getAudioEventInfo()->m_soundType == AT_Music) {
- // Need to stop/fade out the old music here.
- }
- }
- //-------------------------------------------------------------------------------------------------
- void *MilesAudioManager::playSample( AudioEventRTS *event, HSAMPLE sample )
- {
- AIL_init_sample(sample);
- // Prep any sort of filtering, etc, here
- AIL_register_EOS_callback(sample, setSampleCompleted);
- initFilters(sample, event);
- // Load the file in
- void *fileBuffer = NULL;
- fileBuffer = loadFileForRead(event);
- if (fileBuffer) {
- AIL_set_sample_file(sample, fileBuffer, 0);
- // Start playback
- AIL_start_sample(sample);
- }
- return fileBuffer;
- }
- //-------------------------------------------------------------------------------------------------
- void *MilesAudioManager::playSample3D( AudioEventRTS *event, H3DSAMPLE sample3D )
- {
- const Coord3D *pos = getCurrentPositionFromEvent(event);
- if (pos) {
- // Load the file in
- void *fileBuffer = loadFileForRead(event);
- if (fileBuffer) {
- AIL_set_3D_sample_file(sample3D, fileBuffer);
- // Prep any sort of filtering, etc, here
- AIL_register_3D_EOS_callback(sample3D, set3DSampleCompleted);
- // Set the position values of the sample here
- if (event->getAudioEventInfo()->m_type & ST_GLOBAL) {
- AIL_set_3D_sample_distances(sample3D, TheAudio->getAudioSettings()->m_globalMinRange, TheAudio->getAudioSettings()->m_globalMaxRange );
- } else {
- AIL_set_3D_sample_distances(sample3D, event->getAudioEventInfo()->m_minDistance, event->getAudioEventInfo()->m_maxDistance );
- }
-
- // Set the position of the sample here
- Real x = pos->x;
- Real y = pos->y;
- Real z = pos->z;
- AIL_set_3D_position( sample3D, x, y, z );
- initFilters3D(sample3D, event, pos);
-
- // Start playback
- AIL_start_3D_sample(sample3D);
- }
- return fileBuffer;
- }
- return NULL;
- }
- //-------------------------------------------------------------------------------------------------
- void MilesAudioManager::buildProviderList( void )
- {
- HPROENUM next = HPROENUM_FIRST;
- char *name;
- UnsignedInt index = 0;
- while (index < MAXPROVIDERS && AIL_enumerate_3D_providers(&next, &m_provider3D[index].id, &name)) {
- m_provider3D[index].name.set(name); // set it to the AsciiString
- ++index;
- }
-
- m_providerCount = index;
- }
- //-------------------------------------------------------------------------------------------------
- void MilesAudioManager::createListener( void )
- {
- if (!(isOn(AudioAffect_Sound3D) && isValidProvider())) {
- return;
- }
- m_listener = AIL_open_3D_listener(m_provider3D[m_selectedProvider].id);
- // initial listener position will be (0, 0, 0)
- }
- //-------------------------------------------------------------------------------------------------
- void MilesAudioManager::initDelayFilter( void )
- {
- if (m_delayFilter != NULL) {
- return;
- }
- char* filterName;
- HPROENUM enumFLTs = HPROENUM_FIRST;
- HPROVIDER currentProvider;
- while (AIL_enumerate_filters(&enumFLTs, ¤tProvider, &filterName )) {
- if (strcmp(filterName,"Mono Delay Filter") == 0) {
- m_delayFilter = currentProvider;
- break;
- }
- }
- }
- //-------------------------------------------------------------------------------------------------
- Bool MilesAudioManager::isValidProvider( void )
- {
- return (m_selectedProvider < m_providerCount);
- }
- //-------------------------------------------------------------------------------------------------
- void MilesAudioManager::initSamplePools( void )
- {
- if (!(isOn(AudioAffect_Sound3D) && isValidProvider())) {
- return;
- }
- int i = 0;
- for (i = 0; i < getAudioSettings()->m_sampleCount2D; ++i) {
- HSAMPLE sample = AIL_allocate_sample_handle(m_digitalHandle);
- DEBUG_ASSERTCRASH(sample, ("Couldn't get %d 2D samples\n", i + 1));
- if (sample) {
- AIL_init_sample(sample);
- AIL_set_sample_user_data(sample, 0, i + 1);
- m_availableSamples.push_back(sample);
- ++m_num2DSamples;
- }
- }
- for (i = 0; i < getAudioSettings()->m_sampleCount3D; ++i) {
- H3DSAMPLE sample = AIL_allocate_3D_sample_handle(m_provider3D[m_selectedProvider].id);
- DEBUG_ASSERTCRASH(sample, ("Couldn't get %d 3D samples\n", i + 1));
- if (sample) {
- AIL_set_3D_user_data(sample, 0, i + 1);
- m_available3DSamples.push_back(sample);
- ++m_num3DSamples;
- }
- }
- // Streams are basically free, so we can just allocate the appropriate number
- m_numStreams = getAudioSettings()->m_streamCount;
- }
- //-------------------------------------------------------------------------------------------------
- void MilesAudioManager::processRequest( AudioRequest *req )
- {
- switch (req->m_request)
- {
- case AR_Play:
- {
- playAudioEvent(req->m_pendingEvent);
- break;
- }
- case AR_Pause:
- {
- pauseAudioEvent(req->m_handleToInteractOn);
- break;
- }
- case AR_Stop:
- {
- stopAudioEvent(req->m_handleToInteractOn);
- break;
- }
- }
- }
- //-------------------------------------------------------------------------------------------------
- void *MilesAudioManager::getHandleForBink( void )
- {
- if (m_binkHandle == NULL) {
- PlayingAudio *aud = allocatePlayingAudio();
- aud->m_audioEventRTS = NEW AudioEventRTS("BinkHandle"); // poolify
- getInfoForAudioEvent(aud->m_audioEventRTS);
- aud->m_sample = getFirst2DSample(aud->m_audioEventRTS);
- aud->m_type = PAT_Sample;
- if (!aud->m_sample) {
- releasePlayingAudio(aud);
- return NULL;
- }
- m_binkHandle = aud;
- }
-
- AILLPDIRECTSOUND lpDS;
- AIL_get_DirectSound_info(m_binkHandle->m_sample, &lpDS, NULL);
- return lpDS;
- }
- //-------------------------------------------------------------------------------------------------
- void MilesAudioManager::releaseHandleForBink( void )
- {
- if (m_binkHandle) {
- releasePlayingAudio(m_binkHandle);
- m_binkHandle = NULL;
- }
- }
- //-------------------------------------------------------------------------------------------------
- void MilesAudioManager::friend_forcePlayAudioEventRTS(const AudioEventRTS* eventToPlay)
- {
- if (!eventToPlay->getAudioEventInfo()) {
- getInfoForAudioEvent(eventToPlay);
- if (!eventToPlay->getAudioEventInfo()) {
- DEBUG_CRASH(("No info for forced audio event '%s'\n", eventToPlay->getEventName().str()));
- return;
- }
- }
- switch (eventToPlay->getAudioEventInfo()->m_soundType)
- {
- case AT_Music:
- if (!isOn(AudioAffect_Music))
- return;
- break;
- case AT_SoundEffect:
- if (!isOn(AudioAffect_Sound) || !isOn(AudioAffect_Sound3D))
- return;
- break;
- case AT_Streaming:
- if (!isOn(AudioAffect_Speech))
- return;
- break;
- }
-
- AudioEventRTS event = *eventToPlay;
- event.generateFilename();
- event.generatePlayInfo();
- std::list<std::pair<AsciiString, Real> >::iterator it;
- for (it = m_adjustedVolumes.begin(); it != m_adjustedVolumes.end(); ++it) {
- if (it->first == event.getEventName()) {
- event.setVolume(it->second);
- break;
- }
- }
- AsciiString fileToPlay = event.getFilename();
- HAUDIO haud = AIL_quick_load_and_play(fileToPlay.str(), 1, 0);
- // Even though the event type is not Speech, this is used only for mission briefings, so use the
- // speech slider to adjust the volume.
- // Get the volume from the event, and pass 0.5 to play the audio in the middle. (0.0 is full left, 1.0 is full right)
- AIL_quick_set_volume(haud, event.getVolume() * getVolume(AudioAffect_Speech), 0.5);
- m_audioForcePlayed.push_back(haud);
- }
- //-------------------------------------------------------------------------------------------------
- //-------------------------------------------------------------------------------------------------
- //-------------------------------------------------------------------------------------------------
- void AILCALLBACK setSampleCompleted( HSAMPLE sampleCompleted )
- {
- TheAudio->notifyOfAudioCompletion((UnsignedInt) sampleCompleted, PAT_Sample);
- }
- //-------------------------------------------------------------------------------------------------
- void AILCALLBACK set3DSampleCompleted( H3DSAMPLE sample3DCompleted )
- {
- TheAudio->notifyOfAudioCompletion((UnsignedInt) sample3DCompleted, PAT_3DSample);
- }
- //-------------------------------------------------------------------------------------------------
- void AILCALLBACK setStreamCompleted( HSTREAM streamCompleted )
- {
- TheAudio->notifyOfAudioCompletion((UnsignedInt) streamCompleted, PAT_Stream);
- }
- //-------------------------------------------------------------------------------------------------
- U32 AILCALLBACK streamingFileOpen(char const *fileName, U32 *file_handle)
- {
- #if defined(_DEBUG) || defined(_INTERNAL)
- if (sizeof(U32) != sizeof(File*)) {
- RELEASE_CRASH(("streamingFileOpen - This function requires work in order to compile on non 32-bit platforms.\n"));
- }
- #endif
- (*file_handle) = (U32) TheFileSystem->openFile(fileName, File::READ | File::STREAMING);
- return ((*file_handle) != 0);
- }
- //-------------------------------------------------------------------------------------------------
- void AILCALLBACK streamingFileClose(U32 fileHandle)
- {
- ((File*) fileHandle)->close();
- }
- //-------------------------------------------------------------------------------------------------
- S32 AILCALLBACK streamingFileSeek(U32 fileHandle, S32 offset, U32 type)
- {
- return ((File*) fileHandle)->seek(offset, (File::seekMode) type);
- }
- //-------------------------------------------------------------------------------------------------
- U32 AILCALLBACK streamingFileRead(U32 file_handle, void *buffer, U32 bytes)
- {
- return ((File*) file_handle)->read(buffer, bytes);
- }
- //-------------------------------------------------------------------------------------------------
- //-------------------------------------------------------------------------------------------------
- //-------------------------------------------------------------------------------------------------
- AudioFileCache::AudioFileCache() : m_maxSize(0), m_currentlyUsedSize(0), m_mutexName("AudioFileCacheMutex")
- {
- m_mutex = CreateMutex(NULL, FALSE, m_mutexName);
- }
- //-------------------------------------------------------------------------------------------------
- AudioFileCache::~AudioFileCache()
- {
- {
- ScopedMutex mut(m_mutex);
- // Free all the samples that are open.
- OpenFilesHashIt it;
- for ( it = m_openFiles.begin(); it != m_openFiles.end(); ++it ) {
- if (it->second.m_openCount > 0) {
- DEBUG_CRASH(("Sample '%s' is still playing, and we're trying to quit.\n", it->second.m_eventInfo->m_audioName.str()));
- }
- releaseOpenAudioFile(&it->second);
- // Don't erase it from the map, cause it makes this whole process way more complicated, and
- // we're about to go away anyways.
- }
- }
- CloseHandle(m_mutex);
- }
- //-------------------------------------------------------------------------------------------------
- void *AudioFileCache::openFile( AudioEventRTS *eventToOpenFrom )
- {
- // Protect the entire openFile function
- ScopedMutex mut(m_mutex);
- AsciiString strToFind;
- switch (eventToOpenFrom->getNextPlayPortion())
- {
- case PP_Attack:
- strToFind = eventToOpenFrom->getAttackFilename();
- break;
- case PP_Sound:
- strToFind = eventToOpenFrom->getFilename();
- break;
- case PP_Decay:
- strToFind = eventToOpenFrom->getDecayFilename();
- break;
- case PP_Done:
- return NULL;
- }
- OpenFilesHash::iterator it;
- it = m_openFiles.find(strToFind);
- if (it != m_openFiles.end()) {
- ++it->second.m_openCount;
- return it->second.m_file;
- }
- // Couldn't find the file, so actually open it.
- File *file = TheFileSystem->openFile(strToFind.str());
- if (!file) {
- DEBUG_ASSERTLOG(strToFind.isEmpty(), ("Missing Audio File: '%s'\n", strToFind.str()));
- return NULL;
- }
- UnsignedInt fileSize = file->size();
- char* buffer = file->readEntireAndClose();
- OpenAudioFile openedAudioFile;
- openedAudioFile.m_eventInfo = eventToOpenFrom->getAudioEventInfo();
- AILSOUNDINFO soundInfo;
- AIL_WAV_info(buffer, &soundInfo);
- if (eventToOpenFrom->isPositionalAudio()) {
- if (soundInfo.channels > 1) {
- DEBUG_CRASH(("Requested Positional Play of audio '%s', but it is in stereo.", strToFind.str()));
- delete [] buffer;
- return NULL;
- }
- }
-
- if (soundInfo.format == WAVE_FORMAT_IMA_ADPCM) {
- void *decompressFileBuffer;
- U32 newFileSize;
- AIL_decompress_ADPCM(&soundInfo, &decompressFileBuffer, &newFileSize);
- fileSize = newFileSize;
- openedAudioFile.m_compressed = TRUE;
- delete [] buffer;
- openedAudioFile.m_file = decompressFileBuffer;
- openedAudioFile.m_soundInfo = soundInfo;
- openedAudioFile.m_openCount = 1;
- } else if (soundInfo.format == WAVE_FORMAT_PCM) {
- openedAudioFile.m_compressed = FALSE;
- openedAudioFile.m_file = buffer;
- openedAudioFile.m_soundInfo = soundInfo;
- openedAudioFile.m_openCount = 1;
- } else {
- DEBUG_CRASH(("Unexpected compression type in '%s'\n", strToFind.str()));
- // prevent leaks
- delete [] buffer;
- return NULL;
- }
- openedAudioFile.m_fileSize = fileSize;
- m_currentlyUsedSize += openedAudioFile.m_fileSize;
- if (m_currentlyUsedSize > m_maxSize) {
- // We need to free some samples, or we're not going to be able to play this sound.
- if (!freeEnoughSpaceForSample(openedAudioFile)) {
- m_currentlyUsedSize -= openedAudioFile.m_fileSize;
- releaseOpenAudioFile(&openedAudioFile);
- return NULL;
- }
- }
- m_openFiles[strToFind] = openedAudioFile;
- return openedAudioFile.m_file;
- }
- //-------------------------------------------------------------------------------------------------
- void AudioFileCache::closeFile( void *fileToClose )
- {
- if (!fileToClose) {
- return;
- }
- // Protect the entire closeFile function
- ScopedMutex mut(m_mutex);
- OpenFilesHash::iterator it;
- for ( it = m_openFiles.begin(); it != m_openFiles.end(); ++it ) {
- if ( it->second.m_file == fileToClose ) {
- --it->second.m_openCount;
- return;
- }
- }
- }
- //-------------------------------------------------------------------------------------------------
- void AudioFileCache::setMaxSize( UnsignedInt size )
- {
- // Protect the function, in case we're trying to use this value elsewhere.
- ScopedMutex mut(m_mutex);
- m_maxSize = size;
- }
- //-------------------------------------------------------------------------------------------------
- void AudioFileCache::releaseOpenAudioFile( OpenAudioFile *fileToRelease )
- {
- if (fileToRelease->m_openCount > 0) {
- // This thing needs to be terminated IMMEDIATELY.
- TheAudio->closeAnySamplesUsingFile(fileToRelease->m_file);
- }
- if (fileToRelease->m_file) {
- if (fileToRelease->m_compressed) {
- // Files read in via AIL_decompress_ADPCM must be freed with AIL_mem_free_lock.
- AIL_mem_free_lock(fileToRelease->m_file);
- } else {
- // Otherwise, we read it, we own it, blow it away.
- delete [] fileToRelease->m_file;
- }
- fileToRelease->m_file = NULL;
- fileToRelease->m_eventInfo = NULL;
- }
- }
- //-------------------------------------------------------------------------------------------------
- Bool AudioFileCache::freeEnoughSpaceForSample(const OpenAudioFile& sampleThatNeedsSpace)
- {
-
- Int spaceRequired = m_currentlyUsedSize - m_maxSize;
- Int runningTotal = 0;
- std::list<AsciiString> filesToClose;
- // First, search for any samples that have ref counts of 0. They are low-hanging fruit, and
- // should be considered immediately.
- OpenFilesHashIt it;
- for (it = m_openFiles.begin(); it != m_openFiles.end(); ++it) {
- if (it->second.m_openCount == 0) {
- // This is said low-hanging fruit.
- filesToClose.push_back(it->first);
- runningTotal += it->second.m_fileSize;
- if (runningTotal >= spaceRequired) {
- break;
- }
- }
- }
- // If we don't have enough space yet, then search through the events who have a count of 1 or more
- // and who are lower priority than this sound.
- // Mical said that at this point, sounds shouldn't care if other sounds are interruptable or not.
- // Kill any files of lower priority necessary to clear our the buffer.
- if (runningTotal < spaceRequired) {
- for (it = m_openFiles.begin(); it != m_openFiles.end(); ++it) {
- if (it->second.m_openCount > 0) {
- if (it->second.m_eventInfo->m_priority < sampleThatNeedsSpace.m_eventInfo->m_priority) {
- filesToClose.push_back(it->first);
- runningTotal += it->second.m_fileSize;
-
- if (runningTotal >= spaceRequired) {
- break;
- }
- }
- }
- }
- }
- // We weren't able to find enough sounds to truncate. Therefore, this sound is not going to play.
- if (runningTotal < spaceRequired) {
- return FALSE;
- }
- std::list<AsciiString>::iterator ait;
- for (ait = filesToClose.begin(); ait != filesToClose.end(); ++ait) {
- OpenFilesHashIt itToErase = m_openFiles.find(*ait);
- if (itToErase != m_openFiles.end()) {
- releaseOpenAudioFile(&itToErase->second);
- m_currentlyUsedSize -= itToErase->second.m_fileSize;
- m_openFiles.erase(itToErase);
- }
- }
- return TRUE;
- }
- #if defined(_DEBUG) || defined(_INTERNAL)
- //-------------------------------------------------------------------------------------------------
- void MilesAudioManager::dumpAllAssetsUsed()
- {
- if (!TheGlobalData->m_preloadReport) {
- return;
- }
- // Dump all the audio assets we've used.
- FILE *logfile=fopen("PreloadedAssets.txt","a+"); //append to log
- if (!logfile)
- return;
- std::list<AsciiString> missingEvents;
- std::list<AsciiString> usedFiles;
- std::list<AsciiString>::iterator lit;
- fprintf(logfile, "\nAudio Asset Report - BEGIN\n");
- {
- SetAsciiStringIt it;
- std::vector<AsciiString>::iterator asIt;
- for (it = m_allEventsLoaded.begin(); it != m_allEventsLoaded.end(); ++it) {
- AsciiString astr = *it;
- AudioEventInfo *aei = findAudioEventInfo(astr);
- if (!aei) {
- missingEvents.push_back(astr);
- continue;
- }
- for (asIt = aei->m_attackSounds.begin(); asIt != aei->m_attackSounds.end(); ++asIt) {
- usedFiles.push_back(*asIt);
- }
- for (asIt = aei->m_sounds.begin(); asIt != aei->m_sounds.end(); ++asIt) {
- usedFiles.push_back(*asIt);
- }
- for (asIt = aei->m_decaySounds.begin(); asIt != aei->m_decaySounds.end(); ++asIt) {
- usedFiles.push_back(*asIt);
- }
- if (!aei->m_filename.isEmpty()) {
- usedFiles.push_back(aei->m_filename);
- }
- }
- fprintf(logfile, "\nEvents Requested that are missing information - BEGIN\n");
- for (lit = missingEvents.begin(); lit != missingEvents.end(); ++lit) {
- fprintf(logfile, "%s\n", (*lit).str());
- }
- fprintf(logfile, "\nEvents Requested that are missing information - END\n");
- fprintf(logfile, "\nFiles Used - BEGIN\n");
- for (lit = usedFiles.begin(); lit != usedFiles.end(); ++lit) {
- fprintf(logfile, "%s\n", (*lit).str());
- }
- fprintf(logfile, "\nFiles Used - END\n");
- }
- fprintf(logfile, "\nAudio Asset Report - END\n");
- fclose(logfile);
- logfile = NULL;
- }
- #endif
|