PageRenderTime 142ms CodeModel.GetById 20ms app.highlight 111ms RepoModel.GetById 1ms app.codeStats 1ms

/indra/llaudio/llaudioengine.cpp

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