aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llaudio/audioengine.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'linden/indra/llaudio/audioengine.cpp')
-rw-r--r--linden/indra/llaudio/audioengine.cpp1672
1 files changed, 1672 insertions, 0 deletions
diff --git a/linden/indra/llaudio/audioengine.cpp b/linden/indra/llaudio/audioengine.cpp
new file mode 100644
index 0000000..46e621a
--- /dev/null
+++ b/linden/indra/llaudio/audioengine.cpp
@@ -0,0 +1,1672 @@
1/**
2 * @file audioengine.cpp
3 * @brief implementation of LLAudioEngine class abstracting the Open
4 * AL audio support
5 *
6 * Copyright (c) 2000-2007, Linden Research, Inc.
7 *
8 * The source code in this file ("Source Code") is provided by Linden Lab
9 * to you under the terms of the GNU General Public License, version 2.0
10 * ("GPL"), unless you have obtained a separate licensing agreement
11 * ("Other License"), formally executed by you and Linden Lab. Terms of
12 * the GPL can be found in doc/GPL-license.txt in this distribution, or
13 * online at http://secondlife.com/developers/opensource/gplv2
14 *
15 * There are special exceptions to the terms and conditions of the GPL as
16 * it is applied to this Source Code. View the full text of the exception
17 * in the file doc/FLOSS-exception.txt in this software distribution, or
18 * online at http://secondlife.com/developers/opensource/flossexception
19 *
20 * By copying, modifying or distributing this software, you acknowledge
21 * that you have read and understood your obligations described above,
22 * and agree to abide by those obligations.
23 *
24 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
25 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
26 * COMPLETENESS OR PERFORMANCE.
27 */
28
29#include "linden_common.h"
30
31#include <stdio.h>
32#include <stdlib.h>
33#include <string.h>
34#include <math.h>
35
36#if LL_LINUX
37#include <time.h>
38#endif
39
40//#include "message.h"
41
42#include "audioengine.h"
43
44#include "llerror.h"
45#include "llmath.h"
46
47#include "sound_ids.h" // temporary hack for min/max distances
48
49#include "llvfs.h"
50#include "lldir.h"
51#include "llaudiodecodemgr.h"
52#include "llassetstorage.h"
53
54// necessary for grabbing sounds from sim (implemented in viewer)
55extern void request_sound(const LLUUID &sound_guid);
56
57LLAudioEngine* gAudiop = NULL;
58
59// Maximum amount of time we wait for a transfer to complete before starting
60// off another one.
61const F32 MAX_CURRENT_TRANSFER_TIME = 60.f;
62
63//
64// LLAudioEngine implementation
65//
66
67
68LLAudioEngine::LLAudioEngine()
69{
70}
71
72
73LLAudioEngine::~LLAudioEngine()
74{
75}
76
77
78BOOL LLAudioEngine::init(const S32 num_channels, void* userdata)
79{
80 mMuted = FALSE;
81 mMasterGain = 1.f;
82 mInternetStreamGain = 0.125f;
83 mUserData = userdata;
84 mLastStatus = 0;
85
86 mNumChannels = num_channels;
87
88
89 mMaxWindGain = 1.0;
90
91 mEnableWind = FALSE;
92
93 S32 i;
94 for (i = 0; i < MAX_BUFFERS; i++)
95 {
96 mBuffers[i] = NULL;
97 }
98 for (i = 0; i < num_channels; i++)
99 {
100 mChannels[i] = NULL;
101 }
102
103 allocateListener();
104
105 // Initialize the decode manager
106 gAudioDecodeMgrp = new LLAudioDecodeMgr;
107
108 return TRUE;
109}
110
111
112void LLAudioEngine::shutdown()
113{
114 // Clean up decode manager
115 delete gAudioDecodeMgrp;
116 gAudioDecodeMgrp = NULL;
117
118 // Clean up audio sources
119 source_map::iterator iter_src;
120 for (iter_src = mAllSources.begin(); iter_src != mAllSources.end(); iter_src++)
121 {
122 delete iter_src->second;
123 }
124
125
126 // Clean up audio data
127 data_map::iterator iter_data;
128 for (iter_data = mAllData.begin(); iter_data != mAllData.end(); iter_data++)
129 {
130 delete iter_data->second;
131 }
132
133
134 // Clean up channels
135 S32 i;
136 if (mChannels)
137 {
138 for (i = 0; i < MAX_CHANNELS; i++)
139 {
140 if (mChannels[i])
141 {
142 delete mChannels[i];
143 mChannels[i] = NULL;
144 }
145 }
146 }
147
148 // Clean up buffers
149 if (mBuffers)
150 {
151 for (i = 0; i < MAX_BUFFERS; i++)
152 {
153 if (mBuffers[i])
154 {
155 delete mBuffers[i];
156 mBuffers[i] = NULL;
157 }
158 }
159 }
160}
161
162
163void LLAudioEngine::updateChannels()
164{
165 S32 i;
166 for (i = 0; i < MAX_CHANNELS; i++)
167 {
168 if (mChannels[i])
169 {
170 mChannels[i]->updateBuffer();
171 mChannels[i]->update3DPosition();
172 mChannels[i]->updateLoop();
173 }
174 }
175}
176
177static const F32 default_max_decode_time = .002f; // 2 ms
178void LLAudioEngine::idle(F32 max_decode_time)
179{
180 if (max_decode_time <= 0.f)
181 {
182 max_decode_time = default_max_decode_time;
183 }
184
185 // "Update" all of our audio sources, clean up dead ones.
186 // Primarily does position updating, cleanup of unused audio sources.
187 // Also does regeneration of the current priority of each audio source.
188
189 if (getMuted())
190 {
191 setInternalGain(0.f);
192 }
193 else
194 {
195 setInternalGain(getMasterGain());
196 }
197
198 S32 i;
199 for (i = 0; i < MAX_BUFFERS; i++)
200 {
201 if (mBuffers[i])
202 {
203 mBuffers[i]->mInUse = FALSE;
204 }
205 }
206
207 F32 max_priority = -1.f;
208 LLAudioSource *max_sourcep = NULL; // Maximum priority source without a channel
209 source_map::iterator iter;
210 for (iter = mAllSources.begin(); iter != mAllSources.end();)
211 {
212 LLAudioSource *sourcep = iter->second;
213
214 // Update this source
215 sourcep->update();
216 sourcep->updatePriority();
217
218 if (sourcep->isDone())
219 {
220 // The source is done playing, clean it up.
221 delete sourcep;
222 mAllSources.erase(iter++);
223 continue;
224 }
225
226 if (!sourcep->getChannel() && sourcep->getCurrentBuffer())
227 {
228 // We could potentially play this sound if its priority is high enough.
229 if (sourcep->getPriority() > max_priority)
230 {
231 max_priority = sourcep->getPriority();
232 max_sourcep = sourcep;
233 }
234 }
235
236 // Move on to the next source
237 iter++;
238 }
239
240 // Now, do priority-based organization of audio sources.
241 // All channels used, check priorities.
242 // Find channel with lowest priority
243 if (max_sourcep)
244 {
245 LLAudioChannel *channelp = getFreeChannel(max_priority);
246 if (channelp)
247 {
248 //llinfos << "Replacing source in channel due to priority!" << llendl;
249 max_sourcep->setChannel(channelp);
250 channelp->setSource(max_sourcep);
251 if (max_sourcep->isSyncSlave())
252 {
253 // A sync slave, it doesn't start playing until it's synced up with the master.
254 // Flag this channel as waiting for sync, and return true.
255 channelp->setWaiting(TRUE);
256 }
257 else
258 {
259 channelp->setWaiting(FALSE);
260 channelp->play();
261 }
262 }
263 }
264
265
266 // Do this BEFORE we update the channels
267 // Update the channels to sync up with any changes that the source made,
268 // such as changing what sound was playing.
269 updateChannels();
270
271 // Update queued sounds (switch to next queued data if the current has finished playing)
272 for (iter = mAllSources.begin(); iter != mAllSources.end(); ++iter)
273 {
274 // This is lame, instead of this I could actually iterate through all the sources
275 // attached to each channel, since only those with active channels
276 // can have anything interesting happen with their queue? (Maybe not true)
277 LLAudioSource *sourcep = iter->second;
278 if (!sourcep->mQueuedDatap)
279 {
280 // Nothing queued, so we don't care.
281 continue;
282 }
283
284 LLAudioChannel *channelp = sourcep->getChannel();
285 if (!channelp)
286 {
287 // This sound isn't playing, so we just process move the queue
288 sourcep->mCurrentDatap = sourcep->mQueuedDatap;
289 sourcep->mQueuedDatap = NULL;
290
291 // Reset the timer so the source doesn't die.
292 sourcep->mAgeTimer.reset();
293 // Make sure we have the buffer set up if we just decoded the data
294 if (sourcep->mCurrentDatap)
295 {
296 updateBufferForData(sourcep->mCurrentDatap);
297 }
298
299 // Actually play the associated data.
300 sourcep->setupChannel();
301 channelp = sourcep->getChannel();
302 if (channelp)
303 {
304 channelp->updateBuffer();
305 sourcep->getChannel()->play();
306 }
307 continue;
308 }
309 else
310 {
311 // Check to see if the current sound is done playing, or looped.
312 if (!channelp->isPlaying())
313 {
314 sourcep->mCurrentDatap = sourcep->mQueuedDatap;
315 sourcep->mQueuedDatap = NULL;
316
317 // Reset the timer so the source doesn't die.
318 sourcep->mAgeTimer.reset();
319
320 // Make sure we have the buffer set up if we just decoded the data
321 if (sourcep->mCurrentDatap)
322 {
323 updateBufferForData(sourcep->mCurrentDatap);
324 }
325
326 // Actually play the associated data.
327 sourcep->setupChannel();
328 channelp->updateBuffer();
329 sourcep->getChannel()->play();
330 }
331 else if (sourcep->isLoop())
332 {
333 // It's a loop, we need to check and see if we're done with it.
334 if (channelp->mLoopedThisFrame)
335 {
336 sourcep->mCurrentDatap = sourcep->mQueuedDatap;
337 sourcep->mQueuedDatap = NULL;
338
339 // Actually, should do a time sync so if we're a loop master/slave
340 // we don't drift away.
341 sourcep->setupChannel();
342 sourcep->getChannel()->play();
343 }
344 }
345 }
346 }
347
348 // Lame, update the channels AGAIN.
349 // Update the channels to sync up with any changes that the source made,
350 // such as changing what sound was playing.
351 updateChannels();
352
353 // Hack! For now, just use a global sync master;
354 LLAudioSource *sync_masterp = NULL;
355 LLAudioChannel *master_channelp = NULL;
356 F32 max_sm_priority = -1.f;
357 for (iter = mAllSources.begin(); iter != mAllSources.end(); ++iter)
358 {
359 LLAudioSource *sourcep = iter->second;
360 if (sourcep->isSyncMaster())
361 {
362 if (sourcep->getPriority() > max_sm_priority)
363 {
364 sync_masterp = sourcep;
365 master_channelp = sync_masterp->getChannel();
366 max_sm_priority = sourcep->getPriority();
367 }
368 }
369 }
370
371 if (master_channelp && master_channelp->mLoopedThisFrame)
372 {
373 // Synchronize loop slaves with their masters
374 // Update queued sounds (switch to next queued data if the current has finished playing)
375 for (iter = mAllSources.begin(); iter != mAllSources.end(); ++iter)
376 {
377 LLAudioSource *sourcep = iter->second;
378
379 if (!sourcep->isSyncSlave())
380 {
381 // Not a loop slave, we don't need to do anything
382 continue;
383 }
384
385 LLAudioChannel *channelp = sourcep->getChannel();
386 if (!channelp)
387 {
388 // Not playing, don't need to bother.
389 continue;
390 }
391
392 if (!channelp->isPlaying())
393 {
394 // Now we need to check if our loop master has just looped, and
395 // start playback if that's the case.
396 if (sync_masterp->getChannel())
397 {
398 channelp->playSynced(master_channelp);
399 channelp->setWaiting(FALSE);
400 }
401 }
402 }
403 }
404
405 // Sync up everything that the audio engine needs done.
406 commitDeferredChanges();
407
408 // Flush unused buffers that are stale enough
409 for (i = 0; i < MAX_BUFFERS; i++)
410 {
411 if (mBuffers[i])
412 {
413 if (!mBuffers[i]->mInUse && mBuffers[i]->mLastUseTimer.getElapsedTimeF32() > 30.f)
414 {
415 //llinfos << "Flushing unused buffer!" << llendl;
416 mBuffers[i]->mAudioDatap->mBufferp = NULL;
417 delete mBuffers[i];
418 mBuffers[i] = NULL;
419 }
420 }
421 }
422
423
424 // Clear all of the looped flags for the channels
425 for (i = 0; i < MAX_CHANNELS; i++)
426 {
427 if (mChannels[i])
428 {
429 mChannels[i]->mLoopedThisFrame = FALSE;
430 }
431 }
432
433 // Decode audio files
434 gAudioDecodeMgrp->processQueue(max_decode_time);
435
436 // Call this every frame, just in case we somehow
437 // missed picking it up in all the places that can add
438 // or request new data.
439 startNextTransfer();
440}
441
442BOOL LLAudioEngine::updateBufferForData(LLAudioData *adp, const LLUUID &audio_uuid)
443{
444 if (!adp)
445 {
446 return FALSE;
447 }
448
449 // Update the audio buffer first - load a sound if we have it.
450 // Note that this could potentially cause us to waste time updating buffers
451 // for sounds that actually aren't playing, although this should be mitigated
452 // by the fact that we limit the number of buffers, and we flush buffers based
453 // on priority.
454 if (!adp->getBuffer())
455 {
456 if (adp->hasDecodedData())
457 {
458 adp->load();
459 }
460 else if (adp->hasLocalData())
461 {
462 if (audio_uuid.notNull())
463 {
464 gAudioDecodeMgrp->addDecodeRequest(audio_uuid);
465 }
466 }
467 else
468 {
469 return FALSE;
470 }
471 }
472 return TRUE;
473}
474
475
476void LLAudioEngine::enableWind(BOOL enable)
477{
478 if (enable && (!mEnableWind))
479 {
480 initWind();
481 mEnableWind = enable;
482 }
483 else if (mEnableWind && (!enable))
484 {
485 mEnableWind = enable;
486 cleanupWind();
487 }
488}
489
490
491LLAudioBuffer *LLAudioEngine::getFreeBuffer()
492{
493 S32 i;
494 for (i = 0; i < MAX_BUFFERS; i++)
495 {
496 if (!mBuffers[i])
497 {
498 mBuffers[i] = createBuffer();
499 return mBuffers[i];
500 }
501 }
502
503
504 // Grab the oldest unused buffer
505 F32 max_age = -1.f;
506 S32 buffer_id = -1;
507 for (i = 0; i < MAX_BUFFERS; i++)
508 {
509 if (mBuffers[i])
510 {
511 if (!mBuffers[i]->mInUse)
512 {
513 if (mBuffers[i]->mLastUseTimer.getElapsedTimeF32() > max_age)
514 {
515 max_age = mBuffers[i]->mLastUseTimer.getElapsedTimeF32();
516 buffer_id = i;
517 }
518 }
519 }
520 }
521
522 if (buffer_id >= 0)
523 {
524 llinfos << "Taking over unused buffer " << buffer_id << llendl;
525 //llinfos << "Flushing unused buffer!" << llendl;
526 mBuffers[buffer_id]->mAudioDatap->mBufferp = NULL;
527 delete mBuffers[buffer_id];
528 mBuffers[buffer_id] = createBuffer();
529 return mBuffers[buffer_id];
530 }
531 return NULL;
532}
533
534
535LLAudioChannel * LLAudioEngine::getFreeChannel(const F32 priority)
536{
537 S32 i;
538 for (i = 0; i < mNumChannels; i++)
539 {
540 if (!mChannels[i])
541 {
542 // No channel allocated here, use it.
543 mChannels[i] = createChannel();
544 return mChannels[i];
545 }
546 else
547 {
548 // Channel is allocated but not playing right now, use it.
549 if (!mChannels[i]->isPlaying() && !mChannels[i]->isWaiting())
550 {
551 mChannels[i]->cleanup();
552 if (mChannels[i]->getSource())
553 {
554 mChannels[i]->getSource()->setChannel(NULL);
555 }
556 return mChannels[i];
557 }
558 }
559 }
560
561 // All channels used, check priorities.
562 // Find channel with lowest priority and see if we want to replace it.
563 F32 min_priority = 10000.f;
564 LLAudioChannel *min_channelp = NULL;
565
566 for (i = 0; i < mNumChannels; i++)
567 {
568 LLAudioChannel *channelp = mChannels[i];
569 LLAudioSource *sourcep = channelp->getSource();
570 if (sourcep->getPriority() < min_priority)
571 {
572 min_channelp = channelp;
573 min_priority = sourcep->getPriority();
574 }
575 }
576
577 if (min_priority > priority)
578 {
579 // All playing channels have higher priority, return.
580 return NULL;
581 }
582
583 // Flush the minimum priority channel, and return it.
584 min_channelp->cleanup();
585 min_channelp->getSource()->setChannel(NULL);
586 return min_channelp;
587}
588
589
590void LLAudioEngine::cleanupBuffer(LLAudioBuffer *bufferp)
591{
592 S32 i;
593 for (i = 0; i < MAX_BUFFERS; i++)
594 {
595 if (mBuffers[i] == bufferp)
596 {
597 delete mBuffers[i];
598 mBuffers[i] = NULL;
599 }
600 }
601}
602
603
604BOOL LLAudioEngine::preloadSound(const LLUUID &uuid)
605{
606 gAudiop->getAudioData(uuid); // We don't care about the return value, this is just to make sure
607 // that we have an entry, which will mean that the audio engine knows about this
608
609 if (gAudioDecodeMgrp->addDecodeRequest(uuid))
610 {
611 // This means that we do have a local copy, and we're working on decoding it.
612 return TRUE;
613 }
614
615 // At some point we need to have the audio/asset system check the static VFS
616 // before it goes off and fetches stuff from the server.
617 //llwarns << "Used internal preload for non-local sound" << llendl;
618 return FALSE;
619}
620
621
622BOOL LLAudioEngine::isWindEnabled()
623{
624 return mEnableWind;
625}
626
627
628void LLAudioEngine::setMuted(BOOL muted)
629{
630 mMuted = muted;
631 enableWind(!mMuted);
632}
633
634
635void LLAudioEngine::setMasterGain(const F32 gain)
636{
637 mMasterGain = gain;
638 setInternalGain(gain);
639}
640
641F32 LLAudioEngine::getMasterGain()
642{
643 return mMasterGain;
644}
645
646F32 LLAudioEngine::getInternetStreamGain()
647{
648 return mInternetStreamGain;
649}
650
651void LLAudioEngine::setMaxWindGain(F32 gain)
652{
653 mMaxWindGain = gain;
654}
655
656
657F64 LLAudioEngine::mapWindVecToGain(LLVector3 wind_vec)
658{
659 F64 gain = 0.0;
660
661 gain = wind_vec.magVec();
662
663 if (gain)
664 {
665 if (gain > 20)
666 {
667 gain = 20;
668 }
669 gain = gain/20.0;
670 }
671
672 return (gain);
673}
674
675
676F64 LLAudioEngine::mapWindVecToPitch(LLVector3 wind_vec)
677{
678 LLVector3 listen_right;
679 F64 theta;
680
681 // Wind frame is in listener-relative coordinates
682 LLVector3 norm_wind = wind_vec;
683 norm_wind.normVec();
684 listen_right.setVec(1.0,0.0,0.0);
685
686 // measure angle between wind vec and listener right axis (on 0,PI)
687 theta = acos(norm_wind * listen_right);
688
689 // put it on 0, 1
690 theta /= F_PI;
691
692 // put it on [0, 0.5, 0]
693 if (theta > 0.5) theta = 1.0-theta;
694 if (theta < 0) theta = 0;
695
696 return (theta);
697}
698
699
700F64 LLAudioEngine::mapWindVecToPan(LLVector3 wind_vec)
701{
702 LLVector3 listen_right;
703 F64 theta;
704
705 // Wind frame is in listener-relative coordinates
706 listen_right.setVec(1.0,0.0,0.0);
707
708 LLVector3 norm_wind = wind_vec;
709 norm_wind.normVec();
710
711 // measure angle between wind vec and listener right axis (on 0,PI)
712 theta = acos(norm_wind * listen_right);
713
714 // put it on 0, 1
715 theta /= F_PI;
716
717 return (theta);
718}
719
720
721void LLAudioEngine::triggerSound(const LLUUID &audio_uuid, const LLUUID& owner_id, const F32 gain, const LLVector3d &pos_global)
722{
723 // Create a new source (since this can't be associated with an existing source.
724 //llinfos << "Localized: " << audio_uuid << llendl;
725
726 if (mMuted)
727 {
728 return;
729 }
730
731 LLUUID source_id;
732 source_id.generate();
733
734 LLAudioSource *asp = new LLAudioSource(source_id, owner_id, gain);
735 gAudiop->addAudioSource(asp);
736 if (pos_global.isExactlyZero())
737 {
738 asp->setAmbient(TRUE);
739 }
740 else
741 {
742 asp->setPositionGlobal(pos_global);
743 }
744 asp->updatePriority();
745 asp->play(audio_uuid);
746}
747
748
749void LLAudioEngine::setListenerPos(LLVector3 aVec)
750{
751 mListenerp->setPosition(aVec);
752}
753
754
755LLVector3 LLAudioEngine::getListenerPos()
756{
757 if (mListenerp)
758 {
759 return(mListenerp->getPosition());
760 }
761 else
762 {
763 return(LLVector3::zero);
764 }
765}
766
767
768void LLAudioEngine::setListenerVelocity(LLVector3 aVec)
769{
770 mListenerp->setVelocity(aVec);
771}
772
773
774void LLAudioEngine::translateListener(LLVector3 aVec)
775{
776 mListenerp->translate(aVec);
777}
778
779
780void LLAudioEngine::orientListener(LLVector3 up, LLVector3 at)
781{
782 mListenerp->orient(up, at);
783}
784
785
786void LLAudioEngine::setListener(LLVector3 pos, LLVector3 vel, LLVector3 up, LLVector3 at)
787{
788 mListenerp->set(pos,vel,up,at);
789}
790
791
792void LLAudioEngine::setDopplerFactor(F32 factor)
793{
794 if (mListenerp)
795 {
796 mListenerp->setDopplerFactor(factor);
797 }
798}
799
800
801F32 LLAudioEngine::getDopplerFactor()
802{
803 if (mListenerp)
804 {
805 return mListenerp->getDopplerFactor();
806 }
807 else
808 {
809 return 0.f;
810 }
811}
812
813
814void LLAudioEngine::setDistanceFactor(F32 factor)
815{
816 if (mListenerp)
817 {
818 mListenerp->setDistanceFactor(factor);
819 }
820}
821
822
823F32 LLAudioEngine::getDistanceFactor()
824{
825 if (mListenerp)
826 {
827 return mListenerp->getDistanceFactor();
828 }
829 else
830 {
831 return 0.f;
832 }
833}
834
835
836void LLAudioEngine::setRolloffFactor(F32 factor)
837{
838 if (mListenerp)
839 {
840 mListenerp->setRolloffFactor(factor);
841 }
842}
843
844
845F32 LLAudioEngine::getRolloffFactor()
846{
847 if (mListenerp)
848 {
849 return mListenerp->getRolloffFactor();
850 }
851 else
852 {
853 return 0.f;
854 }
855}
856
857
858void LLAudioEngine::commitDeferredChanges()
859{
860 mListenerp->commitDeferredChanges();
861}
862
863
864LLAudioSource *LLAudioEngine::findAudioSource(const LLUUID &source_id)
865{
866 source_map::iterator iter;
867 iter = mAllSources.find(source_id);
868
869 if (iter == mAllSources.end())
870 {
871 return NULL;
872 }
873 else
874 {
875 return iter->second;
876 }
877}
878
879
880LLAudioData *LLAudioEngine::getAudioData(const LLUUID &audio_uuid)
881{
882 data_map::iterator iter;
883 iter = mAllData.find(audio_uuid);
884 if (iter == mAllData.end())
885 {
886 // Create the new audio data
887 LLAudioData *adp = new LLAudioData(audio_uuid);
888 mAllData[audio_uuid] = adp;
889 return adp;
890 }
891 else
892 {
893 return iter->second;
894 }
895}
896
897void LLAudioEngine::addAudioSource(LLAudioSource *asp)
898{
899 mAllSources[asp->getID()] = asp;
900}
901
902
903void LLAudioEngine::cleanupAudioSource(LLAudioSource *asp)
904{
905 source_map::iterator iter;
906 iter = mAllSources.find(asp->getID());
907 if (iter == mAllSources.end())
908 {
909 llwarns << "Cleaning up unknown audio source!" << llendl;
910 return;
911 }
912 delete asp;
913 mAllSources.erase(iter);
914}
915
916
917BOOL LLAudioEngine::hasDecodedFile(const LLUUID &uuid)
918{
919 char uuid_str[UUID_STR_LENGTH]; /*Flawfinder: ignore*/
920 uuid.toString(uuid_str);
921
922 std::string wav_path;
923 wav_path = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,uuid_str);
924 wav_path += ".dsf";
925
926 if (gDirUtilp->fileExists(wav_path))
927 {
928 return TRUE;
929 }
930 else
931 {
932 return FALSE;
933 }
934}
935
936
937BOOL LLAudioEngine::hasLocalFile(const LLUUID &uuid)
938{
939 // See if it's in the VFS.
940 return gVFS->getExists(uuid, LLAssetType::AT_SOUND);
941}
942
943
944void LLAudioEngine::startNextTransfer()
945{
946 //llinfos << "LLAudioEngine::startNextTransfer()" << llendl;
947 if (mCurrentTransfer.notNull() || getMuted())
948 {
949 //llinfos << "Transfer in progress, aborting" << llendl;
950 return;
951 }
952
953 // Get the ID for the next asset that we want to transfer.
954 // Pick one in the following order:
955 LLUUID asset_id;
956 S32 i;
957 LLAudioSource *asp = NULL;
958 LLAudioData *adp = NULL;
959 data_map::iterator data_iter;
960
961 // Check all channels for currently playing sounds.
962 F32 max_pri = -1.f;
963 for (i = 0; i < MAX_CHANNELS; i++)
964 {
965 if (!mChannels[i])
966 {
967 continue;
968 }
969
970 asp = mChannels[i]->getSource();
971 if (!asp)
972 {
973 continue;
974 }
975 if (asp->getPriority() <= max_pri)
976 {
977 continue;
978 }
979
980 if (asp->getPriority() <= max_pri)
981 {
982 continue;
983 }
984
985 adp = asp->getCurrentData();
986 if (!adp)
987 {
988 continue;
989 }
990
991 if (!adp->hasLocalData() && adp->hasValidData())
992 {
993 asset_id = adp->getID();
994 max_pri = asp->getPriority();
995 }
996 }
997
998 // Check all channels for currently queued sounds.
999 if (asset_id.isNull())
1000 {
1001 max_pri = -1.f;
1002 for (i = 0; i < MAX_CHANNELS; i++)
1003 {
1004 if (!mChannels[i])
1005 {
1006 continue;
1007 }
1008
1009 LLAudioSource *asp;
1010 asp = mChannels[i]->getSource();
1011 if (!asp)
1012 {
1013 continue;
1014 }
1015
1016 if (asp->getPriority() <= max_pri)
1017 {
1018 continue;
1019 }
1020
1021 adp = asp->getQueuedData();
1022 if (!adp)
1023 {
1024 continue;
1025 }
1026
1027 if (!adp->hasLocalData() && adp->hasValidData())
1028 {
1029 asset_id = adp->getID();
1030 max_pri = asp->getPriority();
1031 }
1032 }
1033 }
1034
1035 // Check all live channels for other sounds (preloads).
1036 if (asset_id.isNull())
1037 {
1038 max_pri = -1.f;
1039 for (i = 0; i < MAX_CHANNELS; i++)
1040 {
1041 if (!mChannels[i])
1042 {
1043 continue;
1044 }
1045
1046 LLAudioSource *asp;
1047 asp = mChannels[i]->getSource();
1048 if (!asp)
1049 {
1050 continue;
1051 }
1052
1053 if (asp->getPriority() <= max_pri)
1054 {
1055 continue;
1056 }
1057
1058
1059 for (data_iter = asp->mPreloadMap.begin(); data_iter != asp->mPreloadMap.end(); data_iter++)
1060 {
1061 LLAudioData *adp = data_iter->second;
1062 if (!adp)
1063 {
1064 continue;
1065 }
1066
1067 if (!adp->hasLocalData() && adp->hasValidData())
1068 {
1069 asset_id = adp->getID();
1070 max_pri = asp->getPriority();
1071 }
1072 }
1073 }
1074 }
1075
1076 // Check all sources
1077 if (asset_id.isNull())
1078 {
1079 max_pri = -1.f;
1080 source_map::iterator source_iter;
1081 for (source_iter = mAllSources.begin(); source_iter != mAllSources.end(); source_iter++)
1082 {
1083 asp = source_iter->second;
1084 if (!asp)
1085 {
1086 continue;
1087 }
1088
1089 if (asp->getPriority() <= max_pri)
1090 {
1091 continue;
1092 }
1093
1094 adp = asp->getCurrentData();
1095 if (adp && !adp->hasLocalData() && adp->hasValidData())
1096 {
1097 asset_id = adp->getID();
1098 max_pri = asp->getPriority();
1099 continue;
1100 }
1101
1102 adp = asp->getQueuedData();
1103 if (adp && !adp->hasLocalData() && adp->hasValidData())
1104 {
1105 asset_id = adp->getID();
1106 max_pri = asp->getPriority();
1107 continue;
1108 }
1109
1110 for (data_iter = asp->mPreloadMap.begin(); data_iter != asp->mPreloadMap.end(); data_iter++)
1111 {
1112 LLAudioData *adp = data_iter->second;
1113 if (!adp)
1114 {
1115 continue;
1116 }
1117
1118 if (!adp->hasLocalData() && adp->hasValidData())
1119 {
1120 asset_id = adp->getID();
1121 max_pri = asp->getPriority();
1122 break;
1123 }
1124 }
1125 }
1126 }
1127
1128 if (asset_id.notNull())
1129 {
1130 llinfos << "Getting asset data for: " << asset_id << llendl;
1131 gAudiop->mCurrentTransfer = asset_id;
1132 gAudiop->mCurrentTransferTimer.reset();
1133 gAssetStorage->getAssetData(asset_id, LLAssetType::AT_SOUND,
1134 assetCallback, NULL);
1135 }
1136 else
1137 {
1138 //llinfos << "No pending transfers?" << llendl;
1139 }
1140}
1141
1142
1143// static
1144void LLAudioEngine::assetCallback(LLVFS *vfs, const LLUUID &uuid, LLAssetType::EType type, void *user_data, S32 result_code)
1145{
1146 if (result_code)
1147 {
1148 llinfos << "Boom, error in audio file transfer: " << LLAssetStorage::getErrorString( result_code ) << " (" << result_code << ")" << llendl;
1149 // Need to mark data as bad to avoid constant rerequests.
1150 LLAudioData *adp = gAudiop->getAudioData(uuid);
1151 if (adp)
1152 {
1153 adp->setHasValidData(FALSE);
1154 adp->setHasLocalData(FALSE);
1155 adp->setHasDecodedData(FALSE);
1156 }
1157 }
1158 else
1159 {
1160 LLAudioData *adp = gAudiop->getAudioData(uuid);
1161 if (!adp)
1162 {
1163 // Should never happen
1164 llwarns << "Got asset callback without audio data for " << uuid << llendl;
1165 }
1166 else
1167 {
1168 adp->setHasValidData(TRUE);
1169 adp->setHasLocalData(TRUE);
1170 gAudioDecodeMgrp->addDecodeRequest(uuid);
1171 }
1172 }
1173 gAudiop->mCurrentTransfer = LLUUID::null;
1174 gAudiop->startNextTransfer();
1175}
1176
1177
1178//
1179// LLAudioSource implementation
1180//
1181
1182
1183LLAudioSource::LLAudioSource(const LLUUID& id, const LLUUID& owner_id, const F32 gain)
1184: mID(id),
1185 mOwnerID(owner_id),
1186 mPriority(0.f),
1187 mGain(gain),
1188 mAmbient(FALSE),
1189 mLoop(FALSE),
1190 mSyncMaster(FALSE),
1191 mSyncSlave(FALSE),
1192 mQueueSounds(FALSE),
1193 mPlayedOnce(FALSE),
1194 mChannelp(NULL),
1195 mCurrentDatap(NULL),
1196 mQueuedDatap(NULL)
1197{
1198}
1199
1200
1201LLAudioSource::~LLAudioSource()
1202{
1203 if (mChannelp)
1204 {
1205 // Stop playback of this sound
1206 mChannelp->setSource(NULL);
1207 mChannelp = NULL;
1208 }
1209}
1210
1211
1212void LLAudioSource::setChannel(LLAudioChannel *channelp)
1213{
1214 if (channelp == mChannelp)
1215 {
1216 return;
1217 }
1218
1219 mChannelp = channelp;
1220}
1221
1222
1223void LLAudioSource::update()
1224{
1225 if (!getCurrentBuffer())
1226 {
1227 if (getCurrentData())
1228 {
1229 // Hack - try and load the sound. Will do this as a callback
1230 // on decode later.
1231 if (getCurrentData()->load())
1232 {
1233 play(getCurrentData()->getID());
1234 }
1235 }
1236 }
1237}
1238
1239void LLAudioSource::updatePriority()
1240{
1241 if (isAmbient())
1242 {
1243 mPriority = 1.f;
1244 }
1245 else
1246 {
1247 // Priority is based on distance
1248 LLVector3 dist_vec;
1249 dist_vec.setVec(getPositionGlobal());
1250 dist_vec -= gAudiop->getListenerPos();
1251 F32 dist_squared = llmax(1.f, dist_vec.magVecSquared());
1252
1253 mPriority = mGain / dist_squared;
1254 }
1255}
1256
1257BOOL LLAudioSource::setupChannel()
1258{
1259 LLAudioData *adp = getCurrentData();
1260
1261 if (!adp->getBuffer())
1262 {
1263 // We're not ready to play back the sound yet, so don't try and allocate a channel for it.
1264 //llwarns << "Aborting, no buffer" << llendl;
1265 return FALSE;
1266 }
1267
1268
1269 if (!mChannelp)
1270 {
1271 // Update the priority, in case we need to push out another channel.
1272 updatePriority();
1273
1274 setChannel(gAudiop->getFreeChannel(getPriority()));
1275 }
1276
1277 if (!mChannelp)
1278 {
1279 // Ugh, we don't have any free channels.
1280 // Now we have to reprioritize.
1281 // For now, just don't play the sound.
1282 //llwarns << "Aborting, no free channels" << llendl;
1283 return FALSE;
1284 }
1285
1286 mChannelp->setSource(this);
1287 return TRUE;
1288}
1289
1290
1291BOOL LLAudioSource::play(const LLUUID &audio_uuid)
1292{
1293 if (audio_uuid.isNull())
1294 {
1295 if (getChannel())
1296 {
1297 getChannel()->setSource(NULL);
1298 setChannel(NULL);
1299 addAudioData(NULL, TRUE);
1300 }
1301 }
1302 // Reset our age timeout if someone attempts to play the source.
1303 mAgeTimer.reset();
1304
1305 LLAudioData *adp = gAudiop->getAudioData(audio_uuid);
1306
1307 BOOL has_buffer = gAudiop->updateBufferForData(adp, audio_uuid);
1308
1309
1310 addAudioData(adp);
1311
1312 if (!has_buffer)
1313 {
1314 // Don't bother trying to set up a channel or anything, we don't have an audio buffer.
1315 return FALSE;
1316 }
1317
1318 if (!setupChannel())
1319 {
1320 return FALSE;
1321 }
1322
1323 if (isSyncSlave())
1324 {
1325 // A sync slave, it doesn't start playing until it's synced up with the master.
1326 // Flag this channel as waiting for sync, and return true.
1327 getChannel()->setWaiting(TRUE);
1328 return TRUE;
1329 }
1330
1331 getChannel()->play();
1332 return TRUE;
1333}
1334
1335
1336BOOL LLAudioSource::isDone()
1337{
1338 const F32 MAX_AGE = 60.f;
1339 const F32 MAX_UNPLAYED_AGE = 15.f;
1340 if (isLoop())
1341 {
1342 // Looped sources never die on their own.
1343 return FALSE;
1344 }
1345
1346
1347 if (hasPendingPreloads())
1348 {
1349 return FALSE;
1350 }
1351
1352 if (mQueuedDatap)
1353 {
1354 // Don't kill this sound if we've got something queued up to play.
1355 return FALSE;
1356 }
1357
1358 F32 elapsed = mAgeTimer.getElapsedTimeF32();
1359
1360 // This is a single-play source
1361 if (!mChannelp)
1362 {
1363 if ((elapsed > MAX_UNPLAYED_AGE) || mPlayedOnce)
1364 {
1365 // We don't have a channel assigned, and it's been
1366 // over 5 seconds since we tried to play it. Don't bother.
1367 //llinfos << "No channel assigned, source is done" << llendl;
1368 return TRUE;
1369 }
1370 else
1371 {
1372 return FALSE;
1373 }
1374 }
1375
1376 if (mChannelp->isPlaying())
1377 {
1378 if (elapsed > MAX_AGE)
1379 {
1380 // Arbitarily cut off non-looped sounds when they're 20 seconds old.
1381 return TRUE;
1382 }
1383 else
1384 {
1385 // Sound is still playing and we haven't timed out, don't kill it.
1386 return FALSE;
1387 }
1388 }
1389
1390 if ((elapsed > MAX_UNPLAYED_AGE) || mPlayedOnce)
1391 {
1392 // The sound isn't playing back after 5 seconds or we're already done playing it, kill it.
1393 return TRUE;
1394 }
1395
1396 return FALSE;
1397}
1398
1399
1400void LLAudioSource::addAudioData(LLAudioData *adp, const BOOL set_current)
1401{
1402 // Only handle a single piece of audio data associated with a source right now,
1403 // until I implement prefetch.
1404 if (set_current)
1405 {
1406 if (!mCurrentDatap)
1407 {
1408 mCurrentDatap = adp;
1409 if (mChannelp)
1410 {
1411 mChannelp->updateBuffer();
1412 mChannelp->play();
1413 }
1414
1415 // Make sure the audio engine knows that we want to request this sound.
1416 gAudiop->startNextTransfer();
1417 return;
1418 }
1419 else if (mQueueSounds)
1420 {
1421 // If we have current data, and we're queuing, put
1422 // the object onto the queue.
1423 if (mQueuedDatap)
1424 {
1425 // We only queue one sound at a time, and it's a FIFO.
1426 // Don't put it onto the queue.
1427 return;
1428 }
1429
1430 if (adp == mCurrentDatap && isLoop())
1431 {
1432 // No point in queueing the same sound if
1433 // we're looping.
1434 return;
1435 }
1436 mQueuedDatap = adp;
1437
1438 // Make sure the audio engine knows that we want to request this sound.
1439 gAudiop->startNextTransfer();
1440 }
1441 else
1442 {
1443 if (mCurrentDatap != adp)
1444 {
1445 // Right now, if we're currently playing this sound in a channel, we
1446 // update the buffer that the channel's associated with
1447 // and play it. This may not be the correct behavior.
1448 mCurrentDatap = adp;
1449 if (mChannelp)
1450 {
1451 mChannelp->updateBuffer();
1452 mChannelp->play();
1453 }
1454 // Make sure the audio engine knows that we want to request this sound.
1455 gAudiop->startNextTransfer();
1456 }
1457 }
1458 }
1459 else
1460 {
1461 // Add it to the preload list.
1462 mPreloadMap[adp->getID()] = adp;
1463 gAudiop->startNextTransfer();
1464 }
1465}
1466
1467
1468BOOL LLAudioSource::hasPendingPreloads() const
1469{
1470 // Check to see if we've got any preloads on deck for this source
1471 data_map::const_iterator iter;
1472 for (iter = mPreloadMap.begin(); iter != mPreloadMap.end(); iter++)
1473 {
1474 LLAudioData *adp = iter->second;
1475 if (!adp->hasDecodedData())
1476 {
1477 // This source is still waiting for a preload
1478 return TRUE;
1479 }
1480 }
1481
1482 return FALSE;
1483}
1484
1485
1486LLAudioData *LLAudioSource::getCurrentData()
1487{
1488 return mCurrentDatap;
1489}
1490
1491LLAudioData *LLAudioSource::getQueuedData()
1492{
1493 return mQueuedDatap;
1494}
1495
1496LLAudioBuffer *LLAudioSource::getCurrentBuffer()
1497{
1498 if (!mCurrentDatap)
1499 {
1500 return NULL;
1501 }
1502
1503 return mCurrentDatap->getBuffer();
1504}
1505
1506
1507
1508
1509//
1510// LLAudioChannel implementation
1511//
1512
1513
1514LLAudioChannel::LLAudioChannel() :
1515 mCurrentSourcep(NULL),
1516 mCurrentBufferp(NULL),
1517 mLoopedThisFrame(FALSE),
1518 mWaiting(FALSE)
1519{
1520}
1521
1522
1523LLAudioChannel::~LLAudioChannel()
1524{
1525 // Need to disconnect any sources which are using this channel.
1526 //llinfos << "Cleaning up audio channel" << llendl;
1527 if (mCurrentSourcep)
1528 {
1529 mCurrentSourcep->setChannel(NULL);
1530 }
1531 mCurrentBufferp = NULL;
1532}
1533
1534
1535void LLAudioChannel::setSource(LLAudioSource *sourcep)
1536{
1537 //llinfos << this << ": setSource(" << sourcep << ")" << llendl;
1538
1539 if (!sourcep)
1540 {
1541 // Clearing the source for this channel, don't need to do anything.
1542 //llinfos << "Clearing source for channel" << llendl;
1543 cleanup();
1544 mCurrentSourcep = NULL;
1545 mWaiting = FALSE;
1546 return;
1547 }
1548
1549 if (sourcep == mCurrentSourcep)
1550 {
1551 // Don't reallocate the channel, this will make FMOD goofy.
1552 //llinfos << "Calling setSource with same source!" << llendl;
1553 }
1554
1555 mCurrentSourcep = sourcep;
1556 updateBuffer();
1557 update3DPosition();
1558}
1559
1560
1561BOOL LLAudioChannel::updateBuffer()
1562{
1563 if (!mCurrentSourcep)
1564 {
1565 // This channel isn't associated with any source, nothing
1566 // to be updated
1567 return FALSE;
1568 }
1569
1570 LLAudioBuffer *bufferp = mCurrentSourcep->getCurrentBuffer();
1571 if (bufferp == mCurrentBufferp)
1572 {
1573 if (bufferp)
1574 {
1575 // The source hasn't changed what buffer it's playing
1576 bufferp->mLastUseTimer.reset();
1577 bufferp->mInUse = TRUE;
1578 }
1579 return FALSE;
1580 }
1581
1582 //
1583 // The source changed what buffer it's playing. Whe need to clean up the
1584 // existing fmod channel
1585 //
1586 cleanup();
1587
1588 mCurrentBufferp = bufferp;
1589 if (bufferp)
1590 {
1591 bufferp->mLastUseTimer.reset();
1592 bufferp->mInUse = TRUE;
1593 }
1594
1595 if (!mCurrentBufferp)
1596 {
1597 // There's no new buffer to be played, so we just abort.
1598 return FALSE;
1599 }
1600
1601 return TRUE;
1602}
1603
1604
1605
1606
1607//
1608// LLAudioData implementation
1609//
1610
1611
1612LLAudioData::LLAudioData(const LLUUID &uuid) :
1613 mID(uuid),
1614 mBufferp(NULL),
1615 mHasLocalData(FALSE),
1616 mHasDecodedData(FALSE),
1617 mHasValidData(TRUE)
1618{
1619 if (uuid.isNull())
1620 {
1621 // This is a null sound.
1622 return;
1623 }
1624
1625 if (gAudiop->hasDecodedFile(uuid))
1626 {
1627 // Already have a decoded version, don't need to decode it.
1628 mHasLocalData = TRUE;
1629 mHasDecodedData = TRUE;
1630 }
1631 else if (gAssetStorage->hasLocalAsset(uuid, LLAssetType::AT_SOUND))
1632 {
1633 mHasLocalData = TRUE;
1634 }
1635}
1636
1637
1638BOOL LLAudioData::load()
1639{
1640 // For now, just assume we're going to use one buffer per audiodata.
1641 if (mBufferp)
1642 {
1643 // We already have this sound in a buffer, don't do anything.
1644 llinfos << "Already have a buffer for this sound, don't bother loading!" << llendl;
1645 return TRUE;
1646 }
1647
1648 mBufferp = gAudiop->getFreeBuffer();
1649 if (!mBufferp)
1650 {
1651 // No free buffers, abort.
1652 llinfos << "Not able to allocate a new audio buffer, aborting." << llendl;
1653 return FALSE;
1654 }
1655
1656 char uuid_str[UUID_STR_LENGTH]; /*Flawfinder: ignore*/
1657 char wav_path[MAX_PATH]; /*Flawfinder: ignore*/
1658 mID.toString(uuid_str);
1659 snprintf(wav_path, MAX_PATH, "%s.dsf",gDirUtilp->getExpandedFilename(LL_PATH_CACHE,uuid_str).c_str()); /*Flawfinder: ignore*/
1660
1661 if (!mBufferp->loadWAV(wav_path))
1662 {
1663 // Hrm. Right now, let's unset the buffer, since it's empty.
1664 gAudiop->cleanupBuffer(mBufferp);
1665 mBufferp = NULL;
1666
1667 return FALSE;
1668 }
1669 mBufferp->mAudioDatap = this;
1670 return TRUE;
1671}
1672