llaudioengine_fmod.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856
  1. /**
  2. * @file llaudioengine_fmod.cpp
  3. * @brief Implementation of LLAudioEngine class abstracting the audio support
  4. * as a FMOD Studio implementation
  5. *
  6. * $LicenseInfo:firstyear=2002&license=viewergpl$
  7. *
  8. * Copyright (c) 2002-2014, Linden Research, Inc.
  9. *
  10. * Second Life Viewer Source Code
  11. * The source code in this file ("Source Code") is provided by Linden Lab
  12. * to you under the terms of the GNU General Public License, version 2.0
  13. * ("GPL"), unless you have obtained a separate licensing agreement
  14. * ("Other License"), formally executed by you and Linden Lab. Terms of
  15. * the GPL can be found in doc/GPL-license.txt in this distribution, or
  16. * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  17. *
  18. * There are special exceptions to the terms and conditions of the GPL as
  19. * it is applied to this Source Code. View the full text of the exception
  20. * in the file doc/FLOSS-exception.txt in this software distribution, or
  21. * online at
  22. * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  23. *
  24. * By copying, modifying or distributing this software, you acknowledge
  25. * that you have read and understood your obligations described above,
  26. * and agree to abide by those obligations.
  27. *
  28. * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  29. * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  30. * COMPLETENESS OR PERFORMANCE.
  31. * $/LicenseInfo$
  32. */
  33. #include "linden_common.h"
  34. #include "lldir.h"
  35. #include "llmath.h"
  36. #include "llrand.h"
  37. #include "llversionviewer.h" // For LL_CHANNEL
  38. #include "fmod.hpp"
  39. #include "fmod_errors.h"
  40. #include "llstreamingaudio.h"
  41. #include "llstreamingaudio_fmod.h"
  42. #include "llaudioengine_fmod.h"
  43. #include "lllistener_fmod.h"
  44. // Set to 1 to override FMOD memory management with ours
  45. #define LL_MANAGE_FMOD_MEMORY 0
  46. // static variables
  47. #if LL_LINUX
  48. bool LLAudioEngine_FMOD::sNoALSA = false;
  49. bool LLAudioEngine_FMOD::sNoPulseAudio = false;
  50. #endif
  51. FMOD::ChannelGroup* LLAudioEngine_FMOD::sChannelGroups[LLAudioEngine::AUDIO_TYPE_COUNT] = { NULL };
  52. // Helper functions and callbacks
  53. bool checkFMerr(S32 result, const char* str)
  54. {
  55. if (result == (S32)FMOD_OK)
  56. {
  57. return false;
  58. }
  59. LL_DEBUGS("FMOD") << str << " Error: "
  60. << FMOD_ErrorString((FMOD_RESULT)result) << LL_ENDL;
  61. return true;
  62. }
  63. #if LL_MANAGE_FMOD_MEMORY
  64. static void* F_CALL decode_alloc(unsigned int size, FMOD_MEMORY_TYPE type,
  65. const char* sourcestr)
  66. {
  67. if (type & FMOD_MEMORY_STREAM_DECODE)
  68. {
  69. llinfos << "Decode buffer size: " << size << llendl;
  70. }
  71. else if (type & FMOD_MEMORY_STREAM_FILE)
  72. {
  73. llinfos << "Stream buffer size: " << size << llendl;
  74. }
  75. return ll_aligned_malloc_16(size);
  76. }
  77. static void* F_CALL decode_realloc(void* ptr, unsigned int size,
  78. FMOD_MEMORY_TYPE type,
  79. const char* sourcestr)
  80. {
  81. return ll_aligned_realloc_16(ptr, size, 0);
  82. }
  83. static void F_CALL decode_dealloc(void* ptr, FMOD_MEMORY_TYPE type,
  84. const char* sourcestr)
  85. {
  86. ll_aligned_free_16(ptr);
  87. }
  88. #endif
  89. // *NOTE: this is almost certainly being called on the mixer thread, not the
  90. // main thread. May have implications for callees or audio engine shutdown.
  91. FMOD_RESULT F_CALL windCallback(FMOD_DSP_STATE* dsp_state,
  92. float* originalbuffer, float* newbuffer,
  93. unsigned int length, int inchannels,
  94. int* outchannels)
  95. {
  96. // originalbuffer = fmod's original mixbuffer.
  97. // newbuffer = the buffer passed from the previous DSP unit.
  98. // length = length in samples at this mix time.
  99. if (!dsp_state) // Paranoia ?... Better safe than sorry ! HB
  100. {
  101. return FMOD_ERR_DSP_NOTFOUND; // Seems appropriate to me... HB
  102. }
  103. FMOD::DSP* thisdsp = (FMOD::DSP*)dsp_state->instance;
  104. if (!thisdsp)
  105. {
  106. return FMOD_ERR_DSP_NOTFOUND; // Seems appropriate to me... HB
  107. }
  108. LLWindGen<LLAudioEngine_FMOD::MIXBUFFERFORMAT>* windgen;
  109. thisdsp->getUserData((void**)&windgen);
  110. if (windgen)
  111. {
  112. windgen->windGenerate((LLAudioEngine_FMOD::MIXBUFFERFORMAT*)newbuffer,
  113. length);
  114. }
  115. return FMOD_OK;
  116. }
  117. //
  118. // LLAudioEngine_FMOD implementation
  119. //
  120. LLAudioEngine_FMOD::LLAudioEngine_FMOD(bool enable_profiler)
  121. : mInited(false),
  122. mWindGen(NULL),
  123. mWindDSP(NULL),
  124. mSystem(NULL),
  125. mEnableProfiler(enable_profiler)
  126. {
  127. mWindDSPDesc = new FMOD_DSP_DESCRIPTION();
  128. }
  129. LLAudioEngine_FMOD::~LLAudioEngine_FMOD()
  130. {
  131. delete mWindDSPDesc;
  132. mWindDSPDesc = NULL;
  133. }
  134. bool LLAudioEngine_FMOD::init(void* userdata)
  135. {
  136. LL_DEBUGS("AppInit") << "Initializing FMOD" << LL_ENDL;
  137. mAudioDevice.clear();
  138. #if LL_MANAGE_FMOD_MEMORY
  139. FMOD_RESULT result = FMOD::Memory_Initialize(NULL, 0, &decode_alloc,
  140. &decode_realloc,
  141. &decode_dealloc,
  142. FMOD_MEMORY_ALL);
  143. checkFMerr(result, "FMOD::Memory_Initialize");
  144. #else
  145. FMOD_RESULT result;
  146. #endif
  147. result = FMOD::System_Create(&mSystem);
  148. if (checkFMerr(result, "FMOD::System_Create"))
  149. {
  150. return false;
  151. }
  152. // Will call LLAudioEngine_FMOD::allocateListener, which needs a valid
  153. // mSystem pointer.
  154. LLAudioEngine::init(userdata);
  155. unsigned int version;
  156. result = mSystem->getVersion(&version);
  157. checkFMerr(result, "FMOD::System::getVersion");
  158. if (version < FMOD_VERSION)
  159. {
  160. llwarns << "You are using the wrong FMOD Studio version (" << version
  161. << ") ! You should be using FMOD Studio " << FMOD_VERSION
  162. << llendl;
  163. }
  164. // In this case, all sounds, PLUS wind and stream will be software.
  165. result = mSystem->setSoftwareChannels(MAX_AUDIO_CHANNELS + 2);
  166. checkFMerr(result, "FMOD::System::setSoftwareChannels");
  167. FMOD_ADVANCEDSETTINGS adv_settings;
  168. memset(&adv_settings, 0, sizeof(FMOD_ADVANCEDSETTINGS));
  169. adv_settings.cbSize = sizeof(FMOD_ADVANCEDSETTINGS);
  170. adv_settings.resamplerMethod = FMOD_DSP_RESAMPLER_LINEAR;
  171. result = mSystem->setAdvancedSettings(&adv_settings);
  172. checkFMerr(result, "FMOD::System::setAdvancedSettings");
  173. U32 fmod_flags = FMOD_INIT_NORMAL | FMOD_INIT_THREAD_UNSAFE |
  174. FMOD_INIT_3D_RIGHTHANDED;
  175. if (mEnableProfiler)
  176. {
  177. fmod_flags |= FMOD_INIT_PROFILE_ENABLE;
  178. mSystem->createChannelGroup("None", &sChannelGroups[AUDIO_TYPE_NONE]);
  179. mSystem->createChannelGroup("SFX", &sChannelGroups[AUDIO_TYPE_SFX]);
  180. mSystem->createChannelGroup("UI", &sChannelGroups[AUDIO_TYPE_UI]);
  181. mSystem->createChannelGroup("Ambient",
  182. &sChannelGroups[AUDIO_TYPE_AMBIENT]);
  183. }
  184. #if LL_LINUX
  185. bool audio_ok = false;
  186. if (sNoPulseAudio)
  187. {
  188. LL_DEBUGS("AppInit") << "PulseAudio audio output SKIPPED" << LL_ENDL;
  189. }
  190. else
  191. {
  192. LL_DEBUGS("AppInit") << "Trying PulseAudio audio output..." << LL_ENDL;
  193. if (mSystem->setOutput(FMOD_OUTPUTTYPE_PULSEAUDIO) == FMOD_OK &&
  194. (result = mSystem->init(MAX_AUDIO_CHANNELS + 2, fmod_flags,
  195. (void*)LL_CHANNEL)) == FMOD_OK)
  196. {
  197. mAudioDevice = "PulseAudio";
  198. audio_ok = true;
  199. }
  200. else
  201. {
  202. checkFMerr(result, "PulseAudio audio output FAILED to initialize");
  203. }
  204. }
  205. if (audio_ok || sNoALSA)
  206. {
  207. LL_DEBUGS("AppInit") << "ALSA audio output SKIPPED" << LL_ENDL;
  208. }
  209. else
  210. {
  211. LL_DEBUGS("AppInit") << "Trying ALSA audio output..." << LL_ENDL;
  212. if (mSystem->setOutput(FMOD_OUTPUTTYPE_ALSA) == FMOD_OK &&
  213. (result = mSystem->init(MAX_AUDIO_CHANNELS + 2, fmod_flags, 0)) == FMOD_OK)
  214. {
  215. mAudioDevice = "ALSA";
  216. audio_ok = true;
  217. }
  218. else
  219. {
  220. checkFMerr(result, "ALSA audio output FAILED to initialize");
  221. }
  222. }
  223. if (!audio_ok)
  224. {
  225. llwarns << "Overall audio init failure." << llendl;
  226. return false;
  227. }
  228. llinfos << mAudioDevice << " output initialized" << llendl;
  229. // We are interested in logging which output method we ended up with, for
  230. // QA purposes.
  231. FMOD_OUTPUTTYPE output_type;
  232. mSystem->getOutput(&output_type);
  233. switch (output_type)
  234. {
  235. case FMOD_OUTPUTTYPE_NOSOUND:
  236. LL_DEBUGS("AppInit") << "Audio output: NoSound" << LL_ENDL;
  237. break;
  238. case FMOD_OUTPUTTYPE_PULSEAUDIO:
  239. LL_DEBUGS("AppInit") << "Audio output: PulseAudio" << LL_ENDL;
  240. break;
  241. case FMOD_OUTPUTTYPE_ALSA:
  242. LL_DEBUGS("AppInit") << "Audio output: ALSA" << LL_ENDL;
  243. break;
  244. default:
  245. llinfos << "Audio output: Unknown !" << llendl;
  246. }
  247. #else // LL_LINUX
  248. // Initialize the FMOD engine
  249. result = mSystem->init(MAX_AUDIO_CHANNELS + 2, fmod_flags, 0);
  250. if (result == FMOD_ERR_OUTPUT_CREATEBUFFER)
  251. {
  252. // Ok, the format selected is not supported by this soundcard. Switch
  253. // it back to stereo...
  254. result = mSystem->setSoftwareFormat(44100, FMOD_SPEAKERMODE_STEREO, 0);
  255. checkFMerr(result, "Error falling back to stereo mode");
  256. // ... and re-init.
  257. result = mSystem->init(MAX_AUDIO_CHANNELS + 2, fmod_flags, 0);
  258. }
  259. if (checkFMerr(result, "Error initializing FMOD Studio"))
  260. {
  261. return false;
  262. }
  263. #endif
  264. // Set up our favourite FMOD-native streaming audio implementation if none
  265. // has already been added
  266. if (!getStreamingAudioImpl()) // no existing implementation added
  267. {
  268. setStreamingAudioImpl(new LLStreamingAudio_FMOD(mSystem));
  269. }
  270. LL_DEBUGS("AppInit") << "FMOD Studio initialized correctly" << LL_ENDL;
  271. FMOD_ADVANCEDSETTINGS adv_settings_dump = {};
  272. mSystem->getAdvancedSettings(&adv_settings_dump);
  273. LL_DEBUGS("AppInit") << "FMOD Studio resampler: "
  274. << adv_settings.resamplerMethod << " bytes"
  275. << LL_ENDL;
  276. int r_numbuffers;
  277. unsigned int r_bufferlength;
  278. mSystem->getDSPBufferSize(&r_bufferlength, &r_numbuffers);
  279. int r_samplerate, r_channels;
  280. char r_name[512];
  281. mSystem->getDriverInfo(0, r_name, 511, NULL, &r_samplerate, NULL, &r_channels);
  282. r_name[511] = '\0';
  283. // Optimistic default; I suspect if sample rate is 0, everything breaks:
  284. int latency = 100;
  285. if (r_samplerate != 0)
  286. {
  287. latency = (int)(1000.f * r_bufferlength * r_numbuffers / r_samplerate);
  288. }
  289. llinfos << "FMOD device: " << r_name << " with parameters: "
  290. << r_samplerate << " Hz, " << r_channels << " channels - Buffers: "
  291. << r_numbuffers << " * " << r_bufferlength << " bytes - Latency: "
  292. << latency << "ms." << llendl;
  293. mInited = true;
  294. return true;
  295. }
  296. std::string LLAudioEngine_FMOD::getDriverName(bool verbose)
  297. {
  298. if (!mSystem)
  299. {
  300. llwarns << "FMOD not properly initialized !" << llendl;
  301. return "FMODEx_NOT_INITIALIZED";
  302. }
  303. if (!verbose)
  304. {
  305. return "FMODStudio";
  306. }
  307. std::string result = "FMOD Studio";
  308. unsigned int version;
  309. if (!checkFMerr(mSystem->getVersion(&version), "FMOD::System::getVersion"))
  310. {
  311. result += llformat(" v%1x.%02x.%02x", version >> 16,
  312. version >> 8 & 0x000000FF, version & 0x000000FF);
  313. }
  314. if (!mAudioDevice.empty())
  315. {
  316. result += " (" + mAudioDevice + ")";
  317. }
  318. return result;
  319. }
  320. void LLAudioEngine_FMOD::allocateListener()
  321. {
  322. mListenerp = (LLListener*)new(std::nothrow) LLListener_FMOD(mSystem);
  323. if (!mListenerp)
  324. {
  325. llwarns << "Listener creation failed" << llendl;
  326. }
  327. }
  328. void LLAudioEngine_FMOD::shutdown()
  329. {
  330. if (mWindDSP)
  331. {
  332. cleanupWind();
  333. }
  334. stopInternetStream();
  335. llinfos << "Shutting down the audio engine..." << llendl;
  336. LLAudioEngine::shutdown();
  337. if (mSystem)
  338. {
  339. llinfos << "Closing FMOD Studio" << llendl;
  340. mSystem->close();
  341. mSystem->release();
  342. }
  343. llinfos << "Done closing FMOD Studio" << llendl;
  344. delete mListenerp;
  345. mListenerp = NULL;
  346. }
  347. LLAudioBuffer* LLAudioEngine_FMOD::createBuffer()
  348. {
  349. return new LLAudioBufferFMOD(mSystem);
  350. }
  351. LLAudioChannel* LLAudioEngine_FMOD::createChannel()
  352. {
  353. return new LLAudioChannelFMOD(mSystem);
  354. }
  355. bool LLAudioEngine_FMOD::initWind()
  356. {
  357. mNextWindUpdate = 0.f;
  358. if (!mWindDSP)
  359. {
  360. if (!mWindDSPDesc)
  361. {
  362. llwarns << "mWindDSPDesc is NULL !" << llendl;
  363. return false;
  364. }
  365. if (mWindGen)
  366. {
  367. LL_DEBUGS("FMOD") << "mWindGen was non-NULL. Deleting." << LL_ENDL;
  368. delete mWindGen;
  369. }
  370. // Set everything to zero:
  371. memset(mWindDSPDesc, 0, sizeof(*mWindDSPDesc));
  372. mWindDSPDesc->pluginsdkversion = FMOD_PLUGIN_SDK_VERSION;
  373. // Set name to "Wind Unit"
  374. strncpy(mWindDSPDesc->name, "Wind Unit", sizeof(mWindDSPDesc->name));
  375. mWindDSPDesc->numoutputbuffers = 1;
  376. // Assign the callback, which may be called from arbitrary threads
  377. mWindDSPDesc->read = &windCallback;
  378. bool error = checkFMerr(mSystem->createDSP(mWindDSPDesc, &mWindDSP),
  379. "FMOD::createDSP");
  380. if (error || !mWindDSP)
  381. {
  382. llwarns << "Failed to create the wind DSP" << llendl;
  383. return false;
  384. }
  385. int frequency = 44100;
  386. FMOD_SPEAKERMODE mode;
  387. if (!checkFMerr(mSystem->getSoftwareFormat(&frequency, &mode, NULL),
  388. "FMOD::System::getSoftwareFormat"))
  389. {
  390. mWindGen = new LLWindGen<MIXBUFFERFORMAT>((U32)frequency);
  391. if (!checkFMerr(mWindDSP->setUserData((void*)mWindGen),
  392. "FMOD::DSP::setUserData") &&
  393. !checkFMerr(mWindDSP->setChannelFormat(FMOD_CHANNELMASK_STEREO,
  394. 2, mode),
  395. "FMOD::DSP::setChannelFormat") &&
  396. !checkFMerr(mSystem->playDSP(mWindDSP, NULL, false, NULL),
  397. "FMOD::System::playDSP"))
  398. {
  399. return true;
  400. }
  401. llwarns << "Failed to initialize the wind DSP" << llendl;
  402. cleanupWind();
  403. }
  404. }
  405. return false;
  406. }
  407. void LLAudioEngine_FMOD::cleanupWind()
  408. {
  409. if (mWindDSP)
  410. {
  411. FMOD::ChannelGroup* group = NULL;
  412. bool error = checkFMerr(mSystem->getMasterChannelGroup(&group),
  413. "FMOD::System::getMasterChannelGroup");
  414. if (!error && group)
  415. {
  416. group->removeDSP(mWindDSP);
  417. }
  418. mWindDSP->release();
  419. mWindDSP = NULL;
  420. }
  421. if (mWindGen)
  422. {
  423. delete mWindGen;
  424. mWindGen = NULL;
  425. }
  426. }
  427. void LLAudioEngine_FMOD::updateWind(LLVector3 wind_vec,
  428. F32 camera_height_above_water)
  429. {
  430. if (mEnableWind && mWindGen &&
  431. mWindUpdateTimer.checkExpirationAndReset(LL_WIND_UPDATE_INTERVAL))
  432. {
  433. // Wind comes in as Linden coordinate (+X = forward, +Y = left, +Z =
  434. // up), so we need to convert this to the conventional orientation DS3D
  435. // and OpenAL use where +X = right, +Y = up, +Z = backwards
  436. wind_vec.set(-wind_vec.mV[1], wind_vec.mV[2], -wind_vec.mV[0]);
  437. mWindGen->mTargetFreq =
  438. 80.f * powf(1.f + mapWindVecToPitch(wind_vec),
  439. 2.5f * (mapWindVecToGain(wind_vec) + 1.f));
  440. mWindGen->mTargetGain = mapWindVecToGain(wind_vec) * mMaxWindGain;
  441. mWindGen->mTargetPanGainR = mapWindVecToPan(wind_vec);
  442. }
  443. }
  444. void LLAudioEngine_FMOD::setInternalGain(F32 gain)
  445. {
  446. if (!mInited || !mSystem)
  447. {
  448. return;
  449. }
  450. gain = llclamp(gain, 0.f, 1.f);
  451. FMOD::ChannelGroup* master_group;
  452. mSystem->getMasterChannelGroup(&master_group);
  453. if (!master_group)
  454. {
  455. LL_DEBUGS("FMOD") << "Could not get master group." << LL_ENDL;
  456. return;
  457. }
  458. master_group->setVolume(gain);
  459. LLStreamingAudioInterface* saimpl = getStreamingAudioImpl();
  460. if (saimpl)
  461. {
  462. // FMOD Studio likes its streaming audio channel gain re-asserted after
  463. // master volume change.
  464. saimpl->setGain(saimpl->getGain());
  465. }
  466. }
  467. //
  468. // LLAudioChannelFMOD implementation
  469. //
  470. LLAudioChannelFMOD::LLAudioChannelFMOD(FMOD::System* system)
  471. : LLAudioChannel(),
  472. mSystemp(system),
  473. mChannelp(NULL),
  474. mLastSamplePos(0)
  475. {
  476. }
  477. LLAudioChannelFMOD::~LLAudioChannelFMOD()
  478. {
  479. cleanup();
  480. }
  481. bool LLAudioChannelFMOD::updateBuffer()
  482. {
  483. FMOD_RESULT result;
  484. if (LLAudioChannel::updateBuffer())
  485. {
  486. // Base class update returned true, which means that we need to
  487. // actually set up the channel for a different buffer.
  488. LLAudioBufferFMOD* bufferp =
  489. (LLAudioBufferFMOD*)mCurrentSourcep->getCurrentBuffer();
  490. if (!bufferp)
  491. {
  492. llwarns << "No current buffer !" << llendl;
  493. mCurrentBufferp = NULL;
  494. return false;
  495. }
  496. // Grab the FMOD sound associated with the buffer
  497. FMOD::Sound* soundp = bufferp->getSound();
  498. if (!soundp)
  499. {
  500. // This is bad, there should ALWAYS be a sound associated with a
  501. // legit buffer.
  502. llwarns << "No FMOD sound" << llendl;
  503. #if 1
  504. mCurrentBufferp = NULL;
  505. #endif
  506. return false;
  507. }
  508. // Actually play the sound. Start it off paused so we can do all the
  509. // necessary setup.
  510. if (!mChannelp)
  511. {
  512. result = getSystem()->playSound(soundp, NULL, true, &mChannelp);
  513. checkFMerr(result, "FMOD::System::playSound");
  514. if (!mChannelp)
  515. {
  516. LL_DEBUGS("FMOD") << "Could not allocate a new channel"
  517. << LL_ENDL;
  518. mCurrentBufferp = NULL;
  519. return false;
  520. }
  521. }
  522. }
  523. // If we have a source for the channel, we need to update its gain.
  524. if (mCurrentSourcep)
  525. {
  526. result = mChannelp->setVolume(getSecondaryGain() *
  527. mCurrentSourcep->getGain());
  528. if (result != FMOD_OK)
  529. {
  530. LL_DEBUGS("FMOD") << checkFMerr(result, "FMOD::Channel::setVolume")
  531. << LL_ENDL;
  532. }
  533. mChannelp->setMode(mCurrentSourcep->isLoop() ? FMOD_LOOP_NORMAL
  534. : FMOD_LOOP_OFF);
  535. }
  536. return true;
  537. }
  538. void LLAudioChannelFMOD::update3DPosition()
  539. {
  540. if (!mChannelp)
  541. {
  542. // We are not actually a live channel, i.e. we are not playing anything
  543. return;
  544. }
  545. LLAudioBufferFMOD* bufferp =
  546. (LLAudioBufferFMOD*)mCurrentBufferp;
  547. if (!bufferp)
  548. {
  549. // We do not have a buffer associated with us (should really have been
  550. // picked up by the above test).
  551. return;
  552. }
  553. if (mCurrentSourcep->isAmbient())
  554. {
  555. // Ambient sound, so we do not need to do any positional updates.
  556. set3DMode(false);
  557. }
  558. else
  559. {
  560. // Localized sound. Update the position and velocity of the sound.
  561. set3DMode(true);
  562. LLVector3 float_pos(mCurrentSourcep->getPositionGlobal());
  563. FMOD_RESULT result =
  564. mChannelp->set3DAttributes((FMOD_VECTOR*)float_pos.mV,
  565. (FMOD_VECTOR*)mCurrentSourcep->getVelocity().mV);
  566. checkFMerr(result, "FMOD::Channel::set3DAttributes");
  567. }
  568. }
  569. void LLAudioChannelFMOD::updateLoop()
  570. {
  571. if (!mChannelp)
  572. {
  573. // May want to clear up the loop/sample counters.
  574. return;
  575. }
  576. //
  577. //* HACK: we keep track of whether we looped or not by seeing when the
  578. // sample position looks like it's going backwards. Not reliable; may
  579. // yield false negatives.
  580. //
  581. unsigned int cur_pos;
  582. mChannelp->getPosition(&cur_pos, FMOD_TIMEUNIT_PCMBYTES);
  583. if ((U32)cur_pos < mLastSamplePos)
  584. {
  585. mLoopedThisFrame = true;
  586. }
  587. mLastSamplePos = cur_pos;
  588. }
  589. void LLAudioChannelFMOD::cleanup()
  590. {
  591. if (mChannelp)
  592. {
  593. LL_DEBUGS("FMOD") << "Cleaning-up channel " << std::hex << mChannelp
  594. << std::dec << LL_ENDL;
  595. checkFMerr(mChannelp->stop(), "FMOD::Channel::stop");
  596. mCurrentBufferp = NULL;
  597. mChannelp = NULL;
  598. }
  599. }
  600. void LLAudioChannelFMOD::play()
  601. {
  602. if (!mChannelp)
  603. {
  604. llwarns << "Playing without a channelID, aborting" << llendl;
  605. return;
  606. }
  607. checkFMerr(mChannelp->setPaused(false), "FMOD::Channel::pause");
  608. getSource()->setPlayedOnce(true);
  609. FMOD::ChannelGroup* group =
  610. LLAudioEngine_FMOD::sChannelGroups[getSource()->getType()];
  611. if (group)
  612. {
  613. mChannelp->setChannelGroup(group);
  614. }
  615. }
  616. void LLAudioChannelFMOD::playSynced(LLAudioChannel* channelp)
  617. {
  618. LLAudioChannelFMOD* fmod_channelp =
  619. (LLAudioChannelFMOD*)channelp;
  620. if (!(fmod_channelp->mChannelp && mChannelp))
  621. {
  622. // No channel allocated to both the master and the slave
  623. return;
  624. }
  625. unsigned int cur_pos;
  626. if (checkFMerr(mChannelp->getPosition(&cur_pos, FMOD_TIMEUNIT_PCMBYTES),
  627. "Unable to retrieve current position"))
  628. {
  629. return;
  630. }
  631. cur_pos %= mCurrentBufferp->getLength();
  632. // Try to match the position of our sync master
  633. checkFMerr(mChannelp->setPosition(cur_pos, FMOD_TIMEUNIT_PCMBYTES),
  634. "Unable to set current position");
  635. // Start us playing
  636. play();
  637. }
  638. bool LLAudioChannelFMOD::isPlaying()
  639. {
  640. if (!mChannelp)
  641. {
  642. return false;
  643. }
  644. bool paused, playing;
  645. mChannelp->getPaused(&paused);
  646. mChannelp->isPlaying(&playing);
  647. return !paused && playing;
  648. }
  649. void LLAudioChannelFMOD::set3DMode(bool use3d)
  650. {
  651. FMOD_MODE current_mode;
  652. if (mChannelp->getMode(&current_mode) != FMOD_OK)
  653. {
  654. return;
  655. }
  656. FMOD_MODE new_mode = current_mode;
  657. new_mode &= ~(use3d ? FMOD_2D : FMOD_3D);
  658. new_mode |= use3d ? FMOD_3D : FMOD_2D;
  659. if (current_mode != new_mode)
  660. {
  661. mChannelp->setMode(new_mode);
  662. }
  663. }
  664. //
  665. // LLAudioBufferFMOD implementation
  666. //
  667. LLAudioBufferFMOD::LLAudioBufferFMOD(FMOD::System* system)
  668. : mSystemp(system),
  669. mSoundp(NULL)
  670. {
  671. }
  672. LLAudioBufferFMOD::~LLAudioBufferFMOD()
  673. {
  674. if (mSoundp)
  675. {
  676. mSoundp->release();
  677. mSoundp = NULL;
  678. }
  679. }
  680. bool LLAudioBufferFMOD::loadWAV(const std::string& filename)
  681. {
  682. // Try to open a wav file from disk. This will eventually go away, as we
  683. // do not really want to block doing this.
  684. if (filename.empty())
  685. {
  686. // Invalid filename, abort.
  687. return false;
  688. }
  689. if (!LLFile::isfile(filename))
  690. {
  691. // File not found, abort.
  692. return false;
  693. }
  694. if (mSoundp)
  695. {
  696. // If there is already something loaded in this buffer, clean it up.
  697. mSoundp->release();
  698. mSoundp = NULL;
  699. }
  700. FMOD_MODE base_mode = FMOD_LOOP_NORMAL;
  701. FMOD_CREATESOUNDEXINFO exinfo;
  702. memset(&exinfo, 0, sizeof(FMOD_CREATESOUNDEXINFO));
  703. exinfo.cbsize = sizeof(FMOD_CREATESOUNDEXINFO);
  704. // Hint to speed up loading:
  705. exinfo.suggestedsoundtype = FMOD_SOUND_TYPE_WAV;
  706. // Load up the wav file into an fmod sample
  707. FMOD_RESULT result =
  708. getSystem()->createSound(filename.c_str(), base_mode, &exinfo,
  709. &mSoundp);
  710. if (result != FMOD_OK)
  711. {
  712. // We failed to load the file for some reason.
  713. llwarns << "Could not load data '" << filename << "': "
  714. << FMOD_ErrorString(result) << llendl;
  715. // If we EVER want to load wav files provided by end users, we need
  716. // to rethink this!
  717. //
  718. // File is probably corrupt: remove it.
  719. LLFile::remove(filename);
  720. return false;
  721. }
  722. // Everything went well, return true
  723. return true;
  724. }
  725. U32 LLAudioBufferFMOD::getLength()
  726. {
  727. unsigned int length = 0;
  728. if (mSoundp)
  729. {
  730. mSoundp->getLength(&length, FMOD_TIMEUNIT_PCMBYTES);
  731. }
  732. return length;
  733. }