PageRenderTime 44ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 0ms

/indra/llaudio/llaudioengine_openal.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 544 lines | 402 code | 91 blank | 51 comment | 51 complexity | 8053992ea8607557c1527cb64faeeff7 MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file audioengine_openal.cpp
  3. * @brief implementation of audio engine using OpenAL
  4. * support as a OpenAL 3D implementation
  5. *
  6. * $LicenseInfo:firstyear=2002&license=viewerlgpl$
  7. * Second Life Viewer Source Code
  8. * Copyright (C) 2010, Linden Research, Inc.
  9. *
  10. * This library is free software; you can redistribute it and/or
  11. * modify it under the terms of the GNU Lesser General Public
  12. * License as published by the Free Software Foundation;
  13. * version 2.1 of the License only.
  14. *
  15. * This library is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  18. * Lesser General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU Lesser General Public
  21. * License along with this library; if not, write to the Free Software
  22. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  23. *
  24. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  25. * $/LicenseInfo$
  26. */
  27. #include "linden_common.h"
  28. #include "lldir.h"
  29. #include "llaudioengine_openal.h"
  30. #include "lllistener_openal.h"
  31. const float LLAudioEngine_OpenAL::WIND_BUFFER_SIZE_SEC = 0.05f;
  32. LLAudioEngine_OpenAL::LLAudioEngine_OpenAL()
  33. :
  34. mWindGen(NULL),
  35. mWindBuf(NULL),
  36. mWindBufFreq(0),
  37. mWindBufSamples(0),
  38. mWindBufBytes(0),
  39. mWindSource(AL_NONE),
  40. mNumEmptyWindALBuffers(MAX_NUM_WIND_BUFFERS)
  41. {
  42. }
  43. // virtual
  44. LLAudioEngine_OpenAL::~LLAudioEngine_OpenAL()
  45. {
  46. }
  47. // virtual
  48. bool LLAudioEngine_OpenAL::init(const S32 num_channels, void* userdata)
  49. {
  50. mWindGen = NULL;
  51. LLAudioEngine::init(num_channels, userdata);
  52. if(!alutInit(NULL, NULL))
  53. {
  54. llwarns << "LLAudioEngine_OpenAL::init() ALUT initialization failed: " << alutGetErrorString (alutGetError ()) << llendl;
  55. return false;
  56. }
  57. llinfos << "LLAudioEngine_OpenAL::init() OpenAL successfully initialized" << llendl;
  58. llinfos << "OpenAL version: "
  59. << ll_safe_string(alGetString(AL_VERSION)) << llendl;
  60. llinfos << "OpenAL vendor: "
  61. << ll_safe_string(alGetString(AL_VENDOR)) << llendl;
  62. llinfos << "OpenAL renderer: "
  63. << ll_safe_string(alGetString(AL_RENDERER)) << llendl;
  64. ALint major = alutGetMajorVersion ();
  65. ALint minor = alutGetMinorVersion ();
  66. llinfos << "ALUT version: " << major << "." << minor << llendl;
  67. ALCdevice *device = alcGetContextsDevice(alcGetCurrentContext());
  68. alcGetIntegerv(device, ALC_MAJOR_VERSION, 1, &major);
  69. alcGetIntegerv(device, ALC_MAJOR_VERSION, 1, &minor);
  70. llinfos << "ALC version: " << major << "." << minor << llendl;
  71. llinfos << "ALC default device: "
  72. << ll_safe_string(alcGetString(device,
  73. ALC_DEFAULT_DEVICE_SPECIFIER))
  74. << llendl;
  75. return true;
  76. }
  77. // virtual
  78. std::string LLAudioEngine_OpenAL::getDriverName(bool verbose)
  79. {
  80. ALCdevice *device = alcGetContextsDevice(alcGetCurrentContext());
  81. std::ostringstream version;
  82. version <<
  83. "OpenAL";
  84. if (verbose)
  85. {
  86. version <<
  87. ", version " <<
  88. ll_safe_string(alGetString(AL_VERSION)) <<
  89. " / " <<
  90. ll_safe_string(alGetString(AL_VENDOR)) <<
  91. " / " <<
  92. ll_safe_string(alGetString(AL_RENDERER));
  93. if (device)
  94. version <<
  95. ": " <<
  96. ll_safe_string(alcGetString(device,
  97. ALC_DEFAULT_DEVICE_SPECIFIER));
  98. }
  99. return version.str();
  100. }
  101. // virtual
  102. void LLAudioEngine_OpenAL::allocateListener()
  103. {
  104. mListenerp = (LLListener *) new LLListener_OpenAL();
  105. if(!mListenerp)
  106. {
  107. llwarns << "LLAudioEngine_OpenAL::allocateListener() Listener creation failed" << llendl;
  108. }
  109. }
  110. // virtual
  111. void LLAudioEngine_OpenAL::shutdown()
  112. {
  113. llinfos << "About to LLAudioEngine::shutdown()" << llendl;
  114. LLAudioEngine::shutdown();
  115. llinfos << "About to alutExit()" << llendl;
  116. if(!alutExit())
  117. {
  118. llwarns << "Nuts." << llendl;
  119. llwarns << "LLAudioEngine_OpenAL::shutdown() ALUT shutdown failed: " << alutGetErrorString (alutGetError ()) << llendl;
  120. }
  121. llinfos << "LLAudioEngine_OpenAL::shutdown() OpenAL successfully shut down" << llendl;
  122. delete mListenerp;
  123. mListenerp = NULL;
  124. }
  125. LLAudioBuffer *LLAudioEngine_OpenAL::createBuffer()
  126. {
  127. return new LLAudioBufferOpenAL();
  128. }
  129. LLAudioChannel *LLAudioEngine_OpenAL::createChannel()
  130. {
  131. return new LLAudioChannelOpenAL();
  132. }
  133. void LLAudioEngine_OpenAL::setInternalGain(F32 gain)
  134. {
  135. //llinfos << "LLAudioEngine_OpenAL::setInternalGain() Gain: " << gain << llendl;
  136. alListenerf(AL_GAIN, gain);
  137. }
  138. LLAudioChannelOpenAL::LLAudioChannelOpenAL()
  139. :
  140. mALSource(AL_NONE),
  141. mLastSamplePos(0)
  142. {
  143. alGenSources(1, &mALSource);
  144. }
  145. LLAudioChannelOpenAL::~LLAudioChannelOpenAL()
  146. {
  147. cleanup();
  148. alDeleteSources(1, &mALSource);
  149. }
  150. void LLAudioChannelOpenAL::cleanup()
  151. {
  152. alSourceStop(mALSource);
  153. mCurrentBufferp = NULL;
  154. }
  155. void LLAudioChannelOpenAL::play()
  156. {
  157. if (mALSource == AL_NONE)
  158. {
  159. llwarns << "Playing without a mALSource, aborting" << llendl;
  160. return;
  161. }
  162. if(!isPlaying())
  163. {
  164. alSourcePlay(mALSource);
  165. getSource()->setPlayedOnce(true);
  166. }
  167. }
  168. void LLAudioChannelOpenAL::playSynced(LLAudioChannel *channelp)
  169. {
  170. if (channelp)
  171. {
  172. LLAudioChannelOpenAL *masterchannelp =
  173. (LLAudioChannelOpenAL*)channelp;
  174. if (mALSource != AL_NONE &&
  175. masterchannelp->mALSource != AL_NONE)
  176. {
  177. // we have channels allocated to master and slave
  178. ALfloat master_offset;
  179. alGetSourcef(masterchannelp->mALSource, AL_SEC_OFFSET,
  180. &master_offset);
  181. llinfos << "Syncing with master at " << master_offset
  182. << "sec" << llendl;
  183. // *TODO: detect when this fails, maybe use AL_SAMPLE_
  184. alSourcef(mALSource, AL_SEC_OFFSET, master_offset);
  185. }
  186. }
  187. play();
  188. }
  189. bool LLAudioChannelOpenAL::isPlaying()
  190. {
  191. if (mALSource != AL_NONE)
  192. {
  193. ALint state;
  194. alGetSourcei(mALSource, AL_SOURCE_STATE, &state);
  195. if(state == AL_PLAYING)
  196. {
  197. return true;
  198. }
  199. }
  200. return false;
  201. }
  202. bool LLAudioChannelOpenAL::updateBuffer()
  203. {
  204. if (LLAudioChannel::updateBuffer())
  205. {
  206. // Base class update returned true, which means that we need to actually
  207. // set up the source for a different buffer.
  208. LLAudioBufferOpenAL *bufferp = (LLAudioBufferOpenAL *)mCurrentSourcep->getCurrentBuffer();
  209. ALuint buffer = bufferp->getBuffer();
  210. alSourcei(mALSource, AL_BUFFER, buffer);
  211. mLastSamplePos = 0;
  212. }
  213. if (mCurrentSourcep)
  214. {
  215. alSourcef(mALSource, AL_GAIN,
  216. mCurrentSourcep->getGain() * getSecondaryGain());
  217. alSourcei(mALSource, AL_LOOPING,
  218. mCurrentSourcep->isLoop() ? AL_TRUE : AL_FALSE);
  219. alSourcef(mALSource, AL_ROLLOFF_FACTOR,
  220. gAudiop->mListenerp->getRolloffFactor());
  221. }
  222. return true;
  223. }
  224. void LLAudioChannelOpenAL::updateLoop()
  225. {
  226. if (mALSource == AL_NONE)
  227. {
  228. return;
  229. }
  230. // Hack: We keep track of whether we looped or not by seeing when the
  231. // sample position looks like it's going backwards. Not reliable; may
  232. // yield false negatives.
  233. //
  234. ALint cur_pos;
  235. alGetSourcei(mALSource, AL_SAMPLE_OFFSET, &cur_pos);
  236. if (cur_pos < mLastSamplePos)
  237. {
  238. mLoopedThisFrame = true;
  239. }
  240. mLastSamplePos = cur_pos;
  241. }
  242. void LLAudioChannelOpenAL::update3DPosition()
  243. {
  244. if(!mCurrentSourcep)
  245. {
  246. return;
  247. }
  248. if (mCurrentSourcep->isAmbient())
  249. {
  250. alSource3f(mALSource, AL_POSITION, 0.0, 0.0, 0.0);
  251. alSource3f(mALSource, AL_VELOCITY, 0.0, 0.0, 0.0);
  252. alSourcei (mALSource, AL_SOURCE_RELATIVE, AL_TRUE);
  253. } else {
  254. LLVector3 float_pos;
  255. float_pos.setVec(mCurrentSourcep->getPositionGlobal());
  256. alSourcefv(mALSource, AL_POSITION, float_pos.mV);
  257. alSourcefv(mALSource, AL_VELOCITY, mCurrentSourcep->getVelocity().mV);
  258. alSourcei (mALSource, AL_SOURCE_RELATIVE, AL_FALSE);
  259. }
  260. alSourcef(mALSource, AL_GAIN, mCurrentSourcep->getGain() * getSecondaryGain());
  261. }
  262. LLAudioBufferOpenAL::LLAudioBufferOpenAL()
  263. {
  264. mALBuffer = AL_NONE;
  265. }
  266. LLAudioBufferOpenAL::~LLAudioBufferOpenAL()
  267. {
  268. cleanup();
  269. }
  270. void LLAudioBufferOpenAL::cleanup()
  271. {
  272. if(mALBuffer != AL_NONE)
  273. {
  274. alDeleteBuffers(1, &mALBuffer);
  275. mALBuffer = AL_NONE;
  276. }
  277. }
  278. bool LLAudioBufferOpenAL::loadWAV(const std::string& filename)
  279. {
  280. cleanup();
  281. mALBuffer = alutCreateBufferFromFile(filename.c_str());
  282. if(mALBuffer == AL_NONE)
  283. {
  284. ALenum error = alutGetError();
  285. if (gDirUtilp->fileExists(filename))
  286. {
  287. llwarns <<
  288. "LLAudioBufferOpenAL::loadWAV() Error loading "
  289. << filename
  290. << " " << alutGetErrorString(error) << llendl;
  291. }
  292. else
  293. {
  294. // It's common for the file to not actually exist.
  295. lldebugs <<
  296. "LLAudioBufferOpenAL::loadWAV() Error loading "
  297. << filename
  298. << " " << alutGetErrorString(error) << llendl;
  299. }
  300. return false;
  301. }
  302. return true;
  303. }
  304. U32 LLAudioBufferOpenAL::getLength()
  305. {
  306. if(mALBuffer == AL_NONE)
  307. {
  308. return 0;
  309. }
  310. ALint length;
  311. alGetBufferi(mALBuffer, AL_SIZE, &length);
  312. return length / 2; // convert size in bytes to size in (16-bit) samples
  313. }
  314. // ------------
  315. bool LLAudioEngine_OpenAL::initWind()
  316. {
  317. ALenum error;
  318. llinfos << "LLAudioEngine_OpenAL::initWind() start" << llendl;
  319. mNumEmptyWindALBuffers = MAX_NUM_WIND_BUFFERS;
  320. alGetError(); /* clear error */
  321. alGenSources(1,&mWindSource);
  322. if((error=alGetError()) != AL_NO_ERROR)
  323. {
  324. llwarns << "LLAudioEngine_OpenAL::initWind() Error creating wind sources: "<<error<<llendl;
  325. }
  326. mWindGen = new LLWindGen<WIND_SAMPLE_T>;
  327. mWindBufFreq = mWindGen->getInputSamplingRate();
  328. mWindBufSamples = llceil(mWindBufFreq * WIND_BUFFER_SIZE_SEC);
  329. mWindBufBytes = mWindBufSamples * 2 /*stereo*/ * sizeof(WIND_SAMPLE_T);
  330. mWindBuf = new WIND_SAMPLE_T [mWindBufSamples * 2 /*stereo*/];
  331. if(mWindBuf==NULL)
  332. {
  333. llerrs << "LLAudioEngine_OpenAL::initWind() Error creating wind memory buffer" << llendl;
  334. return false;
  335. }
  336. llinfos << "LLAudioEngine_OpenAL::initWind() done" << llendl;
  337. return true;
  338. }
  339. void LLAudioEngine_OpenAL::cleanupWind()
  340. {
  341. llinfos << "LLAudioEngine_OpenAL::cleanupWind()" << llendl;
  342. if (mWindSource != AL_NONE)
  343. {
  344. // detach and delete all outstanding buffers on the wind source
  345. alSourceStop(mWindSource);
  346. ALint processed;
  347. alGetSourcei(mWindSource, AL_BUFFERS_PROCESSED, &processed);
  348. while (processed--)
  349. {
  350. ALuint buffer = AL_NONE;
  351. alSourceUnqueueBuffers(mWindSource, 1, &buffer);
  352. alDeleteBuffers(1, &buffer);
  353. }
  354. // delete the wind source itself
  355. alDeleteSources(1, &mWindSource);
  356. mWindSource = AL_NONE;
  357. }
  358. delete[] mWindBuf;
  359. mWindBuf = NULL;
  360. delete mWindGen;
  361. mWindGen = NULL;
  362. }
  363. void LLAudioEngine_OpenAL::updateWind(LLVector3 wind_vec, F32 camera_altitude)
  364. {
  365. LLVector3 wind_pos;
  366. F64 pitch;
  367. F64 center_freq;
  368. ALenum error;
  369. if (!mEnableWind)
  370. return;
  371. if(!mWindBuf)
  372. return;
  373. if (mWindUpdateTimer.checkExpirationAndReset(LL_WIND_UPDATE_INTERVAL))
  374. {
  375. // wind comes in as Linden coordinate (+X = forward, +Y = left, +Z = up)
  376. // need to convert this to the conventional orientation DS3D and OpenAL use
  377. // where +X = right, +Y = up, +Z = backwards
  378. wind_vec.setVec(-wind_vec.mV[1], wind_vec.mV[2], -wind_vec.mV[0]);
  379. pitch = 1.0 + mapWindVecToPitch(wind_vec);
  380. center_freq = 80.0 * pow(pitch,2.5*(mapWindVecToGain(wind_vec)+1.0));
  381. mWindGen->mTargetFreq = (F32)center_freq;
  382. mWindGen->mTargetGain = (F32)mapWindVecToGain(wind_vec) * mMaxWindGain;
  383. mWindGen->mTargetPanGainR = (F32)mapWindVecToPan(wind_vec);
  384. alSourcei(mWindSource, AL_LOOPING, AL_FALSE);
  385. alSource3f(mWindSource, AL_POSITION, 0.0, 0.0, 0.0);
  386. alSource3f(mWindSource, AL_VELOCITY, 0.0, 0.0, 0.0);
  387. alSourcef(mWindSource, AL_ROLLOFF_FACTOR, 0.0);
  388. alSourcei(mWindSource, AL_SOURCE_RELATIVE, AL_TRUE);
  389. }
  390. // ok lets make a wind buffer now
  391. ALint processed, queued, unprocessed;
  392. alGetSourcei(mWindSource, AL_BUFFERS_PROCESSED, &processed);
  393. alGetSourcei(mWindSource, AL_BUFFERS_QUEUED, &queued);
  394. unprocessed = queued - processed;
  395. // ensure that there are always at least 3x as many filled buffers
  396. // queued as we managed to empty since last time.
  397. mNumEmptyWindALBuffers = llmin(mNumEmptyWindALBuffers + processed * 3 - unprocessed, MAX_NUM_WIND_BUFFERS-unprocessed);
  398. mNumEmptyWindALBuffers = llmax(mNumEmptyWindALBuffers, 0);
  399. //llinfos << "mNumEmptyWindALBuffers: " << mNumEmptyWindALBuffers <<" (" << unprocessed << ":" << processed << ")" << llendl;
  400. while(processed--) // unqueue old buffers
  401. {
  402. ALuint buffer;
  403. ALenum error;
  404. alGetError(); /* clear error */
  405. alSourceUnqueueBuffers(mWindSource, 1, &buffer);
  406. error = alGetError();
  407. if(error != AL_NO_ERROR)
  408. {
  409. llwarns << "LLAudioEngine_OpenAL::updateWind() error swapping (unqueuing) buffers" << llendl;
  410. }
  411. else
  412. {
  413. alDeleteBuffers(1, &buffer);
  414. }
  415. }
  416. unprocessed += mNumEmptyWindALBuffers;
  417. while (mNumEmptyWindALBuffers > 0) // fill+queue new buffers
  418. {
  419. ALuint buffer;
  420. alGetError(); /* clear error */
  421. alGenBuffers(1,&buffer);
  422. if((error=alGetError()) != AL_NO_ERROR)
  423. {
  424. llwarns << "LLAudioEngine_OpenAL::updateWind() Error creating wind buffer: " << error << llendl;
  425. break;
  426. }
  427. alBufferData(buffer,
  428. AL_FORMAT_STEREO16,
  429. mWindGen->windGenerate(mWindBuf,
  430. mWindBufSamples),
  431. mWindBufBytes,
  432. mWindBufFreq);
  433. error = alGetError();
  434. if(error != AL_NO_ERROR)
  435. {
  436. llwarns << "LLAudioEngine_OpenAL::updateWind() error swapping (bufferdata) buffers" << llendl;
  437. }
  438. alSourceQueueBuffers(mWindSource, 1, &buffer);
  439. error = alGetError();
  440. if(error != AL_NO_ERROR)
  441. {
  442. llwarns << "LLAudioEngine_OpenAL::updateWind() error swapping (queuing) buffers" << llendl;
  443. }
  444. --mNumEmptyWindALBuffers;
  445. }
  446. ALint playing;
  447. alGetSourcei(mWindSource, AL_SOURCE_STATE, &playing);
  448. if(playing != AL_PLAYING)
  449. {
  450. alSourcePlay(mWindSource);
  451. lldebugs << "Wind had stopped - probably ran out of buffers - restarting: " << (unprocessed+mNumEmptyWindALBuffers) << " now queued." << llendl;
  452. }
  453. }