diff options
Diffstat (limited to '')
-rw-r--r-- | linden/indra/llaudio/audioengine.cpp | 184 | ||||
-rw-r--r-- | linden/indra/llaudio/audioengine.h | 56 | ||||
-rw-r--r-- | linden/indra/llaudio/audioengine_openal.cpp | 767 | ||||
-rw-r--r-- | linden/indra/llaudio/audioengine_openal.h | 107 | ||||
-rw-r--r-- | linden/indra/newview/llaudiosourcevo.cpp | 2 | ||||
-rw-r--r-- | linden/indra/newview/llpreviewsound.cpp | 3 | ||||
-rw-r--r-- | linden/indra/newview/llstartup.cpp | 51 | ||||
-rw-r--r-- | linden/indra/newview/llviewermessage.cpp | 3 | ||||
-rw-r--r-- | linden/indra/newview/llviewertexteditor.cpp | 3 | ||||
-rw-r--r-- | linden/indra/newview/llvoavatar.cpp | 11 |
10 files changed, 549 insertions, 638 deletions
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); | |||
51 | 51 | ||
52 | LLAudioEngine* gAudiop = NULL; | 52 | LLAudioEngine* gAudiop = NULL; |
53 | 53 | ||
54 | // Maximum amount of time we wait for a transfer to complete before starting | ||
55 | // off another one. | ||
56 | const F32 MAX_CURRENT_TRANSFER_TIME = 60.f; | ||
57 | 54 | ||
58 | // | 55 | // |
59 | // LLAudioEngine implementation | 56 | // LLAudioEngine implementation |
@@ -77,7 +74,8 @@ void LLAudioEngine::setDefaults() | |||
77 | 74 | ||
78 | mListenerp = NULL; | 75 | mListenerp = NULL; |
79 | 76 | ||
80 | mMuted = FALSE; | 77 | mMuted = false; |
78 | mUserData = NULL; | ||
81 | 79 | ||
82 | mLastStatus = 0; | 80 | mLastStatus = 0; |
83 | 81 | ||
@@ -98,16 +96,20 @@ void LLAudioEngine::setDefaults() | |||
98 | mInternetStreamGain = 0.125f; | 96 | mInternetStreamGain = 0.125f; |
99 | mNextWindUpdate = 0.f; | 97 | mNextWindUpdate = 0.f; |
100 | 98 | ||
99 | mInternetStreamMedia = NULL; | ||
100 | mInternetStreamURL.clear(); | ||
101 | |||
101 | for (U32 i = 0; i < LLAudioEngine::AUDIO_TYPE_COUNT; i++) | 102 | for (U32 i = 0; i < LLAudioEngine::AUDIO_TYPE_COUNT; i++) |
102 | mSecondaryGain[i] = 1.0f; | 103 | mSecondaryGain[i] = 1.0f; |
103 | } | 104 | } |
104 | 105 | ||
105 | 106 | ||
106 | BOOL LLAudioEngine::init(const S32 num_channels) | 107 | bool LLAudioEngine::init(const S32 num_channels, void* userdata) |
107 | { | 108 | { |
108 | setDefaults(); | 109 | setDefaults(); |
109 | 110 | ||
110 | mNumChannels = num_channels; | 111 | mNumChannels = num_channels; |
112 | mUserData = userdata; | ||
111 | 113 | ||
112 | allocateListener(); | 114 | allocateListener(); |
113 | 115 | ||
@@ -126,6 +128,9 @@ void LLAudioEngine::shutdown() | |||
126 | delete gAudioDecodeMgrp; | 128 | delete gAudioDecodeMgrp; |
127 | gAudioDecodeMgrp = NULL; | 129 | gAudioDecodeMgrp = NULL; |
128 | 130 | ||
131 | // Clean up wind source | ||
132 | cleanupWind(); | ||
133 | |||
129 | // Clean up audio sources | 134 | // Clean up audio sources |
130 | source_map::iterator iter_src; | 135 | source_map::iterator iter_src; |
131 | for (iter_src = mAllSources.begin(); iter_src != mAllSources.end(); iter_src++) | 136 | for (iter_src = mAllSources.begin(); iter_src != mAllSources.end(); iter_src++) |
@@ -146,22 +151,146 @@ void LLAudioEngine::shutdown() | |||
146 | S32 i; | 151 | S32 i; |
147 | for (i = 0; i < MAX_CHANNELS; i++) | 152 | for (i = 0; i < MAX_CHANNELS; i++) |
148 | { | 153 | { |
149 | if (mChannels[i]) | 154 | delete mChannels[i]; |
150 | { | 155 | mChannels[i] = NULL; |
151 | delete mChannels[i]; | ||
152 | mChannels[i] = NULL; | ||
153 | } | ||
154 | } | 156 | } |
155 | 157 | ||
156 | // Clean up buffers | 158 | // Clean up buffers |
157 | for (i = 0; i < MAX_BUFFERS; i++) | 159 | for (i = 0; i < MAX_BUFFERS; i++) |
158 | { | 160 | { |
159 | if (mBuffers[i]) | 161 | delete mBuffers[i]; |
162 | mBuffers[i] = NULL; | ||
163 | } | ||
164 | |||
165 | delete mInternetStreamMedia; | ||
166 | mInternetStreamMedia = NULL; | ||
167 | mInternetStreamURL.clear(); | ||
168 | } | ||
169 | |||
170 | |||
171 | // virtual | ||
172 | void LLAudioEngine::startInternetStream(const std::string& url) | ||
173 | { | ||
174 | llinfos << "entered startInternetStream()" << llendl; | ||
175 | |||
176 | if (!mInternetStreamMedia) | ||
177 | { | ||
178 | LLMediaManager* mgr = LLMediaManager::getInstance(); | ||
179 | if (mgr) | ||
160 | { | 180 | { |
161 | delete mBuffers[i]; | 181 | mInternetStreamMedia = mgr->createSourceFromMimeType(LLURI(url).scheme(), "audio/mpeg"); // assumes that whatever media implementation supports mp3 also supports vorbis. |
162 | mBuffers[i] = NULL; | 182 | llinfos << "mInternetStreamMedia is now " << mInternetStreamMedia << llendl; |
183 | } | ||
184 | } | ||
185 | |||
186 | if(!mInternetStreamMedia) | ||
187 | return; | ||
188 | |||
189 | if (!url.empty()) { | ||
190 | llinfos << "Starting internet stream: " << url << llendl; | ||
191 | mInternetStreamURL = url; | ||
192 | mInternetStreamMedia->navigateTo ( url ); | ||
193 | llinfos << "Playing....." << llendl; | ||
194 | mInternetStreamMedia->addCommand(LLMediaBase::COMMAND_START); | ||
195 | mInternetStreamMedia->updateMedia(); | ||
196 | } else { | ||
197 | llinfos << "setting stream to NULL"<< llendl; | ||
198 | mInternetStreamURL.clear(); | ||
199 | mInternetStreamMedia->addCommand(LLMediaBase::COMMAND_STOP); | ||
200 | mInternetStreamMedia->updateMedia(); | ||
201 | } | ||
202 | //#endif | ||
203 | } | ||
204 | |||
205 | // virtual | ||
206 | void LLAudioEngine::stopInternetStream() | ||
207 | { | ||
208 | llinfos << "entered stopInternetStream()" << llendl; | ||
209 | |||
210 | if(mInternetStreamMedia) | ||
211 | { | ||
212 | if( ! mInternetStreamMedia->addCommand(LLMediaBase::COMMAND_STOP)){ | ||
213 | llinfos << "attempting to stop stream failed!" << llendl; | ||
214 | } | ||
215 | mInternetStreamMedia->updateMedia(); | ||
216 | } | ||
217 | |||
218 | mInternetStreamURL.clear(); | ||
219 | } | ||
220 | |||
221 | // virtual | ||
222 | void LLAudioEngine::pauseInternetStream(int pause) | ||
223 | { | ||
224 | llinfos << "entered pauseInternetStream()" << llendl; | ||
225 | |||
226 | if(!mInternetStreamMedia) | ||
227 | return; | ||
228 | |||
229 | if(pause) | ||
230 | { | ||
231 | if(! mInternetStreamMedia->addCommand(LLMediaBase::COMMAND_PAUSE)) | ||
232 | { | ||
233 | llinfos << "attempting to pause stream failed!" << llendl; | ||
163 | } | 234 | } |
235 | } else { | ||
236 | if(! mInternetStreamMedia->addCommand(LLMediaBase::COMMAND_START)) | ||
237 | { | ||
238 | llinfos << "attempting to unpause stream failed!" << llendl; | ||
239 | } | ||
240 | } | ||
241 | mInternetStreamMedia->updateMedia(); | ||
242 | } | ||
243 | |||
244 | // virtual | ||
245 | void LLAudioEngine::updateInternetStream() | ||
246 | { | ||
247 | if (mInternetStreamMedia) | ||
248 | mInternetStreamMedia->updateMedia(); | ||
249 | } | ||
250 | |||
251 | // virtual | ||
252 | int LLAudioEngine::isInternetStreamPlaying() | ||
253 | { | ||
254 | if (!mInternetStreamMedia) | ||
255 | return 0; | ||
256 | |||
257 | if (mInternetStreamMedia->getStatus() == LLMediaBase::STATUS_STARTED) | ||
258 | { | ||
259 | return 1; // Active and playing | ||
260 | } | ||
261 | |||
262 | if (mInternetStreamMedia->getStatus() == LLMediaBase::STATUS_PAUSED) | ||
263 | { | ||
264 | return 2; // paused | ||
164 | } | 265 | } |
266 | |||
267 | return 0; // Stopped | ||
268 | } | ||
269 | |||
270 | // virtual | ||
271 | void LLAudioEngine::getInternetStreamInfo(char* artist, char* title) | ||
272 | { | ||
273 | artist[0] = 0; | ||
274 | title[0] = 0; | ||
275 | } | ||
276 | |||
277 | // virtual | ||
278 | void LLAudioEngine::setInternetStreamGain(F32 vol) | ||
279 | { | ||
280 | mInternetStreamGain = vol; | ||
281 | |||
282 | if(!mInternetStreamMedia) | ||
283 | return; | ||
284 | |||
285 | vol = llclamp(vol, 0.f, 1.f); | ||
286 | mInternetStreamMedia->setVolume(vol); | ||
287 | mInternetStreamMedia->updateMedia(); | ||
288 | } | ||
289 | |||
290 | // virtual | ||
291 | const std::string& LLAudioEngine::getInternetStreamURL() | ||
292 | { | ||
293 | return mInternetStreamURL; | ||
165 | } | 294 | } |
166 | 295 | ||
167 | 296 | ||
@@ -449,6 +578,8 @@ void LLAudioEngine::idle(F32 max_decode_time) | |||
449 | // missed picking it up in all the places that can add | 578 | // missed picking it up in all the places that can add |
450 | // or request new data. | 579 | // or request new data. |
451 | startNextTransfer(); | 580 | startNextTransfer(); |
581 | |||
582 | updateInternetStream(); | ||
452 | } | 583 | } |
453 | 584 | ||
454 | 585 | ||
@@ -758,7 +889,7 @@ void LLAudioEngine::triggerSound(const LLUUID &audio_uuid, const LLUUID& owner_i | |||
758 | LLUUID source_id; | 889 | LLUUID source_id; |
759 | source_id.generate(); | 890 | source_id.generate(); |
760 | 891 | ||
761 | LLAudioSource *asp = new LLAudioSource(source_id, owner_id, gain); | 892 | LLAudioSource *asp = new LLAudioSource(source_id, owner_id, gain, type); |
762 | gAudiop->addAudioSource(asp); | 893 | gAudiop->addAudioSource(asp); |
763 | if (pos_global.isExactlyZero()) | 894 | if (pos_global.isExactlyZero()) |
764 | { | 895 | { |
@@ -1207,18 +1338,18 @@ void LLAudioEngine::assetCallback(LLVFS *vfs, const LLUUID &uuid, LLAssetType::E | |||
1207 | // | 1338 | // |
1208 | 1339 | ||
1209 | 1340 | ||
1210 | LLAudioSource::LLAudioSource(const LLUUID& id, const LLUUID& owner_id, const F32 gain) | 1341 | LLAudioSource::LLAudioSource(const LLUUID& id, const LLUUID& owner_id, const F32 gain, const S32 type) |
1211 | : mID(id), | 1342 | : mID(id), |
1212 | mOwnerID(owner_id), | 1343 | mOwnerID(owner_id), |
1213 | mPriority(0.f), | 1344 | mPriority(0.f), |
1214 | mGain(gain), | 1345 | mGain(gain), |
1215 | mType(type), | 1346 | mType(type), |
1216 | mAmbient(FALSE), | 1347 | mAmbient(false), |
1217 | mLoop(FALSE), | 1348 | mLoop(false), |
1218 | mSyncMaster(FALSE), | 1349 | mSyncMaster(false), |
1219 | mSyncSlave(FALSE), | 1350 | mSyncSlave(false), |
1220 | mQueueSounds(FALSE), | 1351 | mQueueSounds(false), |
1221 | mPlayedOnce(FALSE), | 1352 | mPlayedOnce(false), |
1222 | mChannelp(NULL), | 1353 | mChannelp(NULL), |
1223 | mCurrentDatap(NULL), | 1354 | mCurrentDatap(NULL), |
1224 | mQueuedDatap(NULL) | 1355 | mQueuedDatap(NULL) |
@@ -1364,7 +1495,8 @@ bool LLAudioSource::play(const LLUUID &audio_uuid) | |||
1364 | bool LLAudioSource::isDone() | 1495 | bool LLAudioSource::isDone() |
1365 | { | 1496 | { |
1366 | const F32 MAX_AGE = 60.f; | 1497 | const F32 MAX_AGE = 60.f; |
1367 | const F32 MAX_UNPLAYED_AGE = 30.f; | 1498 | const F32 MAX_UNPLAYED_AGE = 15.f; |
1499 | |||
1368 | if (isLoop()) | 1500 | if (isLoop()) |
1369 | { | 1501 | { |
1370 | // Looped sources never die on their own. | 1502 | // Looped sources never die on their own. |
@@ -1542,8 +1674,8 @@ LLAudioBuffer *LLAudioSource::getCurrentBuffer() | |||
1542 | LLAudioChannel::LLAudioChannel() : | 1674 | LLAudioChannel::LLAudioChannel() : |
1543 | mCurrentSourcep(NULL), | 1675 | mCurrentSourcep(NULL), |
1544 | mCurrentBufferp(NULL), | 1676 | mCurrentBufferp(NULL), |
1545 | mLoopedThisFrame(FALSE), | 1677 | mLoopedThisFrame(false), |
1546 | mWaiting(FALSE), | 1678 | mWaiting(false), |
1547 | mSecondaryGain(1.0f) | 1679 | mSecondaryGain(1.0f) |
1548 | { | 1680 | { |
1549 | } | 1681 | } |
@@ -1609,8 +1741,8 @@ bool LLAudioChannel::updateBuffer() | |||
1609 | } | 1741 | } |
1610 | 1742 | ||
1611 | // | 1743 | // |
1612 | // The source changed what buffer it's playing. Whe need to clean up the | 1744 | // The source changed what buffer it's playing. We need to clean up |
1613 | // existing fmod channel | 1745 | // the existing channel |
1614 | // | 1746 | // |
1615 | cleanup(); | 1747 | cleanup(); |
1616 | 1748 | ||
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; | |||
69 | class LLAudioSource; | 69 | class LLAudioSource; |
70 | class LLAudioData; | 70 | class LLAudioData; |
71 | class LLAudioChannel; | 71 | class LLAudioChannel; |
72 | class LLAudioChannelOpenAL; | ||
72 | class LLAudioBuffer; | 73 | class LLAudioBuffer; |
73 | 74 | ||
74 | 75 | ||
@@ -79,8 +80,10 @@ class LLAudioBuffer; | |||
79 | 80 | ||
80 | class LLAudioEngine | 81 | class LLAudioEngine |
81 | { | 82 | { |
83 | friend class LLAudioChannelOpenAL; // bleh. channel needs some listener methods. | ||
84 | |||
82 | public: | 85 | public: |
83 | enum LLAudioType | 86 | typedef enum LLAudioType |
84 | { | 87 | { |
85 | AUDIO_TYPE_NONE = 0, | 88 | AUDIO_TYPE_NONE = 0, |
86 | AUDIO_TYPE_SFX = 1, | 89 | AUDIO_TYPE_SFX = 1, |
@@ -93,9 +96,7 @@ public: | |||
93 | virtual ~LLAudioEngine(); | 96 | virtual ~LLAudioEngine(); |
94 | 97 | ||
95 | // initialization/startup/shutdown | 98 | // initialization/startup/shutdown |
96 | //virtual BOOL init(); | 99 | virtual bool init(const S32 num_channels, void *userdata); |
97 | |||
98 | virtual BOOL init(const S32 num_channels); | ||
99 | virtual std::string getDriverName(bool verbose) = 0; | 100 | virtual std::string getDriverName(bool verbose) = 0; |
100 | virtual void shutdown(); | 101 | virtual void shutdown(); |
101 | 102 | ||
@@ -140,7 +141,7 @@ public: | |||
140 | void triggerSound(const LLUUID &sound_id, const LLUUID& owner_id, const F32 gain, | 141 | void triggerSound(const LLUUID &sound_id, const LLUUID& owner_id, const F32 gain, |
141 | const S32 type = LLAudioEngine::AUDIO_TYPE_NONE, | 142 | const S32 type = LLAudioEngine::AUDIO_TYPE_NONE, |
142 | const LLVector3d &pos_global = LLVector3d::zero); | 143 | const LLVector3d &pos_global = LLVector3d::zero); |
143 | BOOL preloadSound(const LLUUID &id); | 144 | bool preloadSound(const LLUUID &id); |
144 | 145 | ||
145 | void addAudioSource(LLAudioSource *asp); | 146 | void addAudioSource(LLAudioSource *asp); |
146 | void cleanupAudioSource(LLAudioSource *asp); | 147 | void cleanupAudioSource(LLAudioSource *asp); |
@@ -149,15 +150,16 @@ public: | |||
149 | LLAudioData *getAudioData(const LLUUID &audio_uuid); | 150 | LLAudioData *getAudioData(const LLUUID &audio_uuid); |
150 | 151 | ||
151 | 152 | ||
152 | virtual void startInternetStream(const std::string& url) = 0; | 153 | // Internet stream methods |
153 | virtual void stopInternetStream() = 0; | 154 | virtual void startInternetStream(const std::string& url); |
154 | virtual void pauseInternetStream(int pause) = 0; | 155 | virtual void stopInternetStream(); |
155 | virtual int isInternetStreamPlaying() = 0; | 156 | virtual void pauseInternetStream(int pause); |
156 | virtual void getInternetStreamInfo(char* artist, char* title) { artist[0] = 0; title[0] = 0; } | 157 | virtual void updateInternetStream(); |
158 | virtual int isInternetStreamPlaying(); | ||
159 | virtual void getInternetStreamInfo(char* artist, char* title); | ||
157 | // use a value from 0.0 to 1.0, inclusive | 160 | // use a value from 0.0 to 1.0, inclusive |
158 | virtual void setInternetStreamGain(F32 vol) { mInternetStreamGain = vol; } | 161 | virtual void setInternetStreamGain(F32 vol); |
159 | virtual const std::string& getInternetStreamURL() { return LLStringUtil::null; } | 162 | virtual const std::string& getInternetStreamURL(); |
160 | virtual void InitStreamer() = 0; | ||
161 | 163 | ||
162 | // For debugging usage | 164 | // For debugging usage |
163 | virtual LLVector3 getListenerPos(); | 165 | virtual LLVector3 getListenerPos(); |
@@ -193,11 +195,6 @@ protected: | |||
193 | virtual void allocateListener() = 0; | 195 | virtual void allocateListener() = 0; |
194 | 196 | ||
195 | 197 | ||
196 | // Internet stream methods | ||
197 | virtual void initInternetStream() {} | ||
198 | virtual void updateInternetStream() {} | ||
199 | |||
200 | |||
201 | // listener methods | 198 | // listener methods |
202 | virtual void setListenerPos(LLVector3 vec); | 199 | virtual void setListenerPos(LLVector3 vec); |
203 | virtual void setListenerVelocity(LLVector3 vec); | 200 | virtual void setListenerVelocity(LLVector3 vec); |
@@ -212,7 +209,8 @@ protected: | |||
212 | protected: | 209 | protected: |
213 | LLListener *mListenerp; | 210 | LLListener *mListenerp; |
214 | 211 | ||
215 | BOOL mMuted; | 212 | bool mMuted; |
213 | void* mUserData; | ||
216 | 214 | ||
217 | S32 mLastStatus; | 215 | S32 mLastStatus; |
218 | 216 | ||
@@ -242,6 +240,7 @@ protected: | |||
242 | 240 | ||
243 | // Hack! Internet streams are treated differently from other sources! | 241 | // Hack! Internet streams are treated differently from other sources! |
244 | F32 mInternetStreamGain; | 242 | F32 mInternetStreamGain; |
243 | std::string mInternetStreamURL; | ||
245 | 244 | ||
246 | F32 mNextWindUpdate; | 245 | F32 mNextWindUpdate; |
247 | 246 | ||
@@ -249,6 +248,7 @@ protected: | |||
249 | 248 | ||
250 | private: | 249 | private: |
251 | void setDefaults(); | 250 | void setDefaults(); |
251 | LLMediaBase *mInternetStreamMedia; | ||
252 | }; | 252 | }; |
253 | 253 | ||
254 | 254 | ||
@@ -264,7 +264,7 @@ class LLAudioSource | |||
264 | public: | 264 | public: |
265 | // owner_id is the id of the agent responsible for making this sound | 265 | // owner_id is the id of the agent responsible for making this sound |
266 | // play, for example, the owner of the object currently playing it | 266 | // play, for example, the owner of the object currently playing it |
267 | LLAudioSource(const LLUUID &id, const LLUUID& owner_id, const F32 gain); | 267 | LLAudioSource(const LLUUID &id, const LLUUID& owner_id, const F32 gain, const S32 type = LLAudioEngine::AUDIO_TYPE_NONE); |
268 | virtual ~LLAudioSource(); | 268 | virtual ~LLAudioSource(); |
269 | 269 | ||
270 | virtual void update(); // Update this audio source | 270 | virtual void update(); // Update this audio source |
@@ -326,12 +326,12 @@ protected: | |||
326 | LLUUID mOwnerID; // owner of the object playing the sound | 326 | LLUUID mOwnerID; // owner of the object playing the sound |
327 | F32 mPriority; | 327 | F32 mPriority; |
328 | F32 mGain; | 328 | F32 mGain; |
329 | BOOL mAmbient; | 329 | bool mAmbient; |
330 | BOOL mLoop; | 330 | bool mLoop; |
331 | BOOL mSyncMaster; | 331 | bool mSyncMaster; |
332 | BOOL mSyncSlave; | 332 | bool mSyncSlave; |
333 | BOOL mQueueSounds; | 333 | bool mQueueSounds; |
334 | BOOL mPlayedOnce; | 334 | bool mPlayedOnce; |
335 | S32 mType; | 335 | S32 mType; |
336 | LLVector3d mPositionGlobal; | 336 | LLVector3d mPositionGlobal; |
337 | LLVector3 mVelocity; | 337 | LLVector3 mVelocity; |
@@ -420,8 +420,8 @@ protected: | |||
420 | protected: | 420 | protected: |
421 | LLAudioSource *mCurrentSourcep; | 421 | LLAudioSource *mCurrentSourcep; |
422 | LLAudioBuffer *mCurrentBufferp; | 422 | LLAudioBuffer *mCurrentBufferp; |
423 | BOOL mLoopedThisFrame; | 423 | bool mLoopedThisFrame; |
424 | BOOL mWaiting; // Waiting for sync. | 424 | bool mWaiting; // Waiting for sync. |
425 | F32 mSecondaryGain; | 425 | F32 mSecondaryGain; |
426 | }; | 426 | }; |
427 | 427 | ||
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 @@ | |||
4 | * support as a OpenAL 3D implementation | 4 | * support as a OpenAL 3D implementation |
5 | * | 5 | * |
6 | * $LicenseInfo:firstyear=2002&license=viewergpl$ | 6 | * $LicenseInfo:firstyear=2002&license=viewergpl$ |
7 | * | 7 | * |
8 | * Copyright (c) 2002-2008, Linden Research, Inc. | 8 | * Copyright (c) 2002-2008, Linden Research, Inc. |
9 | * | 9 | * |
10 | * Second Life Viewer Source Code | 10 | * Second Life Viewer Source Code |
11 | * The source code in this file ("Source Code") is provided by Linden Lab | 11 | * The source code in this file ("Source Code") is provided by Linden Lab |
12 | * to you under the terms of the GNU General Public License, version 2.0 | 12 | * to you under the terms of the GNU General Public License, version 2.0 |
13 | * ("GPL"), unless you have obtained a separate licensing agreement | 13 | * ("GPL"), unless you have obtained a separate licensing agreement |
14 | * ("Other License"), formally executed by you and Linden Lab. Terms of | 14 | * ("Other License"), formally executed by you and Linden Lab. Terms of |
15 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | 15 | * the GPL can be found in doc/GPL-license.txt in this distribution, or |
16 | * online at http://secondlife.com/developers/opensource/gplv2 | 16 | * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 |
17 | * | 17 | * |
18 | * There are special exceptions to the terms and conditions of the GPL as | 18 | * There are special exceptions to the terms and conditions of the GPL as |
19 | * it is applied to this Source Code. View the full text of the exception | 19 | * it is applied to this Source Code. View the full text of the exception |
20 | * in the file doc/FLOSS-exception.txt in this software distribution, or | 20 | * in the file doc/FLOSS-exception.txt in this software distribution, or |
21 | * online at http://secondlife.com/developers/opensource/flossexception | 21 | * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception |
22 | * | 22 | * |
23 | * By copying, modifying or distributing this software, you acknowledge | 23 | * By copying, modifying or distributing this software, you acknowledge |
24 | * that you have read and understood your obligations described above, | 24 | * that you have read and understood your obligations described above, |
25 | * and agree to abide by those obligations. | 25 | * and agree to abide by those obligations. |
26 | * | 26 | * |
27 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | 27 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO |
28 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | 28 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, |
29 | * COMPLETENESS OR PERFORMANCE. | 29 | * COMPLETENESS OR PERFORMANCE. |
@@ -36,31 +36,29 @@ | |||
36 | #include "audioengine_openal.h" | 36 | #include "audioengine_openal.h" |
37 | #include "listener_openal.h" | 37 | #include "listener_openal.h" |
38 | 38 | ||
39 | |||
39 | LLAudioEngine_OpenAL::LLAudioEngine_OpenAL() | 40 | LLAudioEngine_OpenAL::LLAudioEngine_OpenAL() |
41 | : | ||
42 | mWindGen(NULL), | ||
43 | mWindBuf(NULL), | ||
44 | mWindBufFreq(0), | ||
45 | mWindBufSamples(0), | ||
46 | mWindBufBytes(0), | ||
47 | mWindSource(AL_NONE), | ||
48 | mNumEmptyWindALBuffers(MAX_NUM_WIND_BUFFERS) | ||
40 | { | 49 | { |
41 | |||
42 | #if LL_GSTREAMER_ENABLED | ||
43 | mMedia_data = new LLMediaManagerData; | ||
44 | // initialize GStreamer | ||
45 | LLMediaImplGStreamer::startup( mMedia_data ); | ||
46 | |||
47 | m_streamer=new LLMediaImplGStreamer (); | ||
48 | |||
49 | if(!m_streamer) | ||
50 | { | ||
51 | llwarns << "LLAudioEngine_OpenAL::LLAudioEngine_OpenAL() Failed to create our private gstreamer audio instance" << llendl; | ||
52 | } | ||
53 | #endif | ||
54 | } | 50 | } |
55 | 51 | ||
52 | // virtual | ||
56 | LLAudioEngine_OpenAL::~LLAudioEngine_OpenAL() | 53 | LLAudioEngine_OpenAL::~LLAudioEngine_OpenAL() |
57 | { | 54 | { |
58 | } | 55 | } |
59 | 56 | ||
60 | 57 | // virtual | |
61 | BOOL LLAudioEngine_OpenAL::init(const S32 num_channels) | 58 | bool LLAudioEngine_OpenAL::init(const S32 num_channels, void* userdata) |
62 | { | 59 | { |
63 | LLAudioEngine::init(num_channels); | 60 | mWindGen = NULL; |
61 | LLAudioEngine::init(num_channels, userdata); | ||
64 | 62 | ||
65 | if(!alutInit(NULL, NULL)) | 63 | if(!alutInit(NULL, NULL)) |
66 | { | 64 | { |
@@ -68,27 +66,39 @@ BOOL LLAudioEngine_OpenAL::init(const S32 num_channels) | |||
68 | return false; | 66 | return false; |
69 | } | 67 | } |
70 | 68 | ||
71 | initInternetStream(); | ||
72 | |||
73 | llinfos << "LLAudioEngine_OpenAL::init() OpenAL successfully initialized" << llendl; | 69 | llinfos << "LLAudioEngine_OpenAL::init() OpenAL successfully initialized" << llendl; |
74 | 70 | ||
75 | llinfos << "LLAudioEngine_OpenAL::init() Speed of sound is: " << alGetFloat(AL_SPEED_OF_SOUND) << llendl; | 71 | llinfos << "OpenAL version: " |
72 | << ll_safe_string(alGetString(AL_VERSION)) << llendl; | ||
73 | llinfos << "OpenAL vendor: " | ||
74 | << ll_safe_string(alGetString(AL_VENDOR)) << llendl; | ||
75 | llinfos << "OpenAL renderer: " | ||
76 | << ll_safe_string(alGetString(AL_RENDERER)) << llendl; | ||
77 | |||
78 | ALint major = alutGetMajorVersion (); | ||
79 | ALint minor = alutGetMinorVersion (); | ||
80 | llinfos << "ALUT version: " << major << "." << minor << llendl; | ||
76 | 81 | ||
77 | return TRUE; | 82 | ALCdevice *device = alcGetContextsDevice(alcGetCurrentContext()); |
83 | |||
84 | alcGetIntegerv(device, ALC_MAJOR_VERSION, 1, &major); | ||
85 | alcGetIntegerv(device, ALC_MAJOR_VERSION, 1, &minor); | ||
86 | llinfos << "ALC version: " << major << "." << minor << llendl; | ||
87 | |||
88 | llinfos << "ALC default device: " | ||
89 | << ll_safe_string(alcGetString(device, | ||
90 | ALC_DEFAULT_DEVICE_SPECIFIER)) | ||
91 | << llendl; | ||
92 | |||
93 | return true; | ||
78 | } | 94 | } |
79 | 95 | ||
96 | // virtual | ||
80 | std::string LLAudioEngine_OpenAL::getDriverName(bool verbose) | 97 | std::string LLAudioEngine_OpenAL::getDriverName(bool verbose) |
81 | { | 98 | { |
82 | ALCdevice *device = alcGetContextsDevice(alcGetCurrentContext()); | 99 | ALCdevice *device = alcGetContextsDevice(alcGetCurrentContext()); |
83 | |||
84 | std::ostringstream version; | 100 | std::ostringstream version; |
85 | 101 | ||
86 | ALint major = alutGetMajorVersion (); | ||
87 | ALint minor = alutGetMinorVersion (); | ||
88 | |||
89 | alcGetIntegerv(device, ALC_MAJOR_VERSION, 1, &major); | ||
90 | alcGetIntegerv(device, ALC_MAJOR_VERSION, 1, &minor); | ||
91 | |||
92 | version << | 102 | version << |
93 | "OpenAL"; | 103 | "OpenAL"; |
94 | 104 | ||
@@ -112,17 +122,7 @@ std::string LLAudioEngine_OpenAL::getDriverName(bool verbose) | |||
112 | return version.str(); | 122 | return version.str(); |
113 | } | 123 | } |
114 | 124 | ||
115 | 125 | // virtual | |
116 | void LLAudioEngine_OpenAL::idle(F32 max_decode_time) | ||
117 | { | ||
118 | LLAudioEngine::idle(max_decode_time); | ||
119 | #if LL_GSTREAMER_ENABLED | ||
120 | if(m_streamer != NULL) | ||
121 | m_streamer->updateMedia(); | ||
122 | #endif | ||
123 | } | ||
124 | |||
125 | |||
126 | void LLAudioEngine_OpenAL::allocateListener() | 126 | void LLAudioEngine_OpenAL::allocateListener() |
127 | { | 127 | { |
128 | mListenerp = (LLListener *) new LLListener_OpenAL(); | 128 | mListenerp = (LLListener *) new LLListener_OpenAL(); |
@@ -132,6 +132,7 @@ void LLAudioEngine_OpenAL::allocateListener() | |||
132 | } | 132 | } |
133 | } | 133 | } |
134 | 134 | ||
135 | // virtual | ||
135 | void LLAudioEngine_OpenAL::shutdown() | 136 | void LLAudioEngine_OpenAL::shutdown() |
136 | { | 137 | { |
137 | llinfos << "About to LLAudioEngine::shutdown()" << llendl; | 138 | llinfos << "About to LLAudioEngine::shutdown()" << llendl; |
@@ -143,21 +144,11 @@ void LLAudioEngine_OpenAL::shutdown() | |||
143 | llwarns << "Nuts." << llendl; | 144 | llwarns << "Nuts." << llendl; |
144 | llwarns << "LLAudioEngine_OpenAL::shutdown() ALUT shutdown failed: " << alutGetErrorString (alutGetError ()) << llendl; | 145 | llwarns << "LLAudioEngine_OpenAL::shutdown() ALUT shutdown failed: " << alutGetErrorString (alutGetError ()) << llendl; |
145 | } | 146 | } |
146 | else | 147 | |
147 | { | 148 | llinfos << "LLAudioEngine_OpenAL::shutdown() OpenAL successfully shut down" << llendl; |
148 | llinfos << "LLAudioEngine_OpenAL::shutdown() OpenAL successfully shut down" << llendl; | 149 | |
149 | } | ||
150 | |||
151 | delete mListenerp; | 150 | delete mListenerp; |
152 | mListenerp = NULL; | 151 | mListenerp = NULL; |
153 | |||
154 | #if LL_GSTREAMER_ENABLED | ||
155 | if(m_streamer) | ||
156 | { | ||
157 | delete m_streamer; | ||
158 | m_streamer = NULL; | ||
159 | } | ||
160 | #endif | ||
161 | } | 152 | } |
162 | 153 | ||
163 | LLAudioBuffer *LLAudioEngine_OpenAL::createBuffer() | 154 | LLAudioBuffer *LLAudioEngine_OpenAL::createBuffer() |
@@ -177,44 +168,75 @@ void LLAudioEngine_OpenAL::setInternalGain(F32 gain) | |||
177 | } | 168 | } |
178 | 169 | ||
179 | LLAudioChannelOpenAL::LLAudioChannelOpenAL() | 170 | LLAudioChannelOpenAL::LLAudioChannelOpenAL() |
171 | : | ||
172 | mALSource(AL_NONE), | ||
173 | mLastSamplePos(0) | ||
180 | { | 174 | { |
181 | alGenSources(1, &ALSource); | 175 | alGenSources(1, &mALSource); |
182 | } | 176 | } |
183 | 177 | ||
184 | LLAudioChannelOpenAL::~LLAudioChannelOpenAL() | 178 | LLAudioChannelOpenAL::~LLAudioChannelOpenAL() |
185 | { | 179 | { |
186 | cleanup(); | 180 | cleanup(); |
187 | alDeleteSources(1, &ALSource); | 181 | alDeleteSources(1, &mALSource); |
188 | } | 182 | } |
189 | 183 | ||
190 | void LLAudioChannelOpenAL::cleanup() | 184 | void LLAudioChannelOpenAL::cleanup() |
191 | { | 185 | { |
192 | alSourceStop(ALSource); | 186 | alSourceStop(mALSource); |
193 | mCurrentBufferp = NULL; | 187 | mCurrentBufferp = NULL; |
194 | } | 188 | } |
195 | 189 | ||
196 | void LLAudioChannelOpenAL::play() | 190 | void LLAudioChannelOpenAL::play() |
197 | { | 191 | { |
192 | if (mALSource == AL_NONE) | ||
193 | { | ||
194 | llwarns << "Playing without a mALSource, aborting" << llendl; | ||
195 | return; | ||
196 | } | ||
197 | |||
198 | if(!isPlaying()) | 198 | if(!isPlaying()) |
199 | { | 199 | { |
200 | alSourcePlay(ALSource); | 200 | alSourcePlay(mALSource); |
201 | getSource()->setPlayedOnce(TRUE); | 201 | getSource()->setPlayedOnce(true); |
202 | } | 202 | } |
203 | } | 203 | } |
204 | 204 | ||
205 | void LLAudioChannelOpenAL::playSynced(LLAudioChannel *channelp) | 205 | void LLAudioChannelOpenAL::playSynced(LLAudioChannel *channelp) |
206 | { | 206 | { |
207 | if (channelp) | ||
208 | { | ||
209 | LLAudioChannelOpenAL *masterchannelp = | ||
210 | (LLAudioChannelOpenAL*)channelp; | ||
211 | if (mALSource != AL_NONE && | ||
212 | masterchannelp->mALSource != AL_NONE) | ||
213 | { | ||
214 | // we have channels allocated to master and slave | ||
215 | ALfloat master_offset; | ||
216 | alGetSourcef(masterchannelp->mALSource, AL_SEC_OFFSET, | ||
217 | &master_offset); | ||
218 | |||
219 | llinfos << "Syncing with master at " << master_offset | ||
220 | << "sec" << llendl; | ||
221 | // *TODO: detect when this fails, maybe use AL_SAMPLE_ | ||
222 | alSourcef(mALSource, AL_SEC_OFFSET, master_offset); | ||
223 | } | ||
224 | } | ||
207 | play(); | 225 | play(); |
208 | } | 226 | } |
209 | 227 | ||
210 | bool LLAudioChannelOpenAL::isPlaying() | 228 | bool LLAudioChannelOpenAL::isPlaying() |
211 | { | 229 | { |
212 | ALint state; | 230 | if (mALSource != AL_NONE) |
213 | alGetSourcei(ALSource, AL_SOURCE_STATE, &state); | ||
214 | if(state == AL_PLAYING) | ||
215 | { | 231 | { |
216 | return TRUE; | 232 | ALint state; |
233 | alGetSourcei(mALSource, AL_SOURCE_STATE, &state); | ||
234 | if(state == AL_PLAYING) | ||
235 | { | ||
236 | return true; | ||
237 | } | ||
217 | } | 238 | } |
239 | |||
218 | return false; | 240 | return false; |
219 | } | 241 | } |
220 | 242 | ||
@@ -225,14 +247,48 @@ bool LLAudioChannelOpenAL::updateBuffer() | |||
225 | // Base class update returned true, which means that we need to actually | 247 | // Base class update returned true, which means that we need to actually |
226 | // set up the source for a different buffer. | 248 | // set up the source for a different buffer. |
227 | LLAudioBufferOpenAL *bufferp = (LLAudioBufferOpenAL *)mCurrentSourcep->getCurrentBuffer(); | 249 | LLAudioBufferOpenAL *bufferp = (LLAudioBufferOpenAL *)mCurrentSourcep->getCurrentBuffer(); |
228 | alSourcei(ALSource, AL_BUFFER, bufferp->getBuffer()); | 250 | ALuint buffer = bufferp->getBuffer(); |
229 | alSourcef(ALSource, AL_GAIN, mCurrentSourcep->getGain()); | 251 | alSourcei(mALSource, AL_BUFFER, buffer); |
230 | alSourcei(ALSource, AL_LOOPING, mCurrentSourcep->isLoop() ? AL_TRUE : AL_FALSE); | 252 | mLastSamplePos = 0; |
253 | } | ||
254 | |||
255 | if (mCurrentSourcep) | ||
256 | { | ||
257 | alSourcef(mALSource, AL_GAIN, | ||
258 | mCurrentSourcep->getGain() * getSecondaryGain()); | ||
259 | alSourcei(mALSource, AL_LOOPING, | ||
260 | mCurrentSourcep->isLoop() ? AL_TRUE : AL_FALSE); | ||
261 | alSourcef(mALSource, AL_ROLLOFF_FACTOR, | ||
262 | gAudiop->mListenerp->getRolloffFactor()); | ||
263 | alSourcef(mALSource, AL_REFERENCE_DISTANCE, | ||
264 | gAudiop->mListenerp->getDistanceFactor()); | ||
231 | } | 265 | } |
232 | 266 | ||
233 | return true; | 267 | return true; |
234 | } | 268 | } |
235 | 269 | ||
270 | |||
271 | void LLAudioChannelOpenAL::updateLoop() | ||
272 | { | ||
273 | if (mALSource == AL_NONE) | ||
274 | { | ||
275 | return; | ||
276 | } | ||
277 | |||
278 | // Hack: We keep track of whether we looped or not by seeing when the | ||
279 | // sample position looks like it's going backwards. Not reliable; may | ||
280 | // yield false negatives. | ||
281 | // | ||
282 | ALint cur_pos; | ||
283 | alGetSourcei(mALSource, AL_SAMPLE_OFFSET, &cur_pos); | ||
284 | if (cur_pos < mLastSamplePos) | ||
285 | { | ||
286 | mLoopedThisFrame = true; | ||
287 | } | ||
288 | mLastSamplePos = cur_pos; | ||
289 | } | ||
290 | |||
291 | |||
236 | void LLAudioChannelOpenAL::update3DPosition() | 292 | void LLAudioChannelOpenAL::update3DPosition() |
237 | { | 293 | { |
238 | if(!mCurrentSourcep) | 294 | if(!mCurrentSourcep) |
@@ -241,30 +297,25 @@ void LLAudioChannelOpenAL::update3DPosition() | |||
241 | } | 297 | } |
242 | if (mCurrentSourcep->isAmbient()) | 298 | if (mCurrentSourcep->isAmbient()) |
243 | { | 299 | { |
244 | alSource3f(ALSource, AL_POSITION, 0.0, 0.0, 0.0); | 300 | alSource3f(mALSource, AL_POSITION, 0.0, 0.0, 0.0); |
245 | alSource3f(ALSource, AL_VELOCITY, 0.0, 0.0, 0.0); | 301 | alSource3f(mALSource, AL_VELOCITY, 0.0, 0.0, 0.0); |
246 | //alSource3f(ALSource, AL_DIRECTION, 0.0, 0.0, 0.0); | 302 | //alSource3f(mALSource, AL_DIRECTION, 0.0, 0.0, 0.0); |
247 | alSourcef (ALSource, AL_ROLLOFF_FACTOR, 0.0); | 303 | alSourcei (mALSource, AL_SOURCE_RELATIVE, AL_TRUE); |
248 | alSourcei (ALSource, AL_SOURCE_RELATIVE, AL_TRUE); | 304 | } else { |
249 | } | ||
250 | else | ||
251 | { | ||
252 | LLVector3 float_pos; | 305 | LLVector3 float_pos; |
253 | float_pos.setVec(mCurrentSourcep->getPositionGlobal()); | 306 | float_pos.setVec(mCurrentSourcep->getPositionGlobal()); |
254 | alSourcefv(ALSource, AL_POSITION, float_pos.mV); | 307 | alSourcefv(mALSource, AL_POSITION, float_pos.mV); |
255 | //llinfos << "LLAudioChannelOpenAL::update3DPosition() Velocity: " << mCurrentSourcep->getVelocity() << llendl; | 308 | alSourcefv(mALSource, AL_VELOCITY, mCurrentSourcep->getVelocity().mV); |
256 | alSourcefv(ALSource, AL_VELOCITY, mCurrentSourcep->getVelocity().mV); | 309 | //alSource3f(mALSource, AL_DIRECTION, 0.0, 0.0, 0.0); |
257 | //alSource3f(ALSource, AL_DIRECTION, 0.0, 0.0, 0.0); | 310 | alSourcei (mALSource, AL_SOURCE_RELATIVE, AL_FALSE); |
258 | alSourcef (ALSource, AL_ROLLOFF_FACTOR, 1.0); | ||
259 | alSourcei (ALSource, AL_SOURCE_RELATIVE, AL_FALSE); | ||
260 | } | 311 | } |
261 | //llinfos << "LLAudioChannelOpenAL::update3DPosition() Gain: " << mCurrentSourcep->getGain() << llendl; | 312 | |
262 | alSourcef(ALSource, AL_GAIN, mCurrentSourcep->getGain()); | 313 | alSourcef(mALSource, AL_GAIN, mCurrentSourcep->getGain() * getSecondaryGain()); |
263 | } | 314 | } |
264 | 315 | ||
265 | LLAudioBufferOpenAL::LLAudioBufferOpenAL() | 316 | LLAudioBufferOpenAL::LLAudioBufferOpenAL() |
266 | { | 317 | { |
267 | ALBuffer = AL_NONE; | 318 | mALBuffer = AL_NONE; |
268 | } | 319 | } |
269 | 320 | ||
270 | LLAudioBufferOpenAL::~LLAudioBufferOpenAL() | 321 | LLAudioBufferOpenAL::~LLAudioBufferOpenAL() |
@@ -274,33 +325,49 @@ LLAudioBufferOpenAL::~LLAudioBufferOpenAL() | |||
274 | 325 | ||
275 | void LLAudioBufferOpenAL::cleanup() | 326 | void LLAudioBufferOpenAL::cleanup() |
276 | { | 327 | { |
277 | if(ALBuffer != AL_NONE) | 328 | if(mALBuffer != AL_NONE) |
278 | { | 329 | { |
279 | alDeleteBuffers(1, &ALBuffer); | 330 | alDeleteBuffers(1, &mALBuffer); |
331 | mALBuffer = AL_NONE; | ||
280 | } | 332 | } |
281 | } | 333 | } |
282 | 334 | ||
283 | bool LLAudioBufferOpenAL::loadWAV(const std::string& filename) | 335 | bool LLAudioBufferOpenAL::loadWAV(const std::string& filename) |
284 | { | 336 | { |
285 | cleanup(); | 337 | cleanup(); |
286 | ALBuffer = alutCreateBufferFromFile(filename.c_str()); | 338 | mALBuffer = alutCreateBufferFromFile(filename.c_str()); |
287 | if(ALBuffer == AL_NONE) | 339 | if(mALBuffer == AL_NONE) |
288 | { | 340 | { |
289 | return FALSE; | 341 | ALenum error = alutGetError(); |
342 | if (gDirUtilp->fileExists(filename)) | ||
343 | { | ||
344 | llwarns << | ||
345 | "LLAudioBufferOpenAL::loadWAV() Error loading " | ||
346 | << filename | ||
347 | << " " << alutGetErrorString(error) << llendl; | ||
348 | } | ||
349 | else | ||
350 | { | ||
351 | // It's common for the file to not actually exist. | ||
352 | lldebugs << | ||
353 | "LLAudioBufferOpenAL::loadWAV() Error loading " | ||
354 | << filename | ||
355 | << " " << alutGetErrorString(error) << llendl; | ||
356 | } | ||
357 | return false; | ||
290 | } | 358 | } |
291 | 359 | ||
292 | return true; | 360 | return true; |
293 | } | 361 | } |
294 | 362 | ||
295 | |||
296 | U32 LLAudioBufferOpenAL::getLength() | 363 | U32 LLAudioBufferOpenAL::getLength() |
297 | { | 364 | { |
298 | if(ALBuffer == AL_NONE) | 365 | if(mALBuffer == AL_NONE) |
299 | { | 366 | { |
300 | return 0; | 367 | return 0; |
301 | } | 368 | } |
302 | ALint length; | 369 | ALint length; |
303 | alGetBufferi(ALBuffer, AL_SIZE, &length); | 370 | alGetBufferi(mALBuffer, AL_SIZE, &length); |
304 | return length >> 2; | 371 | return length >> 2; |
305 | } | 372 | } |
306 | 373 | ||
@@ -308,65 +375,78 @@ U32 LLAudioBufferOpenAL::getLength() | |||
308 | 375 | ||
309 | void LLAudioEngine_OpenAL::initWind() | 376 | void LLAudioEngine_OpenAL::initWind() |
310 | { | 377 | { |
378 | ALenum error; | ||
379 | llinfos << "LLAudioEngine_OpenAL::initWind() start" << llendl; | ||
311 | 380 | ||
312 | if (true) | 381 | mNumEmptyWindALBuffers = MAX_NUM_WIND_BUFFERS; |
313 | return; | ||
314 | |||
315 | llinfos << "initWind() start" << llendl; | ||
316 | 382 | ||
317 | alGenBuffers(mNumWindBuffers,mWindBuffers); | 383 | alGetError(); /* clear error */ |
384 | |||
318 | alGenSources(1,&mWindSource); | 385 | alGenSources(1,&mWindSource); |
319 | checkALError(); | 386 | |
320 | 387 | if((error=alGetError()) != AL_NO_ERROR) | |
321 | // ok lets make a wind buffer now | ||
322 | for(int counter=0;counter<mNumWindBuffers;counter++) | ||
323 | { | 388 | { |
324 | 389 | llwarns << "LLAudioEngine_OpenAL::initWind() Error creating wind sources: "<<error<<llendl; | |
325 | alBufferData(mWindBuffers[counter],AL_FORMAT_STEREO16,windDSP((void*)mWindData,mWindDataSize/mBytesPerSample),mWindDataSize,mSampleRate); | ||
326 | checkALError(); | ||
327 | } | 390 | } |
328 | 391 | ||
329 | alSourceQueueBuffers(mWindSource, mNumWindBuffers, mWindBuffers); | 392 | mWindGen = new LLWindGen<WIND_SAMPLE_T>; |
330 | checkALError(); | ||
331 | 393 | ||
332 | alSourcePlay(mWindSource); | 394 | mWindBufFreq = mWindGen->getInputSamplingRate(); |
333 | checkALError(); | 395 | mWindBufSamples = llceil(mWindBufFreq * WIND_BUFFER_SIZE_SEC); |
396 | mWindBufBytes = mWindBufSamples * 2 /*stereo*/ * sizeof(WIND_SAMPLE_T); | ||
334 | 397 | ||
335 | llinfos << "LLAudioEngine_OpenAL::initWind() done" << llendl; | 398 | mWindBuf = new WIND_SAMPLE_T [mWindBufSamples * 2 /*stereo*/]; |
336 | 399 | ||
400 | if(mWindBuf==NULL) | ||
401 | { | ||
402 | llerrs << "LLAudioEngine_OpenAL::initWind() Error creating wind memory buffer" << llendl; | ||
403 | mEnableWind=false; | ||
404 | } | ||
405 | |||
406 | llinfos << "LLAudioEngine_OpenAL::initWind() done" << llendl; | ||
337 | } | 407 | } |
338 | 408 | ||
339 | void LLAudioEngine_OpenAL::cleanupWind(){ | 409 | void LLAudioEngine_OpenAL::cleanupWind() |
410 | { | ||
340 | llinfos << "LLAudioEngine_OpenAL::cleanupWind()" << llendl; | 411 | llinfos << "LLAudioEngine_OpenAL::cleanupWind()" << llendl; |
341 | 412 | ||
342 | alDeleteBuffers(mNumWindBuffers,mWindBuffers); | 413 | if (mWindSource != AL_NONE) |
343 | alDeleteSources(1, &mWindSource); | 414 | { |
415 | // detach and delete all outstanding buffers on the wind source | ||
416 | alSourceStop(mWindSource); | ||
417 | int processed; | ||
418 | alGetSourcei(mWindSource, AL_BUFFERS_PROCESSED, &processed); | ||
419 | while (processed--) | ||
420 | { | ||
421 | ALuint buffer = AL_NONE; | ||
422 | alSourceUnqueueBuffers(mWindSource, 1, &buffer); | ||
423 | alDeleteBuffers(1, &buffer); | ||
424 | } | ||
344 | 425 | ||
345 | checkALError(); | 426 | // delete the wind source itself |
346 | } | 427 | alDeleteSources(1, &mWindSource); |
347 | 428 | ||
348 | void LLAudioEngine_OpenAL::checkALError() | 429 | mWindSource = AL_NONE; |
349 | { | 430 | } |
350 | ALenum error; | 431 | |
351 | if((error=alGetError()) != AL_NO_ERROR) | 432 | delete[] mWindBuf; |
352 | llwarns << "LLAudioEngine_OpenAL Error: "<<error<<llendl; | 433 | mWindBuf = NULL; |
353 | 434 | ||
435 | delete mWindGen; | ||
436 | mWindGen = NULL; | ||
354 | } | 437 | } |
355 | 438 | ||
356 | void LLAudioEngine_OpenAL::updateWind(LLVector3 wind_vec, F32 camera_altitude) | 439 | void LLAudioEngine_OpenAL::updateWind(LLVector3 wind_vec, F32 camera_altitude) |
357 | { | 440 | { |
358 | |||
359 | if (true) | ||
360 | return; | ||
361 | |||
362 | LLVector3 wind_pos; | 441 | LLVector3 wind_pos; |
363 | F32 pitch; | 442 | F64 pitch; |
364 | F32 center_freq; | 443 | F64 center_freq; |
365 | 444 | ALenum error; | |
445 | |||
366 | if (!mEnableWind) | 446 | if (!mEnableWind) |
367 | return; | 447 | return; |
368 | 448 | ||
369 | if(!mWindData) | 449 | if(!mWindBuf) |
370 | return; | 450 | return; |
371 | 451 | ||
372 | if (mWindUpdateTimer.checkExpirationAndReset(LL_WIND_UPDATE_INTERVAL)) | 452 | if (mWindUpdateTimer.checkExpirationAndReset(LL_WIND_UPDATE_INTERVAL)) |
@@ -377,385 +457,88 @@ void LLAudioEngine_OpenAL::updateWind(LLVector3 wind_vec, F32 camera_altitude) | |||
377 | // where +X = right, +Y = up, +Z = backwards | 457 | // where +X = right, +Y = up, +Z = backwards |
378 | 458 | ||
379 | wind_vec.setVec(-wind_vec.mV[1], wind_vec.mV[2], -wind_vec.mV[0]); | 459 | wind_vec.setVec(-wind_vec.mV[1], wind_vec.mV[2], -wind_vec.mV[0]); |
380 | 460 | ||
381 | 461 | pitch = 1.0 + mapWindVecToPitch(wind_vec); | |
382 | pitch = 1.0f + mapWindVecToPitch(wind_vec); | 462 | center_freq = 80.0 * pow(pitch,2.5*(mapWindVecToGain(wind_vec)+1.0)); |
383 | center_freq = 80.0f * powf(pitch,2.5f*(mapWindVecToGain(wind_vec)+1.0f)); | 463 | |
384 | 464 | mWindGen->mTargetFreq = (F32)center_freq; | |
385 | //TESTING | 465 | mWindGen->mTargetGain = (F32)mapWindVecToGain(wind_vec) * mMaxWindGain; |
386 | mMaxWindGain=1.0; | 466 | mWindGen->mTargetPanGainR = (F32)mapWindVecToPan(wind_vec); |
387 | 467 | ||
388 | mTargetFreq = center_freq; | ||
389 | mTargetGain = (F32)mapWindVecToGain(wind_vec) * mMaxWindGain; | ||
390 | mTargetPanGainR = (F32)mapWindVecToPan(wind_vec); | ||
391 | |||
392 | ALfloat source0Pos[]={mListenerp->getPosition().mV[0],mListenerp->getPosition().mV[1],mListenerp->getPosition().mV[2]}; | ||
393 | ALfloat source0Vel[]={ 0.0, 0.0, 0.0}; | ||
394 | |||
395 | alSourcef(mWindSource, AL_GAIN, mTargetGain); | ||
396 | alSourcef(mWindSource, AL_PITCH, pitch); | ||
397 | alSourcefv(mWindSource, AL_POSITION, source0Pos); | ||
398 | alSourcefv(mWindSource, AL_VELOCITY, source0Vel); | ||
399 | alSourcei(mWindSource, AL_LOOPING, AL_FALSE); | 468 | alSourcei(mWindSource, AL_LOOPING, AL_FALSE); |
400 | 469 | alSource3f(mWindSource, AL_POSITION, 0.0, 0.0, 0.0); | |
401 | } | 470 | alSource3f(mWindSource, AL_VELOCITY, 0.0, 0.0, 0.0); |
402 | 471 | alSourcef(mWindSource, AL_ROLLOFF_FACTOR, 0.0); | |
403 | int processed; | 472 | alSourcei(mWindSource, AL_SOURCE_RELATIVE, AL_TRUE); |
404 | alGetSourcei(mWindSource, AL_BUFFERS_PROCESSED, &processed); | ||
405 | |||
406 | while(processed--) | ||
407 | { | ||
408 | ALuint buffer; | ||
409 | alSourceUnqueueBuffers(mWindSource, 1, &buffer); | ||
410 | checkALError(); | ||
411 | alBufferData(buffer,AL_FORMAT_STEREO16,windDSP((void*)mWindData,mWindDataSize/mBytesPerSample),mWindDataSize,mSampleRate); | ||
412 | checkALError(); | ||
413 | alSourceQueueBuffers(mWindSource, 1, &buffer); | ||
414 | checkALError(); | ||
415 | } | 473 | } |
416 | 474 | ||
417 | int playing; | 475 | // ok lets make a wind buffer now |
418 | alGetSourcei(mWindSource, AL_SOURCE_STATE, &playing); | ||
419 | if(playing==AL_STOPPED) | ||
420 | alSourcePlay(mWindSource); | ||
421 | |||
422 | checkALError(); | ||
423 | } | ||
424 | |||
425 | |||
426 | void * LLAudioEngine_OpenAL::windDSP(void *newbuffer, int length) | ||
427 | { | ||
428 | // *NOTE: This function gets called a *lot*. | ||
429 | // Keep performance in mind if you mess with this. | ||
430 | // newbuffer = the buffer being constructed | ||
431 | // length = length in samples of the buffer | ||
432 | |||
433 | |||
434 | //clear the buffer | ||
435 | memset(newbuffer, 0, length*mBytesPerSample); | ||
436 | |||
437 | // This turns off wind synth if it is muted or very very low volume | ||
438 | if (mTargetGain < 0.0005f) | ||
439 | { | ||
440 | llinfos << "Wind off" << llendl; | ||
441 | return newbuffer; | ||
442 | } | ||
443 | |||
444 | static const U8 SUBSAMPLES = 2; | ||
445 | static const F32 FILTER_SAMPLE_PERIOD = (F32)SUBSAMPLES / float(mSampleRate); | ||
446 | static const F32 BANDWIDTH = 50.0f; | ||
447 | static const F32 B2 = expf(-F_TWO_PI * BANDWIDTH * FILTER_SAMPLE_PERIOD); | ||
448 | |||
449 | static F32 pinking_buf0 = 0.0f; | ||
450 | static F32 pinking_buf1 = 0.0f; | ||
451 | static F32 pinking_buf2 = 0.0f; | ||
452 | static F32 Y0 = 0.0f; | ||
453 | static F32 Y1 = 0.0f; | ||
454 | static F32 last_sample = 0.0f; | ||
455 | static F32 current_freq = 0.0f; | ||
456 | static F32 current_gain = 0.0f; | ||
457 | static F32 current_pan_gain_r = 0.0f; | ||
458 | |||
459 | F32 a0 = 0.0f, b1 = 0.0f; | ||
460 | |||
461 | U8 *cursamplep = (U8*)newbuffer; | ||
462 | |||
463 | //we assume 16-bit samples, because the ALUT specification maxes out there | ||
464 | U8 wordsize = 2; | ||
465 | |||
466 | bool interp_freq = false; | ||
467 | |||
468 | //if the frequency isn't changing much, we don't need to interpolate in the inner loop | ||
469 | if (llabs(mTargetFreq - current_freq) > 200.0f) | ||
470 | { | ||
471 | interp_freq = true; | ||
472 | } | ||
473 | else | ||
474 | { | ||
475 | // calculate resonant filter coefficients | ||
476 | current_freq = mTargetFreq; | ||
477 | b1 = (-4.0f * B2) / (1.0f + B2) * cosf(F_TWO_PI * (current_freq * FILTER_SAMPLE_PERIOD)); | ||
478 | a0 = (1.0f - B2) * sqrtf(1.0f - (b1 * b1) / (4.0f * B2)); | ||
479 | } | ||
480 | |||
481 | while (length) | ||
482 | { | ||
483 | F32 next_sample; | ||
484 | |||
485 | // Start with white noise [-16384, 16383] | ||
486 | next_sample = (F32)rand() * (1.0f / (F32)(RAND_MAX / (U16_MAX / 4))) + (S16_MIN / 4); | ||
487 | |||
488 | // Apply a pinking filter | ||
489 | // Magic numbers taken from PKE method at http://www.firstpr.com.au/dsp/pink-noise/ | ||
490 | pinking_buf0 = pinking_buf0 * 0.99765f + next_sample * 0.0990460f; | ||
491 | pinking_buf1 = pinking_buf1 * 0.96300f + next_sample * 0.2965164f; | ||
492 | pinking_buf2 = pinking_buf2 * 0.57000f + next_sample * 1.0526913f; | ||
493 | |||
494 | next_sample = pinking_buf0 + pinking_buf1 + pinking_buf2 + next_sample * 0.1848f; | ||
495 | |||
496 | if (interp_freq) | ||
497 | { | ||
498 | // calculate resonant filter coefficients | ||
499 | current_freq = (0.999f * current_freq) + (0.001f * mTargetFreq); | ||
500 | b1 = (-4.0f * B2) / (1.0f + B2) * cosf(F_TWO_PI * (current_freq * FILTER_SAMPLE_PERIOD)); | ||
501 | a0 = (1.0f - B2) * sqrtf(1.0f - (b1 * b1) / (4.0f * B2)); | ||
502 | } | ||
503 | |||
504 | // Apply a resonant low-pass filter on the pink noise | ||
505 | next_sample = ( a0 * next_sample - b1 * Y0 - B2 * Y1 ); | ||
506 | |||
507 | Y1 = Y0; | ||
508 | Y0 = next_sample; | ||
509 | |||
510 | current_gain = (0.999f * current_gain) + (0.001f * mTargetGain); | ||
511 | current_pan_gain_r = (0.999f * current_pan_gain_r) + (0.001f * mTargetPanGainR); | ||
512 | |||
513 | next_sample *= current_gain; | ||
514 | F32 delta = (next_sample - last_sample) / (F32)SUBSAMPLES; | ||
515 | |||
516 | S32 sample_left; | ||
517 | S32 sample_right; | ||
518 | |||
519 | // Mix into the audio buffer, clipping if necessary for 16-bit mix buffers. | ||
520 | // *TODO: Should do something more intelligent like reducing wind gain to avoid clipping | ||
521 | for (int i=SUBSAMPLES; i && length; --i, --length) | ||
522 | { | ||
523 | last_sample = last_sample + delta; | ||
524 | sample_right = (S32)(last_sample * current_pan_gain_r); | ||
525 | sample_left = (S32)(last_sample - sample_right); | ||
526 | |||
527 | *(S16*)cursamplep = llclamp(sample_left, S16_MIN, S16_MAX); | ||
528 | cursamplep += wordsize; | ||
529 | |||
530 | *(S16*)cursamplep = llclamp(sample_right, S16_MIN, S16_MAX); | ||
531 | cursamplep += wordsize; | ||
532 | } | ||
533 | } | ||
534 | return newbuffer; | ||
535 | |||
536 | } | ||
537 | |||
538 | |||
539 | |||
540 | |||
541 | /* | ||
542 | |||
543 | |||
544 | |||
545 | |||
546 | // newbuffer = the buffer passed from the previous DSP unit. | ||
547 | // length = length in samples at this mix time. | ||
548 | |||
549 | U8 *cursamplep = (U8*)newbuffer; | ||
550 | U8 wordsize = 2; | ||
551 | |||
552 | double bandwidth = 50; | ||
553 | double inputSamplingRate = 44100; | ||
554 | double a0,b1,b2; | ||
555 | |||
556 | // calculate resonant filter coeffs | ||
557 | b2 = exp(-(F_TWO_PI) * (bandwidth / inputSamplingRate)); | ||
558 | |||
559 | while (length--) | ||
560 | { | ||
561 | gCurrentFreq = (float)((0.999 * gCurrentFreq) + (0.001 * gTargetFreq)); | ||
562 | gCurrentGain = (float)((0.999 * gCurrentGain) + (0.001 * gTargetGain)); | ||
563 | gCurrentPanGainR = (float)((0.999 * gCurrentPanGainR) + (0.001 * gTargetPanGainR)); | ||
564 | b1 = (-4.0 * b2) / (1.0 + b2) * cos(F_TWO_PI * (gCurrentFreq / inputSamplingRate)); | ||
565 | a0 = (1.0 - b2) * sqrt(1.0 - (b1 * b1) / (4.0 * b2)); | ||
566 | double nextSample; | ||
567 | |||
568 | // start with white noise | ||
569 | nextSample = ll_frand(2.0f) - 1.0f; | ||
570 | |||
571 | gbuf0 = 0.997f * gbuf0 + 0.0126502f * nextSample; | ||
572 | gbuf1 = 0.985f * gbuf1 + 0.0139083f * nextSample; | ||
573 | gbuf2 = 0.950f * gbuf2 + 0.0205439f * nextSample; | ||
574 | gbuf3 = 0.850f * gbuf3 + 0.0387225f * nextSample; | ||
575 | gbuf4 = 0.620f * gbuf4 + 0.0465932f * nextSample; | ||
576 | gbuf5 = 0.250f * gbuf5 + 0.1093477f * nextSample; | ||
577 | |||
578 | nextSample = gbuf0 + gbuf1 + gbuf2 + gbuf3 + gbuf4 + gbuf5; | ||
579 | |||
580 | nextSample = (double)( a0 * nextSample - b1 * gY0 - b2 * gY1 ); | ||
581 | |||
582 | gY1 = gY0; | ||
583 | gY0 = nextSample; | ||
584 | nextSample *= gCurrentGain; | ||
585 | |||
586 | S16 sample; | ||
587 | |||
588 | sample = llfloor(((F32)nextSample*32768.f*(1.0f - gCurrentPanGainR))+0.5f); | ||
589 | *(S16*)cursamplep = clipSample(sample, -32768, 32767); | ||
590 | |||
591 | cursamplep += wordsize; | ||
592 | |||
593 | sample = llfloor(((F32)nextSample*32768.f*gCurrentPanGainR)+0.5f); | ||
594 | |||
595 | sample = llfloor(((F32)nextSample*32768.f*gCurrentPanGainR)+0.5f); | ||
596 | *(S16*)cursamplep = clipSample(sample, -32768, 32767); | ||
597 | cursamplep += wordsize; | ||
598 | } | ||
599 | |||
600 | return newbuffer; | ||
601 | } | ||
602 | */ | ||
603 | |||
604 | // ------------ | ||
605 | |||
606 | void LLAudioEngine_OpenAL::InitStreamer() | ||
607 | { | ||
608 | #if LL_GSTREAMER_ENABLED | ||
609 | m_streamer=new LLMediaImplGStreamer (); | ||
610 | |||
611 | if(!m_streamer) | ||
612 | { | ||
613 | llwarns << "LLAudioEngine_OpenAL::LLAudioEngine_OpenAL() Failed to create our private gstreamer audio instance" << llendl; | ||
614 | } | ||
615 | |||
616 | if(m_streamer) | ||
617 | { | ||
618 | m_streamer->init (); | ||
619 | } | ||
620 | #endif | ||
621 | } | ||
622 | |||
623 | |||
624 | // ------------ | ||
625 | |||
626 | void LLAudioEngine_OpenAL::initInternetStream() | ||
627 | { | ||
628 | if(!mInternetStreamURL.empty()) | ||
629 | mInternetStreamURL.erase(); | ||
630 | } | ||
631 | |||
632 | |||
633 | void LLAudioEngine_OpenAL::startInternetStream(const std::string& url_cstr) | ||
634 | { | ||
635 | |||
636 | std::string url(url_cstr); | ||
637 | |||
638 | #if LL_GSTREAMER_ENABLED | ||
639 | if(!m_streamer) | ||
640 | return; | ||
641 | // DCF_DEBUG | ||
642 | llinfos << "entered LLAudioEngine_OpenAL::startInternetStream()" << llendl; | ||
643 | |||
644 | if (!url.empty()) | ||
645 | { | ||
646 | llinfos << "LLAudioEngine_OpenAL::startInternetStream() Starting internet stream: " << url << llendl; | ||
647 | mInternetStreamURL=url; | ||
648 | m_streamer->navigateTo ( url ); | ||
649 | llinfos << "Playing....." << llendl; | ||
650 | m_streamer->addCommand(LLMediaBase::COMMAND_START); | ||
651 | m_streamer->updateMedia(); | ||
652 | |||
653 | } | ||
654 | else | ||
655 | { | ||
656 | llinfos << "LLAudioEngine_OpenAL setting stream to NULL"<< llendl; | ||
657 | mInternetStreamURL.erase(); | ||
658 | m_streamer->addCommand(LLMediaBase::COMMAND_STOP); | ||
659 | m_streamer->updateMedia(); | ||
660 | } | ||
661 | #endif | ||
662 | } | ||
663 | |||
664 | |||
665 | void LLAudioEngine_OpenAL::updateInternetStream() | ||
666 | { | ||
667 | // DCF_DEBUG | ||
668 | llinfos << "entered LLAudioEngine_OpenAL::updateInternetStream()" << llendl; | ||
669 | |||
670 | } | ||
671 | |||
672 | |||
673 | void LLAudioEngine_OpenAL::stopInternetStream() | ||
674 | { | ||
675 | // DCF_DEBUG | ||
676 | llinfos << "entered LLAudioEngine_OpenAL::stopInternetStream()" << llendl; | ||
677 | 476 | ||
678 | #if LL_GSTREAMER_ENABLED | 477 | int processed, queued, unprocessed; |
679 | if( ! m_streamer->addCommand(LLMediaBase::COMMAND_STOP)) | 478 | alGetSourcei(mWindSource, AL_BUFFERS_PROCESSED, &processed); |
680 | { | 479 | alGetSourcei(mWindSource, AL_BUFFERS_QUEUED, &queued); |
681 | llinfos << "attempting to stop stream failed!" << llendl; | 480 | unprocessed = queued - processed; |
682 | } | ||
683 | m_streamer->updateMedia(); | ||
684 | #endif | ||
685 | mInternetStreamURL.erase(); | ||
686 | } | ||
687 | 481 | ||
482 | // ensure that there are always at least 3x as many filled buffers | ||
483 | // queued as we managed to empty since last time. | ||
484 | mNumEmptyWindALBuffers = llmin(mNumEmptyWindALBuffers + processed * 3 - unprocessed, MAX_NUM_WIND_BUFFERS-unprocessed); | ||
485 | mNumEmptyWindALBuffers = llmax(mNumEmptyWindALBuffers, 0); | ||
688 | 486 | ||
689 | void LLAudioEngine_OpenAL::pauseInternetStream(int pause) | 487 | //llinfos << "mNumEmptyWindALBuffers: " << mNumEmptyWindALBuffers <<" (" << unprocessed << ":" << processed << ")" << llendl; |
690 | { | ||
691 | #if LL_GSTREAMER_ENABLED | ||
692 | if(!m_streamer) | ||
693 | return; | ||
694 | // DCF_DEBUG | ||
695 | llinfos << "entered LLAudioEngine_OpenAL::pauseInternetStream()" << llendl; | ||
696 | 488 | ||
697 | if(pause) | 489 | while(processed--) // unqueue old buffers |
698 | { | 490 | { |
699 | if(!m_streamer->addCommand(LLMediaBase::COMMAND_PAUSE)) | 491 | ALuint buffer; |
492 | int error; | ||
493 | alGetError(); /* clear error */ | ||
494 | alSourceUnqueueBuffers(mWindSource, 1, &buffer); | ||
495 | error = alGetError(); | ||
496 | if(error != AL_NO_ERROR) | ||
700 | { | 497 | { |
701 | llinfos << "attempting to pause stream failed!" << llendl; | 498 | llwarns << "LLAudioEngine_OpenAL::updateWind() error swapping (unqueuing) buffers" << llendl; |
702 | } | 499 | } |
703 | m_streamer->updateMedia(); | 500 | else |
704 | } | ||
705 | else | ||
706 | { | ||
707 | if( ! m_streamer->addCommand(LLMediaBase::COMMAND_START)) | ||
708 | { | 501 | { |
709 | llinfos << "attempting to pause stream failed!" << llendl; | 502 | alDeleteBuffers(1, &buffer); |
710 | } | 503 | } |
711 | m_streamer->updateMedia(); | ||
712 | } | 504 | } |
713 | #endif | ||
714 | } | ||
715 | |||
716 | 505 | ||
717 | int LLAudioEngine_OpenAL::isInternetStreamPlaying() | 506 | unprocessed += mNumEmptyWindALBuffers; |
718 | { | 507 | while (mNumEmptyWindALBuffers > 0) // fill+queue new buffers |
508 | { | ||
509 | ALuint buffer; | ||
510 | alGetError(); /* clear error */ | ||
511 | alGenBuffers(1,&buffer); | ||
512 | if((error=alGetError()) != AL_NO_ERROR) | ||
513 | { | ||
514 | llwarns << "LLAudioEngine_OpenAL::initWind() Error creating wind buffer: " << error << llendl; | ||
515 | break; | ||
516 | } | ||
719 | 517 | ||
720 | #if LL_GSTREAMER_ENABLED | 518 | alBufferData(buffer, |
721 | if(!m_streamer) | 519 | AL_FORMAT_STEREO16, |
722 | return 0; | 520 | mWindGen->windGenerate(mWindBuf, |
521 | mWindBufSamples, 2), | ||
522 | mWindBufBytes, | ||
523 | mWindBufFreq); | ||
524 | error = alGetError(); | ||
525 | if(error != AL_NO_ERROR) | ||
526 | llwarns << "LLAudioEngine_OpenAL::updateWind() error swapping (bufferdata) buffers" << llendl; | ||
527 | |||
528 | alSourceQueueBuffers(mWindSource, 1, &buffer); | ||
529 | error = alGetError(); | ||
530 | if(error != AL_NO_ERROR) | ||
531 | llwarns << "LLAudioEngine_OpenAL::updateWind() error swapping (queuing) buffers" << llendl; | ||
723 | 532 | ||
724 | if(m_streamer->getStatus() == LLMediaBase::STATUS_STARTED) | 533 | --mNumEmptyWindALBuffers; |
725 | { | ||
726 | return 1; // Active and playing | ||
727 | } | 534 | } |
728 | 535 | ||
729 | if(m_streamer->getStatus() == LLMediaBase::STATUS_PAUSED) | 536 | int playing; |
537 | alGetSourcei(mWindSource, AL_SOURCE_STATE, &playing); | ||
538 | if(playing != AL_PLAYING) | ||
730 | { | 539 | { |
731 | return 2; // paused | 540 | alSourcePlay(mWindSource); |
732 | } | ||
733 | |||
734 | #endif | ||
735 | return 0; // Stopped | ||
736 | } | ||
737 | |||
738 | |||
739 | void LLAudioEngine_OpenAL::getInternetStreamInfo(char* artist_out, char* title_out) | ||
740 | { | ||
741 | } | ||
742 | |||
743 | |||
744 | void LLAudioEngine_OpenAL::setInternetStreamGain(F32 vol) | ||
745 | { | ||
746 | #if LL_GSTREAMER_ENABLED | ||
747 | // Set the gstreamer volume here | ||
748 | if(!m_streamer) | ||
749 | return; | ||
750 | |||
751 | vol = llclamp(vol, 0.f, 1.f); | ||
752 | m_streamer->setVolume(vol); | ||
753 | m_streamer->updateMedia(); | ||
754 | #endif | ||
755 | } | ||
756 | |||
757 | 541 | ||
758 | const std::string& LLAudioEngine_OpenAL::getInternetStreamURL() | 542 | llinfos << "Wind had stopped - probably ran out of buffers - restarting: " << (unprocessed+mNumEmptyWindALBuffers) << " now queued." << llendl; |
759 | { | 543 | } |
760 | return mInternetStreamURL; | ||
761 | } | 544 | } |
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 @@ | |||
3 | * @brief implementation of audio engine using OpenAL | 3 | * @brief implementation of audio engine using OpenAL |
4 | * support as a OpenAL 3D implementation | 4 | * support as a OpenAL 3D implementation |
5 | * | 5 | * |
6 | * Copyright (c) 2002-2008, Linden Research, Inc. | ||
7 | * | 6 | * |
8 | * $LicenseInfo:firstyear=2002&license=viewergpl$ | 7 | * $LicenseInfo:firstyear=2002&license=viewergpl$ |
9 | * | 8 | * |
9 | * Copyright (c) 2002-2008, Linden Research, Inc. | ||
10 | * | ||
10 | * Second Life Viewer Source Code | 11 | * Second Life Viewer Source Code |
11 | * The source code in this file ("Source Code") is provided by Linden Lab | 12 | * The source code in this file ("Source Code") is provided by Linden Lab |
12 | * to you under the terms of the GNU General Public License, version 2.0 | 13 | * to you under the terms of the GNU General Public License, version 2.0 |
13 | * ("GPL"), unless you have obtained a separate licensing agreement | 14 | * ("GPL"), unless you have obtained a separate licensing agreement |
14 | * ("Other License"), formally executed by you and Linden Lab. Terms of | 15 | * ("Other License"), formally executed by you and Linden Lab. Terms of |
15 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | 16 | * the GPL can be found in doc/GPL-license.txt in this distribution, or |
16 | * online at http://secondlife.com/developers/opensource/gplv2 | 17 | * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 |
17 | * | 18 | * |
18 | * There are special exceptions to the terms and conditions of the GPL as | 19 | * There are special exceptions to the terms and conditions of the GPL as |
19 | * it is applied to this Source Code. View the full text of the exception | 20 | * it is applied to this Source Code. View the full text of the exception |
20 | * in the file doc/FLOSS-exception.txt in this software distribution, or | 21 | * in the file doc/FLOSS-exception.txt in this software distribution, or |
21 | * online at http://secondlife.com/developers/opensource/flossexception | 22 | * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception |
22 | * | 23 | * |
23 | * By copying, modifying or distributing this software, you acknowledge | 24 | * By copying, modifying or distributing this software, you acknowledge |
24 | * that you have read and understood your obligations described above, | 25 | * that you have read and understood your obligations described above, |
25 | * and agree to abide by those obligations. | 26 | * and agree to abide by those obligations. |
26 | * | 27 | * |
27 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | 28 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO |
28 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | 29 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, |
29 | * COMPLETENESS OR PERFORMANCE. | 30 | * COMPLETENESS OR PERFORMANCE. |
@@ -31,16 +32,12 @@ | |||
31 | */ | 32 | */ |
32 | 33 | ||
33 | 34 | ||
34 | #ifndef LL_AUDIOENGINE_OpenAL_H | 35 | #ifndef LL_AUDIOENGINE_OPENAL_H |
35 | #define LL_AUDIOENGINE_OpenAL_H | 36 | #define LL_AUDIOENGINE_OPENAL_H |
36 | |||
37 | #include <string> | ||
38 | 37 | ||
39 | #include "audioengine.h" | 38 | #include "audioengine.h" |
40 | #include "listener_openal.h" | 39 | #include "listener_openal.h" |
41 | #include "llmediamanager.h" | 40 | #include "windgen.h" |
42 | #include "llmediaimplgstreamer.h" | ||
43 | #include "llrand.h" | ||
44 | 41 | ||
45 | class LLAudioEngine_OpenAL : public LLAudioEngine | 42 | class LLAudioEngine_OpenAL : public LLAudioEngine |
46 | { | 43 | { |
@@ -48,58 +45,34 @@ class LLAudioEngine_OpenAL : public LLAudioEngine | |||
48 | LLAudioEngine_OpenAL(); | 45 | LLAudioEngine_OpenAL(); |
49 | virtual ~LLAudioEngine_OpenAL(); | 46 | virtual ~LLAudioEngine_OpenAL(); |
50 | 47 | ||
51 | virtual BOOL init(const S32 num_channels); | 48 | virtual bool init(const S32 num_channels, void *user_data); |
52 | virtual std::string getDriverName(bool verbose); | 49 | virtual std::string getDriverName(bool verbose); |
53 | virtual void allocateListener(); | 50 | virtual void allocateListener(); |
54 | 51 | ||
55 | virtual void shutdown(); | 52 | virtual void shutdown(); |
56 | 53 | ||
57 | virtual void idle(F32 max_decode_time = 0.f); | ||
58 | |||
59 | void setInternalGain(F32 gain); | 54 | void setInternalGain(F32 gain); |
60 | 55 | ||
61 | LLAudioBuffer* createBuffer(); | 56 | LLAudioBuffer* createBuffer(); |
62 | LLAudioChannel* createChannel(); | 57 | LLAudioChannel* createChannel(); |
63 | 58 | ||
64 | // Internet stream methods | 59 | /*virtual*/ void initWind(); |
65 | virtual void initInternetStream(); | 60 | /*virtual*/ void cleanupWind(); |
66 | virtual void startInternetStream(const std::string& url_cstr); | 61 | /*virtual*/ void updateWind(LLVector3 direction, F32 camera_altitude); |
67 | virtual void stopInternetStream(); | 62 | |
68 | virtual void updateInternetStream(); | 63 | private: |
69 | virtual void pauseInternetStream(int pause); | ||
70 | virtual int isInternetStreamPlaying(); | ||
71 | virtual void getInternetStreamInfo(char* artist, char* title); | ||
72 | virtual void setInternetStreamGain(F32 vol); | ||
73 | virtual const std::string& getInternetStreamURL(); | ||
74 | virtual void InitStreamer(); | ||
75 | |||
76 | void checkALError(); | ||
77 | |||
78 | void initWind(); | ||
79 | void cleanupWind(); | ||
80 | void updateWind(LLVector3 direction, F32 camera_altitude); | ||
81 | |||
82 | protected: | ||
83 | static const S32 mNumWindBuffers=20; | ||
84 | static const S32 mSampleRate=44100; | ||
85 | static const S32 mBytesPerSample=4; | ||
86 | static const S32 mWindDataSize=8820; //44100 * 0.200 * 2 channels * 2 bytes per sample | ||
87 | |||
88 | BOOL mFirstWind; | ||
89 | ALuint mWindBuffers[mNumWindBuffers]; | ||
90 | ALuint mWindSource; | ||
91 | |||
92 | F32 mTargetGain; | ||
93 | F32 mTargetFreq; | ||
94 | F32 mTargetPanGainR; | ||
95 | S16 mWindData[mWindDataSize]; | ||
96 | |||
97 | std::string mInternetStreamURL; | ||
98 | void * windDSP(void *newbuffer, int length); | 64 | void * windDSP(void *newbuffer, int length); |
99 | #if LL_GSTREAMER_ENABLED | 65 | typedef S16 WIND_SAMPLE_T; |
100 | LLMediaManagerData * mMedia_data; | 66 | LLWindGen<WIND_SAMPLE_T> *mWindGen; |
101 | LLMediaImplGStreamer * m_streamer; | 67 | S16 *mWindBuf; |
102 | #endif | 68 | U32 mWindBufFreq; |
69 | U32 mWindBufSamples; | ||
70 | U32 mWindBufBytes; | ||
71 | ALuint mWindSource; | ||
72 | int mNumEmptyWindALBuffers; | ||
73 | |||
74 | static const int MAX_NUM_WIND_BUFFERS = 80; | ||
75 | static const float WIND_BUFFER_SIZE_SEC = 0.05f; // 1/20th sec | ||
103 | }; | 76 | }; |
104 | 77 | ||
105 | class LLAudioChannelOpenAL : public LLAudioChannel | 78 | class LLAudioChannelOpenAL : public LLAudioChannel |
@@ -108,16 +81,17 @@ class LLAudioChannelOpenAL : public LLAudioChannel | |||
108 | LLAudioChannelOpenAL(); | 81 | LLAudioChannelOpenAL(); |
109 | virtual ~LLAudioChannelOpenAL(); | 82 | virtual ~LLAudioChannelOpenAL(); |
110 | protected: | 83 | protected: |
111 | void play(); | 84 | /*virtual*/ void play(); |
112 | void playSynced(LLAudioChannel *channelp); | 85 | /*virtual*/ void playSynced(LLAudioChannel *channelp); |
113 | void cleanup(); | 86 | /*virtual*/ void cleanup(); |
114 | bool isPlaying(); | 87 | /*virtual*/ bool isPlaying(); |
115 | 88 | ||
116 | bool updateBuffer(); | 89 | /*virtual*/ bool updateBuffer(); |
117 | void update3DPosition(); | 90 | /*virtual*/ void update3DPosition(); |
118 | void updateLoop(){}; | 91 | /*virtual*/ void updateLoop(); |
119 | 92 | ||
120 | ALuint ALSource; | 93 | ALuint mALSource; |
94 | ALint mLastSamplePos; | ||
121 | }; | 95 | }; |
122 | 96 | ||
123 | class LLAudioBufferOpenAL : public LLAudioBuffer{ | 97 | class LLAudioBufferOpenAL : public LLAudioBuffer{ |
@@ -131,8 +105,9 @@ class LLAudioBufferOpenAL : public LLAudioBuffer{ | |||
131 | friend class LLAudioChannelOpenAL; | 105 | friend class LLAudioChannelOpenAL; |
132 | protected: | 106 | protected: |
133 | void cleanup(); | 107 | void cleanup(); |
134 | ALuint getBuffer(){return ALBuffer;} | 108 | ALuint getBuffer() {return mALBuffer;} |
135 | ALuint ALBuffer; | 109 | |
110 | ALuint mALBuffer; | ||
136 | }; | 111 | }; |
137 | 112 | ||
138 | #endif | 113 | #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 @@ | |||
39 | #include "llviewerparcelmgr.h" | 39 | #include "llviewerparcelmgr.h" |
40 | 40 | ||
41 | LLAudioSourceVO::LLAudioSourceVO(const LLUUID &sound_id, const LLUUID& owner_id, const F32 gain, LLViewerObject *objectp) | 41 | LLAudioSourceVO::LLAudioSourceVO(const LLUUID &sound_id, const LLUUID& owner_id, const F32 gain, LLViewerObject *objectp) |
42 | : LLAudioSource(sound_id, owner_id, gain), | 42 | : LLAudioSource(sound_id, owner_id, gain, LLAudioEngine::AUDIO_TYPE_SFX), |
43 | mObjectp(objectp), | 43 | mObjectp(objectp), |
44 | mActualGain(gain) | 44 | mActualGain(gain) |
45 | { | 45 | { |
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 ) | |||
106 | if(item && gAudiop) | 106 | if(item && gAudiop) |
107 | { | 107 | { |
108 | LLVector3d lpos_global = gAgent.getPositionGlobal(); | 108 | LLVector3d lpos_global = gAgent.getPositionGlobal(); |
109 | F32 volume = gSavedSettings.getBOOL("MuteSounds") ? 0.f : SOUND_GAIN * gSavedSettings.getF32("AudioLevelSFX"); | 109 | gAudiop->triggerSound(item->getAssetUUID(), gAgent.getID(), SOUND_GAIN, LLAudioEngine::AUDIO_TYPE_UI, lpos_global); |
110 | gAudiop->triggerSound(item->getAssetUUID(), gAgent.getID(), volume, lpos_global); | ||
111 | } | 110 | } |
112 | } | 111 | } |
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() | |||
583 | 583 | ||
584 | if (FALSE == gSavedSettings.getBOOL("NoAudio")) | 584 | if (FALSE == gSavedSettings.getBOOL("NoAudio")) |
585 | { | 585 | { |
586 | 586 | gAudiop = NULL; | |
587 | gAudiop = (LLAudioEngine *) new LLAudioEngine_OpenAL(); | 587 | |
588 | #ifdef LL_OPENAL | ||
589 | if (!gAudiop | ||
590 | #if !LL_WINDOWS | ||
591 | && NULL == getenv("LL_BAD_OPENAL_DRIVER") | ||
592 | #endif // !LL_WINDOWS | ||
593 | ) | ||
594 | { | ||
595 | gAudiop = (LLAudioEngine *) new LLAudioEngine_OpenAL(); | ||
596 | } | ||
597 | #endif | ||
598 | |||
599 | #ifdef LL_FMOD | ||
600 | if (!gAudiop | ||
601 | #if !LL_WINDOWS | ||
602 | && NULL == getenv("LL_BAD_FMOD_DRIVER") | ||
603 | #endif // !LL_WINDOWS | ||
604 | ) | ||
605 | { | ||
606 | gAudiop = (LLAudioEngine *) new LLAudioEngine_FMOD(); | ||
607 | } | ||
608 | #endif | ||
588 | 609 | ||
589 | if (gAudiop) | 610 | if (gAudiop) |
590 | { | 611 | { |
591 | BOOL init = gAudiop->init(kAUDIO_NUM_SOURCES); | 612 | #if LL_WINDOWS |
592 | if(!init) | 613 | // FMOD on Windows needs the window handle to stop playing audio |
614 | // when window is minimized. JC | ||
615 | void* window_handle = (HWND)gViewerWindow->getPlatformWindow(); | ||
616 | #else | ||
617 | void* window_handle = NULL; | ||
618 | #endif | ||
619 | bool init = gAudiop->init(kAUDIO_NUM_SOURCES, window_handle); | ||
620 | if(init) | ||
593 | { | 621 | { |
594 | LL_WARNS("AppInit") << "Unable to initialize audio engine" << LL_ENDL; | 622 | gAudiop->setMuted(TRUE); |
595 | gAudiop=NULL; | ||
596 | } | 623 | } |
597 | else | 624 | else |
598 | { | 625 | { |
599 | gAudiop->setMuted(TRUE); | 626 | LL_WARNS("AppInit") << "Unable to initialize audio engine" << LL_ENDL; |
600 | LL_INFOS("AppInit") << "Audio Engine Initialized." << LL_ENDL; | 627 | delete gAudiop; |
628 | gAudiop = NULL; | ||
601 | } | 629 | } |
602 | } | 630 | } |
603 | } | 631 | } |
604 | else | 632 | |
605 | { | 633 | LL_INFOS("AppInit") << "Audio Engine Initialized." << LL_ENDL; |
606 | gAudiop = NULL; | 634 | |
607 | } | ||
608 | 635 | ||
609 | if (LLTimer::knownBadTimer()) | 636 | if (LLTimer::knownBadTimer()) |
610 | { | 637 | { |
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 **) | |||
3308 | return; | 3308 | return; |
3309 | } | 3309 | } |
3310 | 3310 | ||
3311 | F32 volume = gSavedSettings.getBOOL("MuteSounds") ? 0.f : (gain * gSavedSettings.getF32("AudioLevelSFX")); | 3311 | gAudiop->triggerSound(sound_id, owner_id, gain, LLAudioEngine::AUDIO_TYPE_SFX, pos_global); |
3312 | gAudiop->triggerSound(sound_id, owner_id, volume, pos_global); | ||
3313 | } | 3312 | } |
3314 | 3313 | ||
3315 | void process_preload_sound(LLMessageSystem *msg, void **user_data) | 3314 | 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 ) | |||
1402 | const F32 SOUND_GAIN = 1.0f; | 1402 | const F32 SOUND_GAIN = 1.0f; |
1403 | if(gAudiop) | 1403 | if(gAudiop) |
1404 | { | 1404 | { |
1405 | F32 volume = gSavedSettings.getBOOL("MuteSounds") ? 0.f : (SOUND_GAIN * gSavedSettings.getF32("AudioLevelSFX")); | 1405 | gAudiop->triggerSound(item->getAssetUUID(), gAgentID, SOUND_GAIN, LLAudioEngine::AUDIO_TYPE_UI, lpos_global); |
1406 | gAudiop->triggerSound(item->getAssetUUID(), gAgentID, volume, lpos_global); | ||
1407 | } | 1406 | } |
1408 | showCopyToInvDialog( item ); | 1407 | showCopyToInvDialog( item ); |
1409 | } | 1408 | } |
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) | |||
3828 | // AUDIO_STEP_LO_SPEED, AUDIO_STEP_HI_SPEED, | 3828 | // AUDIO_STEP_LO_SPEED, AUDIO_STEP_HI_SPEED, |
3829 | // AUDIO_STEP_LO_GAIN, AUDIO_STEP_HI_GAIN ); | 3829 | // AUDIO_STEP_LO_GAIN, AUDIO_STEP_HI_GAIN ); |
3830 | 3830 | ||
3831 | F32 ambient_volume = gSavedSettings.getF32("AudioLevelAmbient"); | 3831 | const F32 STEP_VOLUME = 0.5f; |
3832 | F32 gain = gSavedSettings.getBOOL("MuteAmbient") | ||
3833 | ? 0.f | ||
3834 | : (.50f * ambient_volume * ambient_volume); | ||
3835 | LLUUID& step_sound_id = getStepSound(); | 3832 | LLUUID& step_sound_id = getStepSound(); |
3836 | 3833 | ||
3837 | LLVector3d foot_pos_global = gAgent.getPosGlobalFromAgent(foot_pos_agent); | 3834 | LLVector3d foot_pos_global = gAgent.getPosGlobalFromAgent(foot_pos_agent); |
@@ -3839,7 +3836,7 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent) | |||
3839 | if (LLViewerParcelMgr::getInstance()->canHearSound(foot_pos_global) | 3836 | if (LLViewerParcelMgr::getInstance()->canHearSound(foot_pos_global) |
3840 | && !LLMuteList::getInstance()->isMuted(getID(), LLMute::flagObjectSounds)) | 3837 | && !LLMuteList::getInstance()->isMuted(getID(), LLMute::flagObjectSounds)) |
3841 | { | 3838 | { |
3842 | gAudiop->triggerSound(step_sound_id, getID(), gain, foot_pos_global); | 3839 | gAudiop->triggerSound(step_sound_id, getID(), STEP_VOLUME, LLAudioEngine::AUDIO_TYPE_AMBIENT, foot_pos_global); |
3843 | } | 3840 | } |
3844 | } | 3841 | } |
3845 | } | 3842 | } |
@@ -4819,8 +4816,8 @@ BOOL LLVOAvatar::processSingleAnimationStateChange( const LLUUID& anim_id, BOOL | |||
4819 | //else | 4816 | //else |
4820 | { | 4817 | { |
4821 | LLUUID sound_id = LLUUID(gSavedSettings.getString("UISndTyping")); | 4818 | LLUUID sound_id = LLUUID(gSavedSettings.getString("UISndTyping")); |
4822 | F32 volume = gSavedSettings.getBOOL("MuteSounds") ? 0.f : gSavedSettings.getF32("AudioLevelSFX"); | 4819 | gAudiop->triggerSound(sound_id, getID(), 1.0f, LLAudioEngine::AUDIO_TYPE_SFX, char_pos_global); |
4823 | gAudiop->triggerSound(sound_id, getID(), volume, char_pos_global); | 4820 | |
4824 | } | 4821 | } |
4825 | } | 4822 | } |
4826 | } | 4823 | } |