From b29b13ad98c5c79fd63bae10b4b099a03fa9dc35 Mon Sep 17 00:00:00 2001 From: Jacek Antonelli Date: Sat, 6 Dec 2008 14:03:10 -0600 Subject: Updated audio engine to LL's openal branch r1532. --- linden/indra/llaudio/audioengine.cpp | 184 ++++++- linden/indra/llaudio/audioengine.h | 56 +- linden/indra/llaudio/audioengine_openal.cpp | 767 ++++++++++------------------ linden/indra/llaudio/audioengine_openal.h | 107 ++-- linden/indra/newview/llaudiosourcevo.cpp | 2 +- linden/indra/newview/llpreviewsound.cpp | 3 +- linden/indra/newview/llstartup.cpp | 51 +- linden/indra/newview/llviewermessage.cpp | 3 +- linden/indra/newview/llviewertexteditor.cpp | 3 +- linden/indra/newview/llvoavatar.cpp | 11 +- 10 files changed, 549 insertions(+), 638 deletions(-) (limited to 'linden/indra') diff --git a/linden/indra/llaudio/audioengine.cpp b/linden/indra/llaudio/audioengine.cpp index 5fb38c0..239981b 100644 --- a/linden/indra/llaudio/audioengine.cpp +++ b/linden/indra/llaudio/audioengine.cpp @@ -51,9 +51,6 @@ extern void request_sound(const LLUUID &sound_guid); LLAudioEngine* gAudiop = NULL; -// Maximum amount of time we wait for a transfer to complete before starting -// off another one. -const F32 MAX_CURRENT_TRANSFER_TIME = 60.f; // // LLAudioEngine implementation @@ -77,7 +74,8 @@ void LLAudioEngine::setDefaults() mListenerp = NULL; - mMuted = FALSE; + mMuted = false; + mUserData = NULL; mLastStatus = 0; @@ -98,16 +96,20 @@ void LLAudioEngine::setDefaults() mInternetStreamGain = 0.125f; mNextWindUpdate = 0.f; + mInternetStreamMedia = NULL; + mInternetStreamURL.clear(); + for (U32 i = 0; i < LLAudioEngine::AUDIO_TYPE_COUNT; i++) mSecondaryGain[i] = 1.0f; } -BOOL LLAudioEngine::init(const S32 num_channels) +bool LLAudioEngine::init(const S32 num_channels, void* userdata) { setDefaults(); mNumChannels = num_channels; + mUserData = userdata; allocateListener(); @@ -126,6 +128,9 @@ void LLAudioEngine::shutdown() delete gAudioDecodeMgrp; gAudioDecodeMgrp = NULL; + // Clean up wind source + cleanupWind(); + // Clean up audio sources source_map::iterator iter_src; for (iter_src = mAllSources.begin(); iter_src != mAllSources.end(); iter_src++) @@ -146,22 +151,146 @@ void LLAudioEngine::shutdown() S32 i; for (i = 0; i < MAX_CHANNELS; i++) { - if (mChannels[i]) - { - delete mChannels[i]; - mChannels[i] = NULL; - } + delete mChannels[i]; + mChannels[i] = NULL; } // Clean up buffers for (i = 0; i < MAX_BUFFERS; i++) { - if (mBuffers[i]) + delete mBuffers[i]; + mBuffers[i] = NULL; + } + + delete mInternetStreamMedia; + mInternetStreamMedia = NULL; + mInternetStreamURL.clear(); +} + + +// virtual +void LLAudioEngine::startInternetStream(const std::string& url) +{ + llinfos << "entered startInternetStream()" << llendl; + + if (!mInternetStreamMedia) + { + LLMediaManager* mgr = LLMediaManager::getInstance(); + if (mgr) { - delete mBuffers[i]; - mBuffers[i] = NULL; + mInternetStreamMedia = mgr->createSourceFromMimeType(LLURI(url).scheme(), "audio/mpeg"); // assumes that whatever media implementation supports mp3 also supports vorbis. + llinfos << "mInternetStreamMedia is now " << mInternetStreamMedia << llendl; + } + } + + if(!mInternetStreamMedia) + return; + + if (!url.empty()) { + llinfos << "Starting internet stream: " << url << llendl; + mInternetStreamURL = url; + mInternetStreamMedia->navigateTo ( url ); + llinfos << "Playing....." << llendl; + mInternetStreamMedia->addCommand(LLMediaBase::COMMAND_START); + mInternetStreamMedia->updateMedia(); + } else { + llinfos << "setting stream to NULL"<< llendl; + mInternetStreamURL.clear(); + mInternetStreamMedia->addCommand(LLMediaBase::COMMAND_STOP); + mInternetStreamMedia->updateMedia(); + } + //#endif +} + +// virtual +void LLAudioEngine::stopInternetStream() +{ + llinfos << "entered stopInternetStream()" << llendl; + + if(mInternetStreamMedia) + { + if( ! mInternetStreamMedia->addCommand(LLMediaBase::COMMAND_STOP)){ + llinfos << "attempting to stop stream failed!" << llendl; + } + mInternetStreamMedia->updateMedia(); + } + + mInternetStreamURL.clear(); +} + +// virtual +void LLAudioEngine::pauseInternetStream(int pause) +{ + llinfos << "entered pauseInternetStream()" << llendl; + + if(!mInternetStreamMedia) + return; + + if(pause) + { + if(! mInternetStreamMedia->addCommand(LLMediaBase::COMMAND_PAUSE)) + { + llinfos << "attempting to pause stream failed!" << llendl; } + } else { + if(! mInternetStreamMedia->addCommand(LLMediaBase::COMMAND_START)) + { + llinfos << "attempting to unpause stream failed!" << llendl; + } + } + mInternetStreamMedia->updateMedia(); +} + +// virtual +void LLAudioEngine::updateInternetStream() +{ + if (mInternetStreamMedia) + mInternetStreamMedia->updateMedia(); +} + +// virtual +int LLAudioEngine::isInternetStreamPlaying() +{ + if (!mInternetStreamMedia) + return 0; + + if (mInternetStreamMedia->getStatus() == LLMediaBase::STATUS_STARTED) + { + return 1; // Active and playing + } + + if (mInternetStreamMedia->getStatus() == LLMediaBase::STATUS_PAUSED) + { + return 2; // paused } + + return 0; // Stopped +} + +// virtual +void LLAudioEngine::getInternetStreamInfo(char* artist, char* title) +{ + artist[0] = 0; + title[0] = 0; +} + +// virtual +void LLAudioEngine::setInternetStreamGain(F32 vol) +{ + mInternetStreamGain = vol; + + if(!mInternetStreamMedia) + return; + + vol = llclamp(vol, 0.f, 1.f); + mInternetStreamMedia->setVolume(vol); + mInternetStreamMedia->updateMedia(); +} + +// virtual +const std::string& LLAudioEngine::getInternetStreamURL() +{ + return mInternetStreamURL; } @@ -449,6 +578,8 @@ void LLAudioEngine::idle(F32 max_decode_time) // missed picking it up in all the places that can add // or request new data. startNextTransfer(); + + updateInternetStream(); } @@ -758,7 +889,7 @@ void LLAudioEngine::triggerSound(const LLUUID &audio_uuid, const LLUUID& owner_i LLUUID source_id; source_id.generate(); - LLAudioSource *asp = new LLAudioSource(source_id, owner_id, gain); + LLAudioSource *asp = new LLAudioSource(source_id, owner_id, gain, type); gAudiop->addAudioSource(asp); if (pos_global.isExactlyZero()) { @@ -1207,18 +1338,18 @@ void LLAudioEngine::assetCallback(LLVFS *vfs, const LLUUID &uuid, LLAssetType::E // -LLAudioSource::LLAudioSource(const LLUUID& id, const LLUUID& owner_id, const F32 gain) +LLAudioSource::LLAudioSource(const LLUUID& id, const LLUUID& owner_id, const F32 gain, const S32 type) : mID(id), mOwnerID(owner_id), mPriority(0.f), mGain(gain), mType(type), - mAmbient(FALSE), - mLoop(FALSE), - mSyncMaster(FALSE), - mSyncSlave(FALSE), - mQueueSounds(FALSE), - mPlayedOnce(FALSE), + mAmbient(false), + mLoop(false), + mSyncMaster(false), + mSyncSlave(false), + mQueueSounds(false), + mPlayedOnce(false), mChannelp(NULL), mCurrentDatap(NULL), mQueuedDatap(NULL) @@ -1364,7 +1495,8 @@ bool LLAudioSource::play(const LLUUID &audio_uuid) bool LLAudioSource::isDone() { const F32 MAX_AGE = 60.f; - const F32 MAX_UNPLAYED_AGE = 30.f; + const F32 MAX_UNPLAYED_AGE = 15.f; + if (isLoop()) { // Looped sources never die on their own. @@ -1542,8 +1674,8 @@ LLAudioBuffer *LLAudioSource::getCurrentBuffer() LLAudioChannel::LLAudioChannel() : mCurrentSourcep(NULL), mCurrentBufferp(NULL), - mLoopedThisFrame(FALSE), - mWaiting(FALSE), + mLoopedThisFrame(false), + mWaiting(false), mSecondaryGain(1.0f) { } @@ -1609,8 +1741,8 @@ bool LLAudioChannel::updateBuffer() } // - // The source changed what buffer it's playing. Whe need to clean up the - // existing fmod channel + // The source changed what buffer it's playing. We need to clean up + // the existing channel // cleanup(); diff --git a/linden/indra/llaudio/audioengine.h b/linden/indra/llaudio/audioengine.h index 937a8e1..aff7759 100644 --- a/linden/indra/llaudio/audioengine.h +++ b/linden/indra/llaudio/audioengine.h @@ -69,6 +69,7 @@ class LLVFS; class LLAudioSource; class LLAudioData; class LLAudioChannel; +class LLAudioChannelOpenAL; class LLAudioBuffer; @@ -79,8 +80,10 @@ class LLAudioBuffer; class LLAudioEngine { + friend class LLAudioChannelOpenAL; // bleh. channel needs some listener methods. + public: - enum LLAudioType + typedef enum LLAudioType { AUDIO_TYPE_NONE = 0, AUDIO_TYPE_SFX = 1, @@ -93,9 +96,7 @@ public: virtual ~LLAudioEngine(); // initialization/startup/shutdown - //virtual BOOL init(); - - virtual BOOL init(const S32 num_channels); + virtual bool init(const S32 num_channels, void *userdata); virtual std::string getDriverName(bool verbose) = 0; virtual void shutdown(); @@ -140,7 +141,7 @@ public: void triggerSound(const LLUUID &sound_id, const LLUUID& owner_id, const F32 gain, const S32 type = LLAudioEngine::AUDIO_TYPE_NONE, const LLVector3d &pos_global = LLVector3d::zero); - BOOL preloadSound(const LLUUID &id); + bool preloadSound(const LLUUID &id); void addAudioSource(LLAudioSource *asp); void cleanupAudioSource(LLAudioSource *asp); @@ -149,15 +150,16 @@ public: LLAudioData *getAudioData(const LLUUID &audio_uuid); - virtual void startInternetStream(const std::string& url) = 0; - virtual void stopInternetStream() = 0; - virtual void pauseInternetStream(int pause) = 0; - virtual int isInternetStreamPlaying() = 0; - virtual void getInternetStreamInfo(char* artist, char* title) { artist[0] = 0; title[0] = 0; } + // Internet stream methods + virtual void startInternetStream(const std::string& url); + virtual void stopInternetStream(); + virtual void pauseInternetStream(int pause); + virtual void updateInternetStream(); + virtual int isInternetStreamPlaying(); + virtual void getInternetStreamInfo(char* artist, char* title); // use a value from 0.0 to 1.0, inclusive - virtual void setInternetStreamGain(F32 vol) { mInternetStreamGain = vol; } - virtual const std::string& getInternetStreamURL() { return LLStringUtil::null; } - virtual void InitStreamer() = 0; + virtual void setInternetStreamGain(F32 vol); + virtual const std::string& getInternetStreamURL(); // For debugging usage virtual LLVector3 getListenerPos(); @@ -193,11 +195,6 @@ protected: virtual void allocateListener() = 0; - // Internet stream methods - virtual void initInternetStream() {} - virtual void updateInternetStream() {} - - // listener methods virtual void setListenerPos(LLVector3 vec); virtual void setListenerVelocity(LLVector3 vec); @@ -212,7 +209,8 @@ protected: protected: LLListener *mListenerp; - BOOL mMuted; + bool mMuted; + void* mUserData; S32 mLastStatus; @@ -242,6 +240,7 @@ protected: // Hack! Internet streams are treated differently from other sources! F32 mInternetStreamGain; + std::string mInternetStreamURL; F32 mNextWindUpdate; @@ -249,6 +248,7 @@ protected: private: void setDefaults(); + LLMediaBase *mInternetStreamMedia; }; @@ -264,7 +264,7 @@ class LLAudioSource public: // owner_id is the id of the agent responsible for making this sound // play, for example, the owner of the object currently playing it - LLAudioSource(const LLUUID &id, const LLUUID& owner_id, const F32 gain); + LLAudioSource(const LLUUID &id, const LLUUID& owner_id, const F32 gain, const S32 type = LLAudioEngine::AUDIO_TYPE_NONE); virtual ~LLAudioSource(); virtual void update(); // Update this audio source @@ -326,12 +326,12 @@ protected: LLUUID mOwnerID; // owner of the object playing the sound F32 mPriority; F32 mGain; - BOOL mAmbient; - BOOL mLoop; - BOOL mSyncMaster; - BOOL mSyncSlave; - BOOL mQueueSounds; - BOOL mPlayedOnce; + bool mAmbient; + bool mLoop; + bool mSyncMaster; + bool mSyncSlave; + bool mQueueSounds; + bool mPlayedOnce; S32 mType; LLVector3d mPositionGlobal; LLVector3 mVelocity; @@ -420,8 +420,8 @@ protected: protected: LLAudioSource *mCurrentSourcep; LLAudioBuffer *mCurrentBufferp; - BOOL mLoopedThisFrame; - BOOL mWaiting; // Waiting for sync. + bool mLoopedThisFrame; + bool mWaiting; // Waiting for sync. F32 mSecondaryGain; }; diff --git a/linden/indra/llaudio/audioengine_openal.cpp b/linden/indra/llaudio/audioengine_openal.cpp index 65203dd..002dfba 100644 --- a/linden/indra/llaudio/audioengine_openal.cpp +++ b/linden/indra/llaudio/audioengine_openal.cpp @@ -4,26 +4,26 @@ * support as a OpenAL 3D implementation * * $LicenseInfo:firstyear=2002&license=viewergpl$ - * + * * Copyright (c) 2002-2008, Linden Research, Inc. - * + * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement * ("Other License"), formally executed by you and Linden Lab. Terms of * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlife.com/developers/opensource/gplv2 - * + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * * There are special exceptions to the terms and conditions of the GPL as * it is applied to this Source Code. View the full text of the exception * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at http://secondlife.com/developers/opensource/flossexception - * + * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception + * * By copying, modifying or distributing this software, you acknowledge * that you have read and understood your obligations described above, * and agree to abide by those obligations. - * + * * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, * COMPLETENESS OR PERFORMANCE. @@ -36,31 +36,29 @@ #include "audioengine_openal.h" #include "listener_openal.h" + LLAudioEngine_OpenAL::LLAudioEngine_OpenAL() + : + mWindGen(NULL), + mWindBuf(NULL), + mWindBufFreq(0), + mWindBufSamples(0), + mWindBufBytes(0), + mWindSource(AL_NONE), + mNumEmptyWindALBuffers(MAX_NUM_WIND_BUFFERS) { - - #if LL_GSTREAMER_ENABLED - mMedia_data = new LLMediaManagerData; - // initialize GStreamer - LLMediaImplGStreamer::startup( mMedia_data ); - - m_streamer=new LLMediaImplGStreamer (); - - if(!m_streamer) - { - llwarns << "LLAudioEngine_OpenAL::LLAudioEngine_OpenAL() Failed to create our private gstreamer audio instance" << llendl; - } - #endif } +// virtual LLAudioEngine_OpenAL::~LLAudioEngine_OpenAL() { } - -BOOL LLAudioEngine_OpenAL::init(const S32 num_channels) +// virtual +bool LLAudioEngine_OpenAL::init(const S32 num_channels, void* userdata) { - LLAudioEngine::init(num_channels); + mWindGen = NULL; + LLAudioEngine::init(num_channels, userdata); if(!alutInit(NULL, NULL)) { @@ -68,27 +66,39 @@ BOOL LLAudioEngine_OpenAL::init(const S32 num_channels) return false; } - initInternetStream(); - llinfos << "LLAudioEngine_OpenAL::init() OpenAL successfully initialized" << llendl; - llinfos << "LLAudioEngine_OpenAL::init() Speed of sound is: " << alGetFloat(AL_SPEED_OF_SOUND) << llendl; + llinfos << "OpenAL version: " + << ll_safe_string(alGetString(AL_VERSION)) << llendl; + llinfos << "OpenAL vendor: " + << ll_safe_string(alGetString(AL_VENDOR)) << llendl; + llinfos << "OpenAL renderer: " + << ll_safe_string(alGetString(AL_RENDERER)) << llendl; + + ALint major = alutGetMajorVersion (); + ALint minor = alutGetMinorVersion (); + llinfos << "ALUT version: " << major << "." << minor << llendl; - return TRUE; + ALCdevice *device = alcGetContextsDevice(alcGetCurrentContext()); + + alcGetIntegerv(device, ALC_MAJOR_VERSION, 1, &major); + alcGetIntegerv(device, ALC_MAJOR_VERSION, 1, &minor); + llinfos << "ALC version: " << major << "." << minor << llendl; + + llinfos << "ALC default device: " + << ll_safe_string(alcGetString(device, + ALC_DEFAULT_DEVICE_SPECIFIER)) + << llendl; + + return true; } +// virtual std::string LLAudioEngine_OpenAL::getDriverName(bool verbose) { ALCdevice *device = alcGetContextsDevice(alcGetCurrentContext()); - std::ostringstream version; - ALint major = alutGetMajorVersion (); - ALint minor = alutGetMinorVersion (); - - alcGetIntegerv(device, ALC_MAJOR_VERSION, 1, &major); - alcGetIntegerv(device, ALC_MAJOR_VERSION, 1, &minor); - version << "OpenAL"; @@ -112,17 +122,7 @@ std::string LLAudioEngine_OpenAL::getDriverName(bool verbose) return version.str(); } - -void LLAudioEngine_OpenAL::idle(F32 max_decode_time) -{ - LLAudioEngine::idle(max_decode_time); - #if LL_GSTREAMER_ENABLED - if(m_streamer != NULL) - m_streamer->updateMedia(); - #endif -} - - +// virtual void LLAudioEngine_OpenAL::allocateListener() { mListenerp = (LLListener *) new LLListener_OpenAL(); @@ -132,6 +132,7 @@ void LLAudioEngine_OpenAL::allocateListener() } } +// virtual void LLAudioEngine_OpenAL::shutdown() { llinfos << "About to LLAudioEngine::shutdown()" << llendl; @@ -143,21 +144,11 @@ void LLAudioEngine_OpenAL::shutdown() llwarns << "Nuts." << llendl; llwarns << "LLAudioEngine_OpenAL::shutdown() ALUT shutdown failed: " << alutGetErrorString (alutGetError ()) << llendl; } - else - { - llinfos << "LLAudioEngine_OpenAL::shutdown() OpenAL successfully shut down" << llendl; - } - + + llinfos << "LLAudioEngine_OpenAL::shutdown() OpenAL successfully shut down" << llendl; + delete mListenerp; mListenerp = NULL; - - #if LL_GSTREAMER_ENABLED - if(m_streamer) - { - delete m_streamer; - m_streamer = NULL; - } - #endif } LLAudioBuffer *LLAudioEngine_OpenAL::createBuffer() @@ -177,44 +168,75 @@ void LLAudioEngine_OpenAL::setInternalGain(F32 gain) } LLAudioChannelOpenAL::LLAudioChannelOpenAL() + : + mALSource(AL_NONE), + mLastSamplePos(0) { - alGenSources(1, &ALSource); + alGenSources(1, &mALSource); } LLAudioChannelOpenAL::~LLAudioChannelOpenAL() { cleanup(); - alDeleteSources(1, &ALSource); + alDeleteSources(1, &mALSource); } void LLAudioChannelOpenAL::cleanup() { - alSourceStop(ALSource); + alSourceStop(mALSource); mCurrentBufferp = NULL; } void LLAudioChannelOpenAL::play() { + if (mALSource == AL_NONE) + { + llwarns << "Playing without a mALSource, aborting" << llendl; + return; + } + if(!isPlaying()) { - alSourcePlay(ALSource); - getSource()->setPlayedOnce(TRUE); + alSourcePlay(mALSource); + getSource()->setPlayedOnce(true); } } void LLAudioChannelOpenAL::playSynced(LLAudioChannel *channelp) { + if (channelp) + { + LLAudioChannelOpenAL *masterchannelp = + (LLAudioChannelOpenAL*)channelp; + if (mALSource != AL_NONE && + masterchannelp->mALSource != AL_NONE) + { + // we have channels allocated to master and slave + ALfloat master_offset; + alGetSourcef(masterchannelp->mALSource, AL_SEC_OFFSET, + &master_offset); + + llinfos << "Syncing with master at " << master_offset + << "sec" << llendl; + // *TODO: detect when this fails, maybe use AL_SAMPLE_ + alSourcef(mALSource, AL_SEC_OFFSET, master_offset); + } + } play(); } bool LLAudioChannelOpenAL::isPlaying() { - ALint state; - alGetSourcei(ALSource, AL_SOURCE_STATE, &state); - if(state == AL_PLAYING) + if (mALSource != AL_NONE) { - return TRUE; + ALint state; + alGetSourcei(mALSource, AL_SOURCE_STATE, &state); + if(state == AL_PLAYING) + { + return true; + } } + return false; } @@ -225,14 +247,48 @@ bool LLAudioChannelOpenAL::updateBuffer() // Base class update returned true, which means that we need to actually // set up the source for a different buffer. LLAudioBufferOpenAL *bufferp = (LLAudioBufferOpenAL *)mCurrentSourcep->getCurrentBuffer(); - alSourcei(ALSource, AL_BUFFER, bufferp->getBuffer()); - alSourcef(ALSource, AL_GAIN, mCurrentSourcep->getGain()); - alSourcei(ALSource, AL_LOOPING, mCurrentSourcep->isLoop() ? AL_TRUE : AL_FALSE); + ALuint buffer = bufferp->getBuffer(); + alSourcei(mALSource, AL_BUFFER, buffer); + mLastSamplePos = 0; + } + + if (mCurrentSourcep) + { + alSourcef(mALSource, AL_GAIN, + mCurrentSourcep->getGain() * getSecondaryGain()); + alSourcei(mALSource, AL_LOOPING, + mCurrentSourcep->isLoop() ? AL_TRUE : AL_FALSE); + alSourcef(mALSource, AL_ROLLOFF_FACTOR, + gAudiop->mListenerp->getRolloffFactor()); + alSourcef(mALSource, AL_REFERENCE_DISTANCE, + gAudiop->mListenerp->getDistanceFactor()); } return true; } + +void LLAudioChannelOpenAL::updateLoop() +{ + if (mALSource == AL_NONE) + { + return; + } + + // Hack: We keep track of whether we looped or not by seeing when the + // sample position looks like it's going backwards. Not reliable; may + // yield false negatives. + // + ALint cur_pos; + alGetSourcei(mALSource, AL_SAMPLE_OFFSET, &cur_pos); + if (cur_pos < mLastSamplePos) + { + mLoopedThisFrame = true; + } + mLastSamplePos = cur_pos; +} + + void LLAudioChannelOpenAL::update3DPosition() { if(!mCurrentSourcep) @@ -241,30 +297,25 @@ void LLAudioChannelOpenAL::update3DPosition() } if (mCurrentSourcep->isAmbient()) { - alSource3f(ALSource, AL_POSITION, 0.0, 0.0, 0.0); - alSource3f(ALSource, AL_VELOCITY, 0.0, 0.0, 0.0); - //alSource3f(ALSource, AL_DIRECTION, 0.0, 0.0, 0.0); - alSourcef (ALSource, AL_ROLLOFF_FACTOR, 0.0); - alSourcei (ALSource, AL_SOURCE_RELATIVE, AL_TRUE); - } - else - { + alSource3f(mALSource, AL_POSITION, 0.0, 0.0, 0.0); + alSource3f(mALSource, AL_VELOCITY, 0.0, 0.0, 0.0); + //alSource3f(mALSource, AL_DIRECTION, 0.0, 0.0, 0.0); + alSourcei (mALSource, AL_SOURCE_RELATIVE, AL_TRUE); + } else { LLVector3 float_pos; float_pos.setVec(mCurrentSourcep->getPositionGlobal()); - alSourcefv(ALSource, AL_POSITION, float_pos.mV); - //llinfos << "LLAudioChannelOpenAL::update3DPosition() Velocity: " << mCurrentSourcep->getVelocity() << llendl; - alSourcefv(ALSource, AL_VELOCITY, mCurrentSourcep->getVelocity().mV); - //alSource3f(ALSource, AL_DIRECTION, 0.0, 0.0, 0.0); - alSourcef (ALSource, AL_ROLLOFF_FACTOR, 1.0); - alSourcei (ALSource, AL_SOURCE_RELATIVE, AL_FALSE); + alSourcefv(mALSource, AL_POSITION, float_pos.mV); + alSourcefv(mALSource, AL_VELOCITY, mCurrentSourcep->getVelocity().mV); + //alSource3f(mALSource, AL_DIRECTION, 0.0, 0.0, 0.0); + alSourcei (mALSource, AL_SOURCE_RELATIVE, AL_FALSE); } - //llinfos << "LLAudioChannelOpenAL::update3DPosition() Gain: " << mCurrentSourcep->getGain() << llendl; - alSourcef(ALSource, AL_GAIN, mCurrentSourcep->getGain()); + + alSourcef(mALSource, AL_GAIN, mCurrentSourcep->getGain() * getSecondaryGain()); } LLAudioBufferOpenAL::LLAudioBufferOpenAL() { - ALBuffer = AL_NONE; + mALBuffer = AL_NONE; } LLAudioBufferOpenAL::~LLAudioBufferOpenAL() @@ -274,33 +325,49 @@ LLAudioBufferOpenAL::~LLAudioBufferOpenAL() void LLAudioBufferOpenAL::cleanup() { - if(ALBuffer != AL_NONE) + if(mALBuffer != AL_NONE) { - alDeleteBuffers(1, &ALBuffer); + alDeleteBuffers(1, &mALBuffer); + mALBuffer = AL_NONE; } } bool LLAudioBufferOpenAL::loadWAV(const std::string& filename) { cleanup(); - ALBuffer = alutCreateBufferFromFile(filename.c_str()); - if(ALBuffer == AL_NONE) + mALBuffer = alutCreateBufferFromFile(filename.c_str()); + if(mALBuffer == AL_NONE) { - return FALSE; + ALenum error = alutGetError(); + if (gDirUtilp->fileExists(filename)) + { + llwarns << + "LLAudioBufferOpenAL::loadWAV() Error loading " + << filename + << " " << alutGetErrorString(error) << llendl; + } + else + { + // It's common for the file to not actually exist. + lldebugs << + "LLAudioBufferOpenAL::loadWAV() Error loading " + << filename + << " " << alutGetErrorString(error) << llendl; + } + return false; } return true; } - U32 LLAudioBufferOpenAL::getLength() { - if(ALBuffer == AL_NONE) + if(mALBuffer == AL_NONE) { return 0; } ALint length; - alGetBufferi(ALBuffer, AL_SIZE, &length); + alGetBufferi(mALBuffer, AL_SIZE, &length); return length >> 2; } @@ -308,65 +375,78 @@ U32 LLAudioBufferOpenAL::getLength() void LLAudioEngine_OpenAL::initWind() { + ALenum error; + llinfos << "LLAudioEngine_OpenAL::initWind() start" << llendl; - if (true) - return; - - llinfos << "initWind() start" << llendl; + mNumEmptyWindALBuffers = MAX_NUM_WIND_BUFFERS; - alGenBuffers(mNumWindBuffers,mWindBuffers); + alGetError(); /* clear error */ + alGenSources(1,&mWindSource); - checkALError(); - - // ok lets make a wind buffer now - for(int counter=0;counter; - alSourcePlay(mWindSource); - checkALError(); + mWindBufFreq = mWindGen->getInputSamplingRate(); + mWindBufSamples = llceil(mWindBufFreq * WIND_BUFFER_SIZE_SEC); + mWindBufBytes = mWindBufSamples * 2 /*stereo*/ * sizeof(WIND_SAMPLE_T); - llinfos << "LLAudioEngine_OpenAL::initWind() done" << llendl; + mWindBuf = new WIND_SAMPLE_T [mWindBufSamples * 2 /*stereo*/]; + if(mWindBuf==NULL) + { + llerrs << "LLAudioEngine_OpenAL::initWind() Error creating wind memory buffer" << llendl; + mEnableWind=false; + } + + llinfos << "LLAudioEngine_OpenAL::initWind() done" << llendl; } -void LLAudioEngine_OpenAL::cleanupWind(){ +void LLAudioEngine_OpenAL::cleanupWind() +{ llinfos << "LLAudioEngine_OpenAL::cleanupWind()" << llendl; - alDeleteBuffers(mNumWindBuffers,mWindBuffers); - alDeleteSources(1, &mWindSource); + if (mWindSource != AL_NONE) + { + // detach and delete all outstanding buffers on the wind source + alSourceStop(mWindSource); + int processed; + alGetSourcei(mWindSource, AL_BUFFERS_PROCESSED, &processed); + while (processed--) + { + ALuint buffer = AL_NONE; + alSourceUnqueueBuffers(mWindSource, 1, &buffer); + alDeleteBuffers(1, &buffer); + } - checkALError(); -} + // delete the wind source itself + alDeleteSources(1, &mWindSource); -void LLAudioEngine_OpenAL::checkALError() -{ - ALenum error; - if((error=alGetError()) != AL_NO_ERROR) - llwarns << "LLAudioEngine_OpenAL Error: "<getPosition().mV[0],mListenerp->getPosition().mV[1],mListenerp->getPosition().mV[2]}; - ALfloat source0Vel[]={ 0.0, 0.0, 0.0}; - - alSourcef(mWindSource, AL_GAIN, mTargetGain); - alSourcef(mWindSource, AL_PITCH, pitch); - alSourcefv(mWindSource, AL_POSITION, source0Pos); - alSourcefv(mWindSource, AL_VELOCITY, source0Vel); + + pitch = 1.0 + mapWindVecToPitch(wind_vec); + center_freq = 80.0 * pow(pitch,2.5*(mapWindVecToGain(wind_vec)+1.0)); + + mWindGen->mTargetFreq = (F32)center_freq; + mWindGen->mTargetGain = (F32)mapWindVecToGain(wind_vec) * mMaxWindGain; + mWindGen->mTargetPanGainR = (F32)mapWindVecToPan(wind_vec); + alSourcei(mWindSource, AL_LOOPING, AL_FALSE); - - } - - int processed; - alGetSourcei(mWindSource, AL_BUFFERS_PROCESSED, &processed); - - while(processed--) - { - ALuint buffer; - alSourceUnqueueBuffers(mWindSource, 1, &buffer); - checkALError(); - alBufferData(buffer,AL_FORMAT_STEREO16,windDSP((void*)mWindData,mWindDataSize/mBytesPerSample),mWindDataSize,mSampleRate); - checkALError(); - alSourceQueueBuffers(mWindSource, 1, &buffer); - checkALError(); + alSource3f(mWindSource, AL_POSITION, 0.0, 0.0, 0.0); + alSource3f(mWindSource, AL_VELOCITY, 0.0, 0.0, 0.0); + alSourcef(mWindSource, AL_ROLLOFF_FACTOR, 0.0); + alSourcei(mWindSource, AL_SOURCE_RELATIVE, AL_TRUE); } - int playing; - alGetSourcei(mWindSource, AL_SOURCE_STATE, &playing); - if(playing==AL_STOPPED) - alSourcePlay(mWindSource); - - checkALError(); -} - - -void * LLAudioEngine_OpenAL::windDSP(void *newbuffer, int length) -{ - // *NOTE: This function gets called a *lot*. - // Keep performance in mind if you mess with this. - // newbuffer = the buffer being constructed - // length = length in samples of the buffer - - - //clear the buffer - memset(newbuffer, 0, length*mBytesPerSample); - - // This turns off wind synth if it is muted or very very low volume - if (mTargetGain < 0.0005f) - { - llinfos << "Wind off" << llendl; - return newbuffer; - } - - static const U8 SUBSAMPLES = 2; - static const F32 FILTER_SAMPLE_PERIOD = (F32)SUBSAMPLES / float(mSampleRate); - static const F32 BANDWIDTH = 50.0f; - static const F32 B2 = expf(-F_TWO_PI * BANDWIDTH * FILTER_SAMPLE_PERIOD); - - static F32 pinking_buf0 = 0.0f; - static F32 pinking_buf1 = 0.0f; - static F32 pinking_buf2 = 0.0f; - static F32 Y0 = 0.0f; - static F32 Y1 = 0.0f; - static F32 last_sample = 0.0f; - static F32 current_freq = 0.0f; - static F32 current_gain = 0.0f; - static F32 current_pan_gain_r = 0.0f; - - F32 a0 = 0.0f, b1 = 0.0f; - - U8 *cursamplep = (U8*)newbuffer; - - //we assume 16-bit samples, because the ALUT specification maxes out there - U8 wordsize = 2; - - bool interp_freq = false; - - //if the frequency isn't changing much, we don't need to interpolate in the inner loop - if (llabs(mTargetFreq - current_freq) > 200.0f) - { - interp_freq = true; - } - else - { - // calculate resonant filter coefficients - current_freq = mTargetFreq; - b1 = (-4.0f * B2) / (1.0f + B2) * cosf(F_TWO_PI * (current_freq * FILTER_SAMPLE_PERIOD)); - a0 = (1.0f - B2) * sqrtf(1.0f - (b1 * b1) / (4.0f * B2)); - } - - while (length) - { - F32 next_sample; - - // Start with white noise [-16384, 16383] - next_sample = (F32)rand() * (1.0f / (F32)(RAND_MAX / (U16_MAX / 4))) + (S16_MIN / 4); - - // Apply a pinking filter - // Magic numbers taken from PKE method at http://www.firstpr.com.au/dsp/pink-noise/ - pinking_buf0 = pinking_buf0 * 0.99765f + next_sample * 0.0990460f; - pinking_buf1 = pinking_buf1 * 0.96300f + next_sample * 0.2965164f; - pinking_buf2 = pinking_buf2 * 0.57000f + next_sample * 1.0526913f; - - next_sample = pinking_buf0 + pinking_buf1 + pinking_buf2 + next_sample * 0.1848f; - - if (interp_freq) - { - // calculate resonant filter coefficients - current_freq = (0.999f * current_freq) + (0.001f * mTargetFreq); - b1 = (-4.0f * B2) / (1.0f + B2) * cosf(F_TWO_PI * (current_freq * FILTER_SAMPLE_PERIOD)); - a0 = (1.0f - B2) * sqrtf(1.0f - (b1 * b1) / (4.0f * B2)); - } - - // Apply a resonant low-pass filter on the pink noise - next_sample = ( a0 * next_sample - b1 * Y0 - B2 * Y1 ); - - Y1 = Y0; - Y0 = next_sample; - - current_gain = (0.999f * current_gain) + (0.001f * mTargetGain); - current_pan_gain_r = (0.999f * current_pan_gain_r) + (0.001f * mTargetPanGainR); - - next_sample *= current_gain; - F32 delta = (next_sample - last_sample) / (F32)SUBSAMPLES; - - S32 sample_left; - S32 sample_right; - - // Mix into the audio buffer, clipping if necessary for 16-bit mix buffers. - // *TODO: Should do something more intelligent like reducing wind gain to avoid clipping - for (int i=SUBSAMPLES; i && length; --i, --length) - { - last_sample = last_sample + delta; - sample_right = (S32)(last_sample * current_pan_gain_r); - sample_left = (S32)(last_sample - sample_right); - - *(S16*)cursamplep = llclamp(sample_left, S16_MIN, S16_MAX); - cursamplep += wordsize; - - *(S16*)cursamplep = llclamp(sample_right, S16_MIN, S16_MAX); - cursamplep += wordsize; - } - } - return newbuffer; - -} - - - - -/* - - - - - // newbuffer = the buffer passed from the previous DSP unit. - // length = length in samples at this mix time. - - U8 *cursamplep = (U8*)newbuffer; - U8 wordsize = 2; - - double bandwidth = 50; - double inputSamplingRate = 44100; - double a0,b1,b2; - - // calculate resonant filter coeffs - b2 = exp(-(F_TWO_PI) * (bandwidth / inputSamplingRate)); - - while (length--) - { - gCurrentFreq = (float)((0.999 * gCurrentFreq) + (0.001 * gTargetFreq)); - gCurrentGain = (float)((0.999 * gCurrentGain) + (0.001 * gTargetGain)); - gCurrentPanGainR = (float)((0.999 * gCurrentPanGainR) + (0.001 * gTargetPanGainR)); - b1 = (-4.0 * b2) / (1.0 + b2) * cos(F_TWO_PI * (gCurrentFreq / inputSamplingRate)); - a0 = (1.0 - b2) * sqrt(1.0 - (b1 * b1) / (4.0 * b2)); - double nextSample; - - // start with white noise - nextSample = ll_frand(2.0f) - 1.0f; - - gbuf0 = 0.997f * gbuf0 + 0.0126502f * nextSample; - gbuf1 = 0.985f * gbuf1 + 0.0139083f * nextSample; - gbuf2 = 0.950f * gbuf2 + 0.0205439f * nextSample; - gbuf3 = 0.850f * gbuf3 + 0.0387225f * nextSample; - gbuf4 = 0.620f * gbuf4 + 0.0465932f * nextSample; - gbuf5 = 0.250f * gbuf5 + 0.1093477f * nextSample; - - nextSample = gbuf0 + gbuf1 + gbuf2 + gbuf3 + gbuf4 + gbuf5; - - nextSample = (double)( a0 * nextSample - b1 * gY0 - b2 * gY1 ); - - gY1 = gY0; - gY0 = nextSample; - nextSample *= gCurrentGain; - - S16 sample; - - sample = llfloor(((F32)nextSample*32768.f*(1.0f - gCurrentPanGainR))+0.5f); - *(S16*)cursamplep = clipSample(sample, -32768, 32767); - - cursamplep += wordsize; - - sample = llfloor(((F32)nextSample*32768.f*gCurrentPanGainR)+0.5f); - - sample = llfloor(((F32)nextSample*32768.f*gCurrentPanGainR)+0.5f); - *(S16*)cursamplep = clipSample(sample, -32768, 32767); - cursamplep += wordsize; - } - - return newbuffer; -} -*/ - -// ------------ - -void LLAudioEngine_OpenAL::InitStreamer() -{ - #if LL_GSTREAMER_ENABLED - m_streamer=new LLMediaImplGStreamer (); - - if(!m_streamer) - { - llwarns << "LLAudioEngine_OpenAL::LLAudioEngine_OpenAL() Failed to create our private gstreamer audio instance" << llendl; - } - - if(m_streamer) - { - m_streamer->init (); - } - #endif -} - - -// ------------ - -void LLAudioEngine_OpenAL::initInternetStream() -{ - if(!mInternetStreamURL.empty()) - mInternetStreamURL.erase(); -} - - -void LLAudioEngine_OpenAL::startInternetStream(const std::string& url_cstr) -{ - - std::string url(url_cstr); - - #if LL_GSTREAMER_ENABLED - if(!m_streamer) - return; - // DCF_DEBUG - llinfos << "entered LLAudioEngine_OpenAL::startInternetStream()" << llendl; - - if (!url.empty()) - { - llinfos << "LLAudioEngine_OpenAL::startInternetStream() Starting internet stream: " << url << llendl; - mInternetStreamURL=url; - m_streamer->navigateTo ( url ); - llinfos << "Playing....." << llendl; - m_streamer->addCommand(LLMediaBase::COMMAND_START); - m_streamer->updateMedia(); - - } - else - { - llinfos << "LLAudioEngine_OpenAL setting stream to NULL"<< llendl; - mInternetStreamURL.erase(); - m_streamer->addCommand(LLMediaBase::COMMAND_STOP); - m_streamer->updateMedia(); - } - #endif -} - - -void LLAudioEngine_OpenAL::updateInternetStream() -{ - // DCF_DEBUG - llinfos << "entered LLAudioEngine_OpenAL::updateInternetStream()" << llendl; - -} - - -void LLAudioEngine_OpenAL::stopInternetStream() -{ - // DCF_DEBUG - llinfos << "entered LLAudioEngine_OpenAL::stopInternetStream()" << llendl; + // ok lets make a wind buffer now - #if LL_GSTREAMER_ENABLED - if( ! m_streamer->addCommand(LLMediaBase::COMMAND_STOP)) - { - llinfos << "attempting to stop stream failed!" << llendl; - } - m_streamer->updateMedia(); - #endif - mInternetStreamURL.erase(); -} + int processed, queued, unprocessed; + alGetSourcei(mWindSource, AL_BUFFERS_PROCESSED, &processed); + alGetSourcei(mWindSource, AL_BUFFERS_QUEUED, &queued); + unprocessed = queued - processed; + // ensure that there are always at least 3x as many filled buffers + // queued as we managed to empty since last time. + mNumEmptyWindALBuffers = llmin(mNumEmptyWindALBuffers + processed * 3 - unprocessed, MAX_NUM_WIND_BUFFERS-unprocessed); + mNumEmptyWindALBuffers = llmax(mNumEmptyWindALBuffers, 0); -void LLAudioEngine_OpenAL::pauseInternetStream(int pause) -{ - #if LL_GSTREAMER_ENABLED - if(!m_streamer) - return; - // DCF_DEBUG - llinfos << "entered LLAudioEngine_OpenAL::pauseInternetStream()" << llendl; + //llinfos << "mNumEmptyWindALBuffers: " << mNumEmptyWindALBuffers <<" (" << unprocessed << ":" << processed << ")" << llendl; - if(pause) + while(processed--) // unqueue old buffers { - if(!m_streamer->addCommand(LLMediaBase::COMMAND_PAUSE)) + ALuint buffer; + int error; + alGetError(); /* clear error */ + alSourceUnqueueBuffers(mWindSource, 1, &buffer); + error = alGetError(); + if(error != AL_NO_ERROR) { - llinfos << "attempting to pause stream failed!" << llendl; + llwarns << "LLAudioEngine_OpenAL::updateWind() error swapping (unqueuing) buffers" << llendl; } - m_streamer->updateMedia(); - } - else - { - if( ! m_streamer->addCommand(LLMediaBase::COMMAND_START)) + else { - llinfos << "attempting to pause stream failed!" << llendl; + alDeleteBuffers(1, &buffer); } - m_streamer->updateMedia(); } - #endif -} - -int LLAudioEngine_OpenAL::isInternetStreamPlaying() -{ + unprocessed += mNumEmptyWindALBuffers; + while (mNumEmptyWindALBuffers > 0) // fill+queue new buffers + { + ALuint buffer; + alGetError(); /* clear error */ + alGenBuffers(1,&buffer); + if((error=alGetError()) != AL_NO_ERROR) + { + llwarns << "LLAudioEngine_OpenAL::initWind() Error creating wind buffer: " << error << llendl; + break; + } - #if LL_GSTREAMER_ENABLED - if(!m_streamer) - return 0; + alBufferData(buffer, + AL_FORMAT_STEREO16, + mWindGen->windGenerate(mWindBuf, + mWindBufSamples, 2), + mWindBufBytes, + mWindBufFreq); + error = alGetError(); + if(error != AL_NO_ERROR) + llwarns << "LLAudioEngine_OpenAL::updateWind() error swapping (bufferdata) buffers" << llendl; + + alSourceQueueBuffers(mWindSource, 1, &buffer); + error = alGetError(); + if(error != AL_NO_ERROR) + llwarns << "LLAudioEngine_OpenAL::updateWind() error swapping (queuing) buffers" << llendl; - if(m_streamer->getStatus() == LLMediaBase::STATUS_STARTED) - { - return 1; // Active and playing + --mNumEmptyWindALBuffers; } - if(m_streamer->getStatus() == LLMediaBase::STATUS_PAUSED) + int playing; + alGetSourcei(mWindSource, AL_SOURCE_STATE, &playing); + if(playing != AL_PLAYING) { - return 2; // paused - } - - #endif - return 0; // Stopped -} - - -void LLAudioEngine_OpenAL::getInternetStreamInfo(char* artist_out, char* title_out) -{ -} - - -void LLAudioEngine_OpenAL::setInternetStreamGain(F32 vol) -{ - #if LL_GSTREAMER_ENABLED - // Set the gstreamer volume here - if(!m_streamer) - return; - - vol = llclamp(vol, 0.f, 1.f); - m_streamer->setVolume(vol); - m_streamer->updateMedia(); - #endif -} - + alSourcePlay(mWindSource); -const std::string& LLAudioEngine_OpenAL::getInternetStreamURL() -{ - return mInternetStreamURL; + llinfos << "Wind had stopped - probably ran out of buffers - restarting: " << (unprocessed+mNumEmptyWindALBuffers) << " now queued." << llendl; + } } diff --git a/linden/indra/llaudio/audioengine_openal.h b/linden/indra/llaudio/audioengine_openal.h index 5d5c7d8..b03153a 100644 --- a/linden/indra/llaudio/audioengine_openal.h +++ b/linden/indra/llaudio/audioengine_openal.h @@ -3,27 +3,28 @@ * @brief implementation of audio engine using OpenAL * support as a OpenAL 3D implementation * - * Copyright (c) 2002-2008, Linden Research, Inc. * * $LicenseInfo:firstyear=2002&license=viewergpl$ - * + * + * Copyright (c) 2002-2008, Linden Research, Inc. + * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement * ("Other License"), formally executed by you and Linden Lab. Terms of * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlife.com/developers/opensource/gplv2 - * + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * * There are special exceptions to the terms and conditions of the GPL as * it is applied to this Source Code. View the full text of the exception * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at http://secondlife.com/developers/opensource/flossexception - * + * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception + * * By copying, modifying or distributing this software, you acknowledge * that you have read and understood your obligations described above, * and agree to abide by those obligations. - * + * * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, * COMPLETENESS OR PERFORMANCE. @@ -31,16 +32,12 @@ */ -#ifndef LL_AUDIOENGINE_OpenAL_H -#define LL_AUDIOENGINE_OpenAL_H - -#include +#ifndef LL_AUDIOENGINE_OPENAL_H +#define LL_AUDIOENGINE_OPENAL_H #include "audioengine.h" #include "listener_openal.h" -#include "llmediamanager.h" -#include "llmediaimplgstreamer.h" -#include "llrand.h" +#include "windgen.h" class LLAudioEngine_OpenAL : public LLAudioEngine { @@ -48,58 +45,34 @@ class LLAudioEngine_OpenAL : public LLAudioEngine LLAudioEngine_OpenAL(); virtual ~LLAudioEngine_OpenAL(); - virtual BOOL init(const S32 num_channels); - virtual std::string getDriverName(bool verbose); + virtual bool init(const S32 num_channels, void *user_data); + virtual std::string getDriverName(bool verbose); virtual void allocateListener(); virtual void shutdown(); - virtual void idle(F32 max_decode_time = 0.f); - void setInternalGain(F32 gain); LLAudioBuffer* createBuffer(); LLAudioChannel* createChannel(); - // Internet stream methods - virtual void initInternetStream(); - virtual void startInternetStream(const std::string& url_cstr); - virtual void stopInternetStream(); - virtual void updateInternetStream(); - virtual void pauseInternetStream(int pause); - virtual int isInternetStreamPlaying(); - virtual void getInternetStreamInfo(char* artist, char* title); - virtual void setInternetStreamGain(F32 vol); - virtual const std::string& getInternetStreamURL(); - virtual void InitStreamer(); - - void checkALError(); - - void initWind(); - void cleanupWind(); - void updateWind(LLVector3 direction, F32 camera_altitude); - - protected: - static const S32 mNumWindBuffers=20; - static const S32 mSampleRate=44100; - static const S32 mBytesPerSample=4; - static const S32 mWindDataSize=8820; //44100 * 0.200 * 2 channels * 2 bytes per sample - - BOOL mFirstWind; - ALuint mWindBuffers[mNumWindBuffers]; - ALuint mWindSource; - - F32 mTargetGain; - F32 mTargetFreq; - F32 mTargetPanGainR; - S16 mWindData[mWindDataSize]; - - std::string mInternetStreamURL; + /*virtual*/ void initWind(); + /*virtual*/ void cleanupWind(); + /*virtual*/ void updateWind(LLVector3 direction, F32 camera_altitude); + + private: void * windDSP(void *newbuffer, int length); -#if LL_GSTREAMER_ENABLED - LLMediaManagerData * mMedia_data; - LLMediaImplGStreamer * m_streamer; -#endif + typedef S16 WIND_SAMPLE_T; + LLWindGen *mWindGen; + S16 *mWindBuf; + U32 mWindBufFreq; + U32 mWindBufSamples; + U32 mWindBufBytes; + ALuint mWindSource; + int mNumEmptyWindALBuffers; + + static const int MAX_NUM_WIND_BUFFERS = 80; + static const float WIND_BUFFER_SIZE_SEC = 0.05f; // 1/20th sec }; class LLAudioChannelOpenAL : public LLAudioChannel @@ -108,16 +81,17 @@ class LLAudioChannelOpenAL : public LLAudioChannel LLAudioChannelOpenAL(); virtual ~LLAudioChannelOpenAL(); protected: - void play(); - void playSynced(LLAudioChannel *channelp); - void cleanup(); - bool isPlaying(); + /*virtual*/ void play(); + /*virtual*/ void playSynced(LLAudioChannel *channelp); + /*virtual*/ void cleanup(); + /*virtual*/ bool isPlaying(); - bool updateBuffer(); - void update3DPosition(); - void updateLoop(){}; + /*virtual*/ bool updateBuffer(); + /*virtual*/ void update3DPosition(); + /*virtual*/ void updateLoop(); - ALuint ALSource; + ALuint mALSource; + ALint mLastSamplePos; }; class LLAudioBufferOpenAL : public LLAudioBuffer{ @@ -131,8 +105,9 @@ class LLAudioBufferOpenAL : public LLAudioBuffer{ friend class LLAudioChannelOpenAL; protected: void cleanup(); - ALuint getBuffer(){return ALBuffer;} - ALuint ALBuffer; + ALuint getBuffer() {return mALBuffer;} + + ALuint mALBuffer; }; #endif diff --git a/linden/indra/newview/llaudiosourcevo.cpp b/linden/indra/newview/llaudiosourcevo.cpp index e668078..9c25d94 100644 --- a/linden/indra/newview/llaudiosourcevo.cpp +++ b/linden/indra/newview/llaudiosourcevo.cpp @@ -39,7 +39,7 @@ #include "llviewerparcelmgr.h" LLAudioSourceVO::LLAudioSourceVO(const LLUUID &sound_id, const LLUUID& owner_id, const F32 gain, LLViewerObject *objectp) -: LLAudioSource(sound_id, owner_id, gain), +: LLAudioSource(sound_id, owner_id, gain, LLAudioEngine::AUDIO_TYPE_SFX), mObjectp(objectp), mActualGain(gain) { diff --git a/linden/indra/newview/llpreviewsound.cpp b/linden/indra/newview/llpreviewsound.cpp index 9ba6fd5..6b79bfb 100644 --- a/linden/indra/newview/llpreviewsound.cpp +++ b/linden/indra/newview/llpreviewsound.cpp @@ -106,7 +106,6 @@ void LLPreviewSound::auditionSound( void *userdata ) if(item && gAudiop) { LLVector3d lpos_global = gAgent.getPositionGlobal(); - F32 volume = gSavedSettings.getBOOL("MuteSounds") ? 0.f : SOUND_GAIN * gSavedSettings.getF32("AudioLevelSFX"); - gAudiop->triggerSound(item->getAssetUUID(), gAgent.getID(), volume, lpos_global); + gAudiop->triggerSound(item->getAssetUUID(), gAgent.getID(), SOUND_GAIN, LLAudioEngine::AUDIO_TYPE_UI, lpos_global); } } diff --git a/linden/indra/newview/llstartup.cpp b/linden/indra/newview/llstartup.cpp index 636cf31..11e4ac5 100644 --- a/linden/indra/newview/llstartup.cpp +++ b/linden/indra/newview/llstartup.cpp @@ -583,28 +583,55 @@ bool idle_startup() if (FALSE == gSavedSettings.getBOOL("NoAudio")) { - - gAudiop = (LLAudioEngine *) new LLAudioEngine_OpenAL(); + gAudiop = NULL; + +#ifdef LL_OPENAL + if (!gAudiop +#if !LL_WINDOWS + && NULL == getenv("LL_BAD_OPENAL_DRIVER") +#endif // !LL_WINDOWS + ) + { + gAudiop = (LLAudioEngine *) new LLAudioEngine_OpenAL(); + } +#endif + +#ifdef LL_FMOD + if (!gAudiop +#if !LL_WINDOWS + && NULL == getenv("LL_BAD_FMOD_DRIVER") +#endif // !LL_WINDOWS + ) + { + gAudiop = (LLAudioEngine *) new LLAudioEngine_FMOD(); + } +#endif if (gAudiop) { - BOOL init = gAudiop->init(kAUDIO_NUM_SOURCES); - if(!init) +#if LL_WINDOWS + // FMOD on Windows needs the window handle to stop playing audio + // when window is minimized. JC + void* window_handle = (HWND)gViewerWindow->getPlatformWindow(); +#else + void* window_handle = NULL; +#endif + bool init = gAudiop->init(kAUDIO_NUM_SOURCES, window_handle); + if(init) { - LL_WARNS("AppInit") << "Unable to initialize audio engine" << LL_ENDL; - gAudiop=NULL; + gAudiop->setMuted(TRUE); } else { - gAudiop->setMuted(TRUE); - LL_INFOS("AppInit") << "Audio Engine Initialized." << LL_ENDL; + LL_WARNS("AppInit") << "Unable to initialize audio engine" << LL_ENDL; + delete gAudiop; + gAudiop = NULL; } } } - else - { - gAudiop = NULL; - } + + LL_INFOS("AppInit") << "Audio Engine Initialized." << LL_ENDL; + if (LLTimer::knownBadTimer()) { diff --git a/linden/indra/newview/llviewermessage.cpp b/linden/indra/newview/llviewermessage.cpp index 0e39026..260265e 100644 --- a/linden/indra/newview/llviewermessage.cpp +++ b/linden/indra/newview/llviewermessage.cpp @@ -3308,8 +3308,7 @@ void process_sound_trigger(LLMessageSystem *msg, void **) return; } - F32 volume = gSavedSettings.getBOOL("MuteSounds") ? 0.f : (gain * gSavedSettings.getF32("AudioLevelSFX")); - gAudiop->triggerSound(sound_id, owner_id, volume, pos_global); + gAudiop->triggerSound(sound_id, owner_id, gain, LLAudioEngine::AUDIO_TYPE_SFX, pos_global); } void process_preload_sound(LLMessageSystem *msg, void **user_data) diff --git a/linden/indra/newview/llviewertexteditor.cpp b/linden/indra/newview/llviewertexteditor.cpp index 8a55b3f..1dda1ca 100644 --- a/linden/indra/newview/llviewertexteditor.cpp +++ b/linden/indra/newview/llviewertexteditor.cpp @@ -1402,8 +1402,7 @@ void LLViewerTextEditor::openEmbeddedSound( LLInventoryItem* item ) const F32 SOUND_GAIN = 1.0f; if(gAudiop) { - F32 volume = gSavedSettings.getBOOL("MuteSounds") ? 0.f : (SOUND_GAIN * gSavedSettings.getF32("AudioLevelSFX")); - gAudiop->triggerSound(item->getAssetUUID(), gAgentID, volume, lpos_global); + gAudiop->triggerSound(item->getAssetUUID(), gAgentID, SOUND_GAIN, LLAudioEngine::AUDIO_TYPE_UI, lpos_global); } showCopyToInvDialog( item ); } diff --git a/linden/indra/newview/llvoavatar.cpp b/linden/indra/newview/llvoavatar.cpp index e480eb3..327cd57 100644 --- a/linden/indra/newview/llvoavatar.cpp +++ b/linden/indra/newview/llvoavatar.cpp @@ -3828,10 +3828,7 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent) // AUDIO_STEP_LO_SPEED, AUDIO_STEP_HI_SPEED, // AUDIO_STEP_LO_GAIN, AUDIO_STEP_HI_GAIN ); - F32 ambient_volume = gSavedSettings.getF32("AudioLevelAmbient"); - F32 gain = gSavedSettings.getBOOL("MuteAmbient") - ? 0.f - : (.50f * ambient_volume * ambient_volume); + const F32 STEP_VOLUME = 0.5f; LLUUID& step_sound_id = getStepSound(); LLVector3d foot_pos_global = gAgent.getPosGlobalFromAgent(foot_pos_agent); @@ -3839,7 +3836,7 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent) if (LLViewerParcelMgr::getInstance()->canHearSound(foot_pos_global) && !LLMuteList::getInstance()->isMuted(getID(), LLMute::flagObjectSounds)) { - gAudiop->triggerSound(step_sound_id, getID(), gain, foot_pos_global); + gAudiop->triggerSound(step_sound_id, getID(), STEP_VOLUME, LLAudioEngine::AUDIO_TYPE_AMBIENT, foot_pos_global); } } } @@ -4819,8 +4816,8 @@ BOOL LLVOAvatar::processSingleAnimationStateChange( const LLUUID& anim_id, BOOL //else { LLUUID sound_id = LLUUID(gSavedSettings.getString("UISndTyping")); - F32 volume = gSavedSettings.getBOOL("MuteSounds") ? 0.f : gSavedSettings.getF32("AudioLevelSFX"); - gAudiop->triggerSound(sound_id, getID(), volume, char_pos_global); + gAudiop->triggerSound(sound_id, getID(), 1.0f, LLAudioEngine::AUDIO_TYPE_SFX, char_pos_global); + } } } -- cgit v1.1