llaudioengine_openal.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:13k
源码类别:

游戏引擎

开发平台:

C++ Builder

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