diff options
Diffstat (limited to 'linden/indra/llaudio')
-rw-r--r-- | linden/indra/llaudio/CMakeLists.txt | 19 | ||||
-rw-r--r-- | linden/indra/llaudio/audioengine.cpp | 361 | ||||
-rw-r--r-- | linden/indra/llaudio/audioengine.h | 161 | ||||
-rw-r--r-- | linden/indra/llaudio/audioengine_fmod.cpp | 271 | ||||
-rw-r--r-- | linden/indra/llaudio/audioengine_fmod.h | 31 | ||||
-rw-r--r-- | linden/indra/llaudio/audioengine_openal.cpp | 544 | ||||
-rw-r--r-- | linden/indra/llaudio/audioengine_openal.h | 113 | ||||
-rw-r--r-- | linden/indra/llaudio/listener_fmod.h | 10 | ||||
-rw-r--r-- | linden/indra/llaudio/listener_openal.cpp | 98 | ||||
-rw-r--r-- | linden/indra/llaudio/listener_openal.h | 7 | ||||
-rw-r--r-- | linden/indra/llaudio/llaudiodecodemgr.cpp | 23 | ||||
-rw-r--r-- | linden/indra/llaudio/windgen.h | 138 |
12 files changed, 1397 insertions, 379 deletions
diff --git a/linden/indra/llaudio/CMakeLists.txt b/linden/indra/llaudio/CMakeLists.txt index b662023..aa15a9d 100644 --- a/linden/indra/llaudio/CMakeLists.txt +++ b/linden/indra/llaudio/CMakeLists.txt | |||
@@ -9,6 +9,7 @@ include(LLCommon) | |||
9 | include(LLMath) | 9 | include(LLMath) |
10 | include(LLMessage) | 10 | include(LLMessage) |
11 | include(LLVFS) | 11 | include(LLVFS) |
12 | include(LLMedia) | ||
12 | 13 | ||
13 | include_directories( | 14 | include_directories( |
14 | ${FMOD_INCLUDE_DIR} | 15 | ${FMOD_INCLUDE_DIR} |
@@ -20,6 +21,10 @@ include_directories( | |||
20 | ${VORBISENC_INCLUDE_DIRS} | 21 | ${VORBISENC_INCLUDE_DIRS} |
21 | ${VORBISFILE_INCLUDE_DIRS} | 22 | ${VORBISFILE_INCLUDE_DIRS} |
22 | ${VORBIS_INCLUDE_DIRS} | 23 | ${VORBIS_INCLUDE_DIRS} |
24 | ${OPENAL_LIB_INCLUDE_DIRS} | ||
25 | ${FREEAULT_LIB_INCLUDE_DIRS} | ||
26 | ${LLMEDIA_INCLUDE_DIRS} | ||
27 | ${GSTREAMER_INCLUDE_DIRS} | ||
23 | ) | 28 | ) |
24 | 29 | ||
25 | set(llaudio_SOURCE_FILES | 30 | set(llaudio_SOURCE_FILES |
@@ -38,6 +43,7 @@ set(llaudio_HEADER_FILES | |||
38 | llaudiodecodemgr.h | 43 | llaudiodecodemgr.h |
39 | vorbisdecode.h | 44 | vorbisdecode.h |
40 | vorbisencode.h | 45 | vorbisencode.h |
46 | windgen.h | ||
41 | ) | 47 | ) |
42 | 48 | ||
43 | if (FMOD) | 49 | if (FMOD) |
@@ -59,6 +65,19 @@ if (FMOD) | |||
59 | endif (LINUX) | 65 | endif (LINUX) |
60 | endif (FMOD) | 66 | endif (FMOD) |
61 | 67 | ||
68 | if (OPENAL) | ||
69 | list(APPEND llaudio_SOURCE_FILES | ||
70 | audioengine_openal.cpp | ||
71 | listener_openal.cpp | ||
72 | ) | ||
73 | |||
74 | list(APPEND llaudio_HEADER_FILES | ||
75 | audioengine_openal.h | ||
76 | listener_openal.h | ||
77 | ) | ||
78 | |||
79 | endif (OPENAL) | ||
80 | |||
62 | set_source_files_properties(${llaudio_HEADER_FILES} | 81 | set_source_files_properties(${llaudio_HEADER_FILES} |
63 | PROPERTIES HEADER_FILE_ONLY TRUE) | 82 | PROPERTIES HEADER_FILE_ONLY TRUE) |
64 | 83 | ||
diff --git a/linden/indra/llaudio/audioengine.cpp b/linden/indra/llaudio/audioengine.cpp index 5dd5b28..239981b 100644 --- a/linden/indra/llaudio/audioengine.cpp +++ b/linden/indra/llaudio/audioengine.cpp | |||
@@ -44,14 +44,13 @@ | |||
44 | #include "llaudiodecodemgr.h" | 44 | #include "llaudiodecodemgr.h" |
45 | #include "llassetstorage.h" | 45 | #include "llassetstorage.h" |
46 | 46 | ||
47 | #include "llmediamanager.h" | ||
48 | |||
47 | // necessary for grabbing sounds from sim (implemented in viewer) | 49 | // necessary for grabbing sounds from sim (implemented in viewer) |
48 | extern void request_sound(const LLUUID &sound_guid); | 50 | extern void request_sound(const LLUUID &sound_guid); |
49 | 51 | ||
50 | LLAudioEngine* gAudiop = NULL; | 52 | LLAudioEngine* gAudiop = NULL; |
51 | 53 | ||
52 | // Maximum amount of time we wait for a transfer to complete before starting | ||
53 | // off another one. | ||
54 | const F32 MAX_CURRENT_TRANSFER_TIME = 60.f; | ||
55 | 54 | ||
56 | // | 55 | // |
57 | // LLAudioEngine implementation | 56 | // LLAudioEngine implementation |
@@ -75,13 +74,13 @@ void LLAudioEngine::setDefaults() | |||
75 | 74 | ||
76 | mListenerp = NULL; | 75 | mListenerp = NULL; |
77 | 76 | ||
78 | mMuted = FALSE; | 77 | mMuted = false; |
79 | mUserData = NULL; | 78 | mUserData = NULL; |
80 | 79 | ||
81 | mLastStatus = 0; | 80 | mLastStatus = 0; |
82 | 81 | ||
83 | mNumChannels = 0; | 82 | mNumChannels = 0; |
84 | mEnableWind = FALSE; | 83 | mEnableWind = false; |
85 | 84 | ||
86 | S32 i; | 85 | S32 i; |
87 | for (i = 0; i < MAX_CHANNELS; i++) | 86 | for (i = 0; i < MAX_CHANNELS; i++) |
@@ -91,15 +90,21 @@ void LLAudioEngine::setDefaults() | |||
91 | for (i = 0; i < MAX_BUFFERS; i++) | 90 | for (i = 0; i < MAX_BUFFERS; i++) |
92 | { | 91 | { |
93 | mBuffers[i] = NULL; | 92 | mBuffers[i] = NULL; |
94 | } | 93 | } |
95 | 94 | ||
96 | mMasterGain = 1.f; | 95 | mMasterGain = 1.f; |
97 | mInternetStreamGain = 0.125f; | 96 | mInternetStreamGain = 0.125f; |
98 | mNextWindUpdate = 0.f; | 97 | mNextWindUpdate = 0.f; |
98 | |||
99 | mInternetStreamMedia = NULL; | ||
100 | mInternetStreamURL.clear(); | ||
101 | |||
102 | for (U32 i = 0; i < LLAudioEngine::AUDIO_TYPE_COUNT; i++) | ||
103 | mSecondaryGain[i] = 1.0f; | ||
99 | } | 104 | } |
100 | 105 | ||
101 | 106 | ||
102 | BOOL LLAudioEngine::init(const S32 num_channels, void* userdata) | 107 | bool LLAudioEngine::init(const S32 num_channels, void* userdata) |
103 | { | 108 | { |
104 | setDefaults(); | 109 | setDefaults(); |
105 | 110 | ||
@@ -111,7 +116,9 @@ BOOL LLAudioEngine::init(const S32 num_channels, void* userdata) | |||
111 | // Initialize the decode manager | 116 | // Initialize the decode manager |
112 | gAudioDecodeMgrp = new LLAudioDecodeMgr; | 117 | gAudioDecodeMgrp = new LLAudioDecodeMgr; |
113 | 118 | ||
114 | return TRUE; | 119 | llinfos << "LLAudioEngine::init() AudioEngine successfully initialized" << llendl; |
120 | |||
121 | return true; | ||
115 | } | 122 | } |
116 | 123 | ||
117 | 124 | ||
@@ -121,6 +128,9 @@ void LLAudioEngine::shutdown() | |||
121 | delete gAudioDecodeMgrp; | 128 | delete gAudioDecodeMgrp; |
122 | gAudioDecodeMgrp = NULL; | 129 | gAudioDecodeMgrp = NULL; |
123 | 130 | ||
131 | // Clean up wind source | ||
132 | cleanupWind(); | ||
133 | |||
124 | // Clean up audio sources | 134 | // Clean up audio sources |
125 | source_map::iterator iter_src; | 135 | source_map::iterator iter_src; |
126 | for (iter_src = mAllSources.begin(); iter_src != mAllSources.end(); iter_src++) | 136 | for (iter_src = mAllSources.begin(); iter_src != mAllSources.end(); iter_src++) |
@@ -141,22 +151,146 @@ void LLAudioEngine::shutdown() | |||
141 | S32 i; | 151 | S32 i; |
142 | for (i = 0; i < MAX_CHANNELS; i++) | 152 | for (i = 0; i < MAX_CHANNELS; i++) |
143 | { | 153 | { |
144 | if (mChannels[i]) | 154 | delete mChannels[i]; |
145 | { | 155 | mChannels[i] = NULL; |
146 | delete mChannels[i]; | ||
147 | mChannels[i] = NULL; | ||
148 | } | ||
149 | } | 156 | } |
150 | 157 | ||
151 | // Clean up buffers | 158 | // Clean up buffers |
152 | for (i = 0; i < MAX_BUFFERS; i++) | 159 | for (i = 0; i < MAX_BUFFERS; i++) |
153 | { | 160 | { |
154 | 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) | ||
155 | { | 180 | { |
156 | delete mBuffers[i]; | 181 | mInternetStreamMedia = mgr->createSourceFromMimeType(LLURI(url).scheme(), "audio/mpeg"); // assumes that whatever media implementation supports mp3 also supports vorbis. |
157 | 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; | ||
234 | } | ||
235 | } else { | ||
236 | if(! mInternetStreamMedia->addCommand(LLMediaBase::COMMAND_START)) | ||
237 | { | ||
238 | llinfos << "attempting to unpause stream failed!" << llendl; | ||
158 | } | 239 | } |
159 | } | 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 | ||
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; | ||
160 | } | 294 | } |
161 | 295 | ||
162 | 296 | ||
@@ -167,6 +301,13 @@ void LLAudioEngine::updateChannels() | |||
167 | { | 301 | { |
168 | if (mChannels[i]) | 302 | if (mChannels[i]) |
169 | { | 303 | { |
304 | // set secondary gain if type is available | ||
305 | LLAudioSource* source = mChannels[i]->getSource(); | ||
306 | if (source) | ||
307 | { | ||
308 | mChannels[i]->setSecondaryGain(mSecondaryGain[source->getType()]); | ||
309 | } | ||
310 | |||
170 | mChannels[i]->updateBuffer(); | 311 | mChannels[i]->updateBuffer(); |
171 | mChannels[i]->update3DPosition(); | 312 | mChannels[i]->update3DPosition(); |
172 | mChannels[i]->updateLoop(); | 313 | mChannels[i]->updateLoop(); |
@@ -200,7 +341,7 @@ void LLAudioEngine::idle(F32 max_decode_time) | |||
200 | { | 341 | { |
201 | if (mBuffers[i]) | 342 | if (mBuffers[i]) |
202 | { | 343 | { |
203 | mBuffers[i]->mInUse = FALSE; | 344 | mBuffers[i]->mInUse = false; |
204 | } | 345 | } |
205 | } | 346 | } |
206 | 347 | ||
@@ -252,11 +393,11 @@ void LLAudioEngine::idle(F32 max_decode_time) | |||
252 | { | 393 | { |
253 | // A sync slave, it doesn't start playing until it's synced up with the master. | 394 | // A sync slave, it doesn't start playing until it's synced up with the master. |
254 | // Flag this channel as waiting for sync, and return true. | 395 | // Flag this channel as waiting for sync, and return true. |
255 | channelp->setWaiting(TRUE); | 396 | channelp->setWaiting(true); |
256 | } | 397 | } |
257 | else | 398 | else |
258 | { | 399 | { |
259 | channelp->setWaiting(FALSE); | 400 | channelp->setWaiting(false); |
260 | channelp->play(); | 401 | channelp->play(); |
261 | } | 402 | } |
262 | } | 403 | } |
@@ -396,7 +537,7 @@ void LLAudioEngine::idle(F32 max_decode_time) | |||
396 | if (sync_masterp->getChannel()) | 537 | if (sync_masterp->getChannel()) |
397 | { | 538 | { |
398 | channelp->playSynced(master_channelp); | 539 | channelp->playSynced(master_channelp); |
399 | channelp->setWaiting(FALSE); | 540 | channelp->setWaiting(false); |
400 | } | 541 | } |
401 | } | 542 | } |
402 | } | 543 | } |
@@ -426,7 +567,7 @@ void LLAudioEngine::idle(F32 max_decode_time) | |||
426 | { | 567 | { |
427 | if (mChannels[i]) | 568 | if (mChannels[i]) |
428 | { | 569 | { |
429 | mChannels[i]->mLoopedThisFrame = FALSE; | 570 | mChannels[i]->mLoopedThisFrame = false; |
430 | } | 571 | } |
431 | } | 572 | } |
432 | 573 | ||
@@ -437,13 +578,17 @@ void LLAudioEngine::idle(F32 max_decode_time) | |||
437 | // missed picking it up in all the places that can add | 578 | // missed picking it up in all the places that can add |
438 | // or request new data. | 579 | // or request new data. |
439 | startNextTransfer(); | 580 | startNextTransfer(); |
581 | |||
582 | updateInternetStream(); | ||
440 | } | 583 | } |
441 | 584 | ||
442 | BOOL LLAudioEngine::updateBufferForData(LLAudioData *adp, const LLUUID &audio_uuid) | 585 | |
586 | |||
587 | bool LLAudioEngine::updateBufferForData(LLAudioData *adp, const LLUUID &audio_uuid) | ||
443 | { | 588 | { |
444 | if (!adp) | 589 | if (!adp) |
445 | { | 590 | { |
446 | return FALSE; | 591 | return false; |
447 | } | 592 | } |
448 | 593 | ||
449 | // Update the audio buffer first - load a sound if we have it. | 594 | // Update the audio buffer first - load a sound if we have it. |
@@ -466,14 +611,14 @@ BOOL LLAudioEngine::updateBufferForData(LLAudioData *adp, const LLUUID &audio_uu | |||
466 | } | 611 | } |
467 | else | 612 | else |
468 | { | 613 | { |
469 | return FALSE; | 614 | return false; |
470 | } | 615 | } |
471 | } | 616 | } |
472 | return TRUE; | 617 | return true; |
473 | } | 618 | } |
474 | 619 | ||
475 | 620 | ||
476 | void LLAudioEngine::enableWind(BOOL enable) | 621 | void LLAudioEngine::enableWind(bool enable) |
477 | { | 622 | { |
478 | if (enable && (!mEnableWind)) | 623 | if (enable && (!mEnableWind)) |
479 | { | 624 | { |
@@ -601,7 +746,7 @@ void LLAudioEngine::cleanupBuffer(LLAudioBuffer *bufferp) | |||
601 | } | 746 | } |
602 | 747 | ||
603 | 748 | ||
604 | BOOL LLAudioEngine::preloadSound(const LLUUID &uuid) | 749 | bool LLAudioEngine::preloadSound(const LLUUID &uuid) |
605 | { | 750 | { |
606 | gAudiop->getAudioData(uuid); // We don't care about the return value, this is just to make sure | 751 | gAudiop->getAudioData(uuid); // We don't care about the return value, this is just to make sure |
607 | // that we have an entry, which will mean that the audio engine knows about this | 752 | // that we have an entry, which will mean that the audio engine knows about this |
@@ -609,23 +754,23 @@ BOOL LLAudioEngine::preloadSound(const LLUUID &uuid) | |||
609 | if (gAudioDecodeMgrp->addDecodeRequest(uuid)) | 754 | if (gAudioDecodeMgrp->addDecodeRequest(uuid)) |
610 | { | 755 | { |
611 | // This means that we do have a local copy, and we're working on decoding it. | 756 | // This means that we do have a local copy, and we're working on decoding it. |
612 | return TRUE; | 757 | return true; |
613 | } | 758 | } |
614 | 759 | ||
615 | // At some point we need to have the audio/asset system check the static VFS | 760 | // At some point we need to have the audio/asset system check the static VFS |
616 | // before it goes off and fetches stuff from the server. | 761 | // before it goes off and fetches stuff from the server. |
617 | //llwarns << "Used internal preload for non-local sound" << llendl; | 762 | //llwarns << "Used internal preload for non-local sound" << llendl; |
618 | return FALSE; | 763 | return false; |
619 | } | 764 | } |
620 | 765 | ||
621 | 766 | ||
622 | BOOL LLAudioEngine::isWindEnabled() | 767 | bool LLAudioEngine::isWindEnabled() |
623 | { | 768 | { |
624 | return mEnableWind; | 769 | return mEnableWind; |
625 | } | 770 | } |
626 | 771 | ||
627 | 772 | ||
628 | void LLAudioEngine::setMuted(BOOL muted) | 773 | void LLAudioEngine::setMuted(bool muted) |
629 | { | 774 | { |
630 | mMuted = muted; | 775 | mMuted = muted; |
631 | enableWind(!mMuted); | 776 | enableWind(!mMuted); |
@@ -643,6 +788,18 @@ F32 LLAudioEngine::getMasterGain() | |||
643 | return mMasterGain; | 788 | return mMasterGain; |
644 | } | 789 | } |
645 | 790 | ||
791 | void LLAudioEngine::setSecondaryGain(S32 type, F32 gain) | ||
792 | { | ||
793 | llassert(type < LLAudioEngine::AUDIO_TYPE_COUNT); | ||
794 | |||
795 | mSecondaryGain[type] = gain; | ||
796 | } | ||
797 | |||
798 | F32 LLAudioEngine::getSecondaryGain(S32 type) | ||
799 | { | ||
800 | return mSecondaryGain[type]; | ||
801 | } | ||
802 | |||
646 | F32 LLAudioEngine::getInternetStreamGain() | 803 | F32 LLAudioEngine::getInternetStreamGain() |
647 | { | 804 | { |
648 | return mInternetStreamGain; | 805 | return mInternetStreamGain; |
@@ -718,7 +875,8 @@ F64 LLAudioEngine::mapWindVecToPan(LLVector3 wind_vec) | |||
718 | } | 875 | } |
719 | 876 | ||
720 | 877 | ||
721 | void LLAudioEngine::triggerSound(const LLUUID &audio_uuid, const LLUUID& owner_id, const F32 gain, const LLVector3d &pos_global) | 878 | void LLAudioEngine::triggerSound(const LLUUID &audio_uuid, const LLUUID& owner_id, const F32 gain, |
879 | const S32 type, const LLVector3d &pos_global) | ||
722 | { | 880 | { |
723 | // Create a new source (since this can't be associated with an existing source. | 881 | // Create a new source (since this can't be associated with an existing source. |
724 | //llinfos << "Localized: " << audio_uuid << llendl; | 882 | //llinfos << "Localized: " << audio_uuid << llendl; |
@@ -731,11 +889,11 @@ void LLAudioEngine::triggerSound(const LLUUID &audio_uuid, const LLUUID& owner_i | |||
731 | LLUUID source_id; | 889 | LLUUID source_id; |
732 | source_id.generate(); | 890 | source_id.generate(); |
733 | 891 | ||
734 | LLAudioSource *asp = new LLAudioSource(source_id, owner_id, gain); | 892 | LLAudioSource *asp = new LLAudioSource(source_id, owner_id, gain, type); |
735 | gAudiop->addAudioSource(asp); | 893 | gAudiop->addAudioSource(asp); |
736 | if (pos_global.isExactlyZero()) | 894 | if (pos_global.isExactlyZero()) |
737 | { | 895 | { |
738 | asp->setAmbient(TRUE); | 896 | asp->setAmbient(true); |
739 | } | 897 | } |
740 | else | 898 | else |
741 | { | 899 | { |
@@ -914,7 +1072,7 @@ void LLAudioEngine::cleanupAudioSource(LLAudioSource *asp) | |||
914 | } | 1072 | } |
915 | 1073 | ||
916 | 1074 | ||
917 | BOOL LLAudioEngine::hasDecodedFile(const LLUUID &uuid) | 1075 | bool LLAudioEngine::hasDecodedFile(const LLUUID &uuid) |
918 | { | 1076 | { |
919 | std::string uuid_str; | 1077 | std::string uuid_str; |
920 | uuid.toString(uuid_str); | 1078 | uuid.toString(uuid_str); |
@@ -925,16 +1083,16 @@ BOOL LLAudioEngine::hasDecodedFile(const LLUUID &uuid) | |||
925 | 1083 | ||
926 | if (gDirUtilp->fileExists(wav_path)) | 1084 | if (gDirUtilp->fileExists(wav_path)) |
927 | { | 1085 | { |
928 | return TRUE; | 1086 | return true; |
929 | } | 1087 | } |
930 | else | 1088 | else |
931 | { | 1089 | { |
932 | return FALSE; | 1090 | return false; |
933 | } | 1091 | } |
934 | } | 1092 | } |
935 | 1093 | ||
936 | 1094 | ||
937 | BOOL LLAudioEngine::hasLocalFile(const LLUUID &uuid) | 1095 | bool LLAudioEngine::hasLocalFile(const LLUUID &uuid) |
938 | { | 1096 | { |
939 | // See if it's in the VFS. | 1097 | // See if it's in the VFS. |
940 | return gVFS->getExists(uuid, LLAssetType::AT_SOUND); | 1098 | return gVFS->getExists(uuid, LLAssetType::AT_SOUND); |
@@ -1150,9 +1308,9 @@ void LLAudioEngine::assetCallback(LLVFS *vfs, const LLUUID &uuid, LLAssetType::E | |||
1150 | LLAudioData *adp = gAudiop->getAudioData(uuid); | 1308 | LLAudioData *adp = gAudiop->getAudioData(uuid); |
1151 | if (adp) | 1309 | if (adp) |
1152 | { | 1310 | { |
1153 | adp->setHasValidData(FALSE); | 1311 | adp->setHasValidData(false); |
1154 | adp->setHasLocalData(FALSE); | 1312 | adp->setHasLocalData(false); |
1155 | adp->setHasDecodedData(FALSE); | 1313 | adp->setHasDecodedData(false); |
1156 | } | 1314 | } |
1157 | } | 1315 | } |
1158 | else | 1316 | else |
@@ -1165,8 +1323,8 @@ void LLAudioEngine::assetCallback(LLVFS *vfs, const LLUUID &uuid, LLAssetType::E | |||
1165 | } | 1323 | } |
1166 | else | 1324 | else |
1167 | { | 1325 | { |
1168 | adp->setHasValidData(TRUE); | 1326 | adp->setHasValidData(true); |
1169 | adp->setHasLocalData(TRUE); | 1327 | adp->setHasLocalData(true); |
1170 | gAudioDecodeMgrp->addDecodeRequest(uuid); | 1328 | gAudioDecodeMgrp->addDecodeRequest(uuid); |
1171 | } | 1329 | } |
1172 | } | 1330 | } |
@@ -1180,17 +1338,18 @@ void LLAudioEngine::assetCallback(LLVFS *vfs, const LLUUID &uuid, LLAssetType::E | |||
1180 | // | 1338 | // |
1181 | 1339 | ||
1182 | 1340 | ||
1183 | 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) |
1184 | : mID(id), | 1342 | : mID(id), |
1185 | mOwnerID(owner_id), | 1343 | mOwnerID(owner_id), |
1186 | mPriority(0.f), | 1344 | mPriority(0.f), |
1187 | mGain(gain), | 1345 | mGain(gain), |
1188 | mAmbient(FALSE), | 1346 | mType(type), |
1189 | mLoop(FALSE), | 1347 | mAmbient(false), |
1190 | mSyncMaster(FALSE), | 1348 | mLoop(false), |
1191 | mSyncSlave(FALSE), | 1349 | mSyncMaster(false), |
1192 | mQueueSounds(FALSE), | 1350 | mSyncSlave(false), |
1193 | mPlayedOnce(FALSE), | 1351 | mQueueSounds(false), |
1352 | mPlayedOnce(false), | ||
1194 | mChannelp(NULL), | 1353 | mChannelp(NULL), |
1195 | mCurrentDatap(NULL), | 1354 | mCurrentDatap(NULL), |
1196 | mQueuedDatap(NULL) | 1355 | mQueuedDatap(NULL) |
@@ -1254,7 +1413,7 @@ void LLAudioSource::updatePriority() | |||
1254 | } | 1413 | } |
1255 | } | 1414 | } |
1256 | 1415 | ||
1257 | BOOL LLAudioSource::setupChannel() | 1416 | bool LLAudioSource::setupChannel() |
1258 | { | 1417 | { |
1259 | LLAudioData *adp = getCurrentData(); | 1418 | LLAudioData *adp = getCurrentData(); |
1260 | 1419 | ||
@@ -1262,7 +1421,7 @@ BOOL LLAudioSource::setupChannel() | |||
1262 | { | 1421 | { |
1263 | // We're not ready to play back the sound yet, so don't try and allocate a channel for it. | 1422 | // We're not ready to play back the sound yet, so don't try and allocate a channel for it. |
1264 | //llwarns << "Aborting, no buffer" << llendl; | 1423 | //llwarns << "Aborting, no buffer" << llendl; |
1265 | return FALSE; | 1424 | return false; |
1266 | } | 1425 | } |
1267 | 1426 | ||
1268 | 1427 | ||
@@ -1280,15 +1439,15 @@ BOOL LLAudioSource::setupChannel() | |||
1280 | // Now we have to reprioritize. | 1439 | // Now we have to reprioritize. |
1281 | // For now, just don't play the sound. | 1440 | // For now, just don't play the sound. |
1282 | //llwarns << "Aborting, no free channels" << llendl; | 1441 | //llwarns << "Aborting, no free channels" << llendl; |
1283 | return FALSE; | 1442 | return false; |
1284 | } | 1443 | } |
1285 | 1444 | ||
1286 | mChannelp->setSource(this); | 1445 | mChannelp->setSource(this); |
1287 | return TRUE; | 1446 | return true; |
1288 | } | 1447 | } |
1289 | 1448 | ||
1290 | 1449 | ||
1291 | BOOL LLAudioSource::play(const LLUUID &audio_uuid) | 1450 | bool LLAudioSource::play(const LLUUID &audio_uuid) |
1292 | { | 1451 | { |
1293 | if (audio_uuid.isNull()) | 1452 | if (audio_uuid.isNull()) |
1294 | { | 1453 | { |
@@ -1296,7 +1455,7 @@ BOOL LLAudioSource::play(const LLUUID &audio_uuid) | |||
1296 | { | 1455 | { |
1297 | getChannel()->setSource(NULL); | 1456 | getChannel()->setSource(NULL); |
1298 | setChannel(NULL); | 1457 | setChannel(NULL); |
1299 | addAudioData(NULL, TRUE); | 1458 | addAudioData(NULL, true); |
1300 | } | 1459 | } |
1301 | } | 1460 | } |
1302 | // Reset our age timeout if someone attempts to play the source. | 1461 | // Reset our age timeout if someone attempts to play the source. |
@@ -1304,7 +1463,7 @@ BOOL LLAudioSource::play(const LLUUID &audio_uuid) | |||
1304 | 1463 | ||
1305 | LLAudioData *adp = gAudiop->getAudioData(audio_uuid); | 1464 | LLAudioData *adp = gAudiop->getAudioData(audio_uuid); |
1306 | 1465 | ||
1307 | BOOL has_buffer = gAudiop->updateBufferForData(adp, audio_uuid); | 1466 | bool has_buffer = gAudiop->updateBufferForData(adp, audio_uuid); |
1308 | 1467 | ||
1309 | 1468 | ||
1310 | addAudioData(adp); | 1469 | addAudioData(adp); |
@@ -1312,47 +1471,48 @@ BOOL LLAudioSource::play(const LLUUID &audio_uuid) | |||
1312 | if (!has_buffer) | 1471 | if (!has_buffer) |
1313 | { | 1472 | { |
1314 | // Don't bother trying to set up a channel or anything, we don't have an audio buffer. | 1473 | // Don't bother trying to set up a channel or anything, we don't have an audio buffer. |
1315 | return FALSE; | 1474 | return false; |
1316 | } | 1475 | } |
1317 | 1476 | ||
1318 | if (!setupChannel()) | 1477 | if (!setupChannel()) |
1319 | { | 1478 | { |
1320 | return FALSE; | 1479 | return false; |
1321 | } | 1480 | } |
1322 | 1481 | ||
1323 | if (isSyncSlave()) | 1482 | if (isSyncSlave()) |
1324 | { | 1483 | { |
1325 | // A sync slave, it doesn't start playing until it's synced up with the master. | 1484 | // A sync slave, it doesn't start playing until it's synced up with the master. |
1326 | // Flag this channel as waiting for sync, and return true. | 1485 | // Flag this channel as waiting for sync, and return true. |
1327 | getChannel()->setWaiting(TRUE); | 1486 | getChannel()->setWaiting(true); |
1328 | return TRUE; | 1487 | return true; |
1329 | } | 1488 | } |
1330 | 1489 | ||
1331 | getChannel()->play(); | 1490 | getChannel()->play(); |
1332 | return TRUE; | 1491 | return true; |
1333 | } | 1492 | } |
1334 | 1493 | ||
1335 | 1494 | ||
1336 | BOOL LLAudioSource::isDone() | 1495 | bool LLAudioSource::isDone() |
1337 | { | 1496 | { |
1338 | const F32 MAX_AGE = 60.f; | 1497 | const F32 MAX_AGE = 60.f; |
1339 | const F32 MAX_UNPLAYED_AGE = 15.f; | 1498 | const F32 MAX_UNPLAYED_AGE = 15.f; |
1499 | |||
1340 | if (isLoop()) | 1500 | if (isLoop()) |
1341 | { | 1501 | { |
1342 | // Looped sources never die on their own. | 1502 | // Looped sources never die on their own. |
1343 | return FALSE; | 1503 | return false; |
1344 | } | 1504 | } |
1345 | 1505 | ||
1346 | 1506 | ||
1347 | if (hasPendingPreloads()) | 1507 | if (hasPendingPreloads()) |
1348 | { | 1508 | { |
1349 | return FALSE; | 1509 | return false; |
1350 | } | 1510 | } |
1351 | 1511 | ||
1352 | if (mQueuedDatap) | 1512 | if (mQueuedDatap) |
1353 | { | 1513 | { |
1354 | // Don't kill this sound if we've got something queued up to play. | 1514 | // Don't kill this sound if we've got something queued up to play. |
1355 | return FALSE; | 1515 | return false; |
1356 | } | 1516 | } |
1357 | 1517 | ||
1358 | F32 elapsed = mAgeTimer.getElapsedTimeF32(); | 1518 | F32 elapsed = mAgeTimer.getElapsedTimeF32(); |
@@ -1365,11 +1525,11 @@ BOOL LLAudioSource::isDone() | |||
1365 | // We don't have a channel assigned, and it's been | 1525 | // We don't have a channel assigned, and it's been |
1366 | // over 5 seconds since we tried to play it. Don't bother. | 1526 | // over 5 seconds since we tried to play it. Don't bother. |
1367 | //llinfos << "No channel assigned, source is done" << llendl; | 1527 | //llinfos << "No channel assigned, source is done" << llendl; |
1368 | return TRUE; | 1528 | return true; |
1369 | } | 1529 | } |
1370 | else | 1530 | else |
1371 | { | 1531 | { |
1372 | return FALSE; | 1532 | return false; |
1373 | } | 1533 | } |
1374 | } | 1534 | } |
1375 | 1535 | ||
@@ -1377,27 +1537,27 @@ BOOL LLAudioSource::isDone() | |||
1377 | { | 1537 | { |
1378 | if (elapsed > MAX_AGE) | 1538 | if (elapsed > MAX_AGE) |
1379 | { | 1539 | { |
1380 | // Arbitarily cut off non-looped sounds when they're 20 seconds old. | 1540 | // Arbitarily cut off non-looped sounds when they're old. |
1381 | return TRUE; | 1541 | return true; |
1382 | } | 1542 | } |
1383 | else | 1543 | else |
1384 | { | 1544 | { |
1385 | // Sound is still playing and we haven't timed out, don't kill it. | 1545 | // Sound is still playing and we haven't timed out, don't kill it. |
1386 | return FALSE; | 1546 | return false; |
1387 | } | 1547 | } |
1388 | } | 1548 | } |
1389 | 1549 | ||
1390 | if ((elapsed > MAX_UNPLAYED_AGE) || mPlayedOnce) | 1550 | if ((elapsed > MAX_UNPLAYED_AGE) || mPlayedOnce) |
1391 | { | 1551 | { |
1392 | // The sound isn't playing back after 5 seconds or we're already done playing it, kill it. | 1552 | // The sound isn't playing back after 5 seconds or we're already done playing it, kill it. |
1393 | return TRUE; | 1553 | return true; |
1394 | } | 1554 | } |
1395 | 1555 | ||
1396 | return FALSE; | 1556 | return false; |
1397 | } | 1557 | } |
1398 | 1558 | ||
1399 | 1559 | ||
1400 | void LLAudioSource::addAudioData(LLAudioData *adp, const BOOL set_current) | 1560 | void LLAudioSource::addAudioData(LLAudioData *adp, const bool set_current) |
1401 | { | 1561 | { |
1402 | // Only handle a single piece of audio data associated with a source right now, | 1562 | // Only handle a single piece of audio data associated with a source right now, |
1403 | // until I implement prefetch. | 1563 | // until I implement prefetch. |
@@ -1465,7 +1625,7 @@ void LLAudioSource::addAudioData(LLAudioData *adp, const BOOL set_current) | |||
1465 | } | 1625 | } |
1466 | 1626 | ||
1467 | 1627 | ||
1468 | BOOL LLAudioSource::hasPendingPreloads() const | 1628 | bool LLAudioSource::hasPendingPreloads() const |
1469 | { | 1629 | { |
1470 | // Check to see if we've got any preloads on deck for this source | 1630 | // Check to see if we've got any preloads on deck for this source |
1471 | data_map::const_iterator iter; | 1631 | data_map::const_iterator iter; |
@@ -1475,11 +1635,11 @@ BOOL LLAudioSource::hasPendingPreloads() const | |||
1475 | if (!adp->hasDecodedData()) | 1635 | if (!adp->hasDecodedData()) |
1476 | { | 1636 | { |
1477 | // This source is still waiting for a preload | 1637 | // This source is still waiting for a preload |
1478 | return TRUE; | 1638 | return true; |
1479 | } | 1639 | } |
1480 | } | 1640 | } |
1481 | 1641 | ||
1482 | return FALSE; | 1642 | return false; |
1483 | } | 1643 | } |
1484 | 1644 | ||
1485 | 1645 | ||
@@ -1514,8 +1674,9 @@ LLAudioBuffer *LLAudioSource::getCurrentBuffer() | |||
1514 | LLAudioChannel::LLAudioChannel() : | 1674 | LLAudioChannel::LLAudioChannel() : |
1515 | mCurrentSourcep(NULL), | 1675 | mCurrentSourcep(NULL), |
1516 | mCurrentBufferp(NULL), | 1676 | mCurrentBufferp(NULL), |
1517 | mLoopedThisFrame(FALSE), | 1677 | mLoopedThisFrame(false), |
1518 | mWaiting(FALSE) | 1678 | mWaiting(false), |
1679 | mSecondaryGain(1.0f) | ||
1519 | { | 1680 | { |
1520 | } | 1681 | } |
1521 | 1682 | ||
@@ -1542,7 +1703,7 @@ void LLAudioChannel::setSource(LLAudioSource *sourcep) | |||
1542 | //llinfos << "Clearing source for channel" << llendl; | 1703 | //llinfos << "Clearing source for channel" << llendl; |
1543 | cleanup(); | 1704 | cleanup(); |
1544 | mCurrentSourcep = NULL; | 1705 | mCurrentSourcep = NULL; |
1545 | mWaiting = FALSE; | 1706 | mWaiting = false; |
1546 | return; | 1707 | return; |
1547 | } | 1708 | } |
1548 | 1709 | ||
@@ -1558,13 +1719,13 @@ void LLAudioChannel::setSource(LLAudioSource *sourcep) | |||
1558 | } | 1719 | } |
1559 | 1720 | ||
1560 | 1721 | ||
1561 | BOOL LLAudioChannel::updateBuffer() | 1722 | bool LLAudioChannel::updateBuffer() |
1562 | { | 1723 | { |
1563 | if (!mCurrentSourcep) | 1724 | if (!mCurrentSourcep) |
1564 | { | 1725 | { |
1565 | // This channel isn't associated with any source, nothing | 1726 | // This channel isn't associated with any source, nothing |
1566 | // to be updated | 1727 | // to be updated |
1567 | return FALSE; | 1728 | return false; |
1568 | } | 1729 | } |
1569 | 1730 | ||
1570 | LLAudioBuffer *bufferp = mCurrentSourcep->getCurrentBuffer(); | 1731 | LLAudioBuffer *bufferp = mCurrentSourcep->getCurrentBuffer(); |
@@ -1574,14 +1735,14 @@ BOOL LLAudioChannel::updateBuffer() | |||
1574 | { | 1735 | { |
1575 | // The source hasn't changed what buffer it's playing | 1736 | // The source hasn't changed what buffer it's playing |
1576 | bufferp->mLastUseTimer.reset(); | 1737 | bufferp->mLastUseTimer.reset(); |
1577 | bufferp->mInUse = TRUE; | 1738 | bufferp->mInUse = true; |
1578 | } | 1739 | } |
1579 | return FALSE; | 1740 | return false; |
1580 | } | 1741 | } |
1581 | 1742 | ||
1582 | // | 1743 | // |
1583 | // 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 |
1584 | // existing fmod channel | 1745 | // the existing channel |
1585 | // | 1746 | // |
1586 | cleanup(); | 1747 | cleanup(); |
1587 | 1748 | ||
@@ -1589,16 +1750,16 @@ BOOL LLAudioChannel::updateBuffer() | |||
1589 | if (bufferp) | 1750 | if (bufferp) |
1590 | { | 1751 | { |
1591 | bufferp->mLastUseTimer.reset(); | 1752 | bufferp->mLastUseTimer.reset(); |
1592 | bufferp->mInUse = TRUE; | 1753 | bufferp->mInUse = true; |
1593 | } | 1754 | } |
1594 | 1755 | ||
1595 | if (!mCurrentBufferp) | 1756 | if (!mCurrentBufferp) |
1596 | { | 1757 | { |
1597 | // There's no new buffer to be played, so we just abort. | 1758 | // There's no new buffer to be played, so we just abort. |
1598 | return FALSE; | 1759 | return false; |
1599 | } | 1760 | } |
1600 | 1761 | ||
1601 | return TRUE; | 1762 | return true; |
1602 | } | 1763 | } |
1603 | 1764 | ||
1604 | 1765 | ||
@@ -1612,9 +1773,9 @@ BOOL LLAudioChannel::updateBuffer() | |||
1612 | LLAudioData::LLAudioData(const LLUUID &uuid) : | 1773 | LLAudioData::LLAudioData(const LLUUID &uuid) : |
1613 | mID(uuid), | 1774 | mID(uuid), |
1614 | mBufferp(NULL), | 1775 | mBufferp(NULL), |
1615 | mHasLocalData(FALSE), | 1776 | mHasLocalData(false), |
1616 | mHasDecodedData(FALSE), | 1777 | mHasDecodedData(false), |
1617 | mHasValidData(TRUE) | 1778 | mHasValidData(true) |
1618 | { | 1779 | { |
1619 | if (uuid.isNull()) | 1780 | if (uuid.isNull()) |
1620 | { | 1781 | { |
@@ -1625,24 +1786,24 @@ LLAudioData::LLAudioData(const LLUUID &uuid) : | |||
1625 | if (gAudiop && gAudiop->hasDecodedFile(uuid)) | 1786 | if (gAudiop && gAudiop->hasDecodedFile(uuid)) |
1626 | { | 1787 | { |
1627 | // Already have a decoded version, don't need to decode it. | 1788 | // Already have a decoded version, don't need to decode it. |
1628 | mHasLocalData = TRUE; | 1789 | mHasLocalData = true; |
1629 | mHasDecodedData = TRUE; | 1790 | mHasDecodedData = true; |
1630 | } | 1791 | } |
1631 | else if (gAssetStorage && gAssetStorage->hasLocalAsset(uuid, LLAssetType::AT_SOUND)) | 1792 | else if (gAssetStorage && gAssetStorage->hasLocalAsset(uuid, LLAssetType::AT_SOUND)) |
1632 | { | 1793 | { |
1633 | mHasLocalData = TRUE; | 1794 | mHasLocalData = true; |
1634 | } | 1795 | } |
1635 | } | 1796 | } |
1636 | 1797 | ||
1637 | 1798 | ||
1638 | BOOL LLAudioData::load() | 1799 | bool LLAudioData::load() |
1639 | { | 1800 | { |
1640 | // For now, just assume we're going to use one buffer per audiodata. | 1801 | // For now, just assume we're going to use one buffer per audiodata. |
1641 | if (mBufferp) | 1802 | if (mBufferp) |
1642 | { | 1803 | { |
1643 | // We already have this sound in a buffer, don't do anything. | 1804 | // We already have this sound in a buffer, don't do anything. |
1644 | llinfos << "Already have a buffer for this sound, don't bother loading!" << llendl; | 1805 | llinfos << "Already have a buffer for this sound, don't bother loading!" << llendl; |
1645 | return TRUE; | 1806 | return true; |
1646 | } | 1807 | } |
1647 | 1808 | ||
1648 | mBufferp = gAudiop->getFreeBuffer(); | 1809 | mBufferp = gAudiop->getFreeBuffer(); |
@@ -1650,7 +1811,7 @@ BOOL LLAudioData::load() | |||
1650 | { | 1811 | { |
1651 | // No free buffers, abort. | 1812 | // No free buffers, abort. |
1652 | llinfos << "Not able to allocate a new audio buffer, aborting." << llendl; | 1813 | llinfos << "Not able to allocate a new audio buffer, aborting." << llendl; |
1653 | return FALSE; | 1814 | return false; |
1654 | } | 1815 | } |
1655 | 1816 | ||
1656 | std::string uuid_str; | 1817 | std::string uuid_str; |
@@ -1664,10 +1825,10 @@ BOOL LLAudioData::load() | |||
1664 | gAudiop->cleanupBuffer(mBufferp); | 1825 | gAudiop->cleanupBuffer(mBufferp); |
1665 | mBufferp = NULL; | 1826 | mBufferp = NULL; |
1666 | 1827 | ||
1667 | return FALSE; | 1828 | return false; |
1668 | } | 1829 | } |
1669 | mBufferp->mAudioDatap = this; | 1830 | mBufferp->mAudioDatap = this; |
1670 | return TRUE; | 1831 | return true; |
1671 | } | 1832 | } |
1672 | 1833 | ||
1673 | 1834 | ||
diff --git a/linden/indra/llaudio/audioengine.h b/linden/indra/llaudio/audioengine.h index e38413f..15cb35f 100644 --- a/linden/indra/llaudio/audioengine.h +++ b/linden/indra/llaudio/audioengine.h | |||
@@ -45,6 +45,8 @@ | |||
45 | #include "llframetimer.h" | 45 | #include "llframetimer.h" |
46 | #include "llassettype.h" | 46 | #include "llassettype.h" |
47 | 47 | ||
48 | class LLMediaBase; | ||
49 | |||
48 | const F32 LL_WIND_UPDATE_INTERVAL = 0.1f; | 50 | const F32 LL_WIND_UPDATE_INTERVAL = 0.1f; |
49 | const F32 LL_ROLLOFF_MULTIPLIER_UNDER_WATER = 5.f; // How much sounds are weaker under water | 51 | const F32 LL_ROLLOFF_MULTIPLIER_UNDER_WATER = 5.f; // How much sounds are weaker under water |
50 | const F32 LL_WIND_UNDERWATER_CENTER_FREQ = 20.f; | 52 | const F32 LL_WIND_UNDERWATER_CENTER_FREQ = 20.f; |
@@ -67,6 +69,7 @@ class LLVFS; | |||
67 | class LLAudioSource; | 69 | class LLAudioSource; |
68 | class LLAudioData; | 70 | class LLAudioData; |
69 | class LLAudioChannel; | 71 | class LLAudioChannel; |
72 | class LLAudioChannelOpenAL; | ||
70 | class LLAudioBuffer; | 73 | class LLAudioBuffer; |
71 | 74 | ||
72 | 75 | ||
@@ -77,14 +80,24 @@ class LLAudioBuffer; | |||
77 | 80 | ||
78 | class LLAudioEngine | 81 | class LLAudioEngine |
79 | { | 82 | { |
83 | friend class LLAudioChannelOpenAL; // bleh. channel needs some listener methods. | ||
84 | |||
80 | public: | 85 | public: |
86 | enum LLAudioType | ||
87 | { | ||
88 | AUDIO_TYPE_NONE = 0, | ||
89 | AUDIO_TYPE_SFX = 1, | ||
90 | AUDIO_TYPE_UI = 2, | ||
91 | AUDIO_TYPE_AMBIENT = 3, | ||
92 | AUDIO_TYPE_COUNT = 4 // last | ||
93 | }; | ||
94 | |||
81 | LLAudioEngine(); | 95 | LLAudioEngine(); |
82 | virtual ~LLAudioEngine(); | 96 | virtual ~LLAudioEngine(); |
83 | 97 | ||
84 | // initialization/startup/shutdown | 98 | // initialization/startup/shutdown |
85 | //virtual BOOL init(); | 99 | virtual bool init(const S32 num_channels, void *userdata); |
86 | 100 | virtual std::string getDriverName(bool verbose) = 0; | |
87 | virtual BOOL init(const S32 num_channels, void *userdata); | ||
88 | virtual void shutdown(); | 101 | virtual void shutdown(); |
89 | 102 | ||
90 | // Used by the mechanics of the engine | 103 | // Used by the mechanics of the engine |
@@ -97,18 +110,21 @@ public: | |||
97 | // | 110 | // |
98 | // "End user" functionality | 111 | // "End user" functionality |
99 | // | 112 | // |
100 | virtual BOOL isWindEnabled(); | 113 | virtual bool isWindEnabled(); |
101 | virtual void enableWind(BOOL state_b); | 114 | virtual void enableWind(bool state_b); |
102 | 115 | ||
103 | // Use these for temporarily muting the audio system. | 116 | // Use these for temporarily muting the audio system. |
104 | // Does not change buffers, initialization, etc. but | 117 | // Does not change buffers, initialization, etc. but |
105 | // stops playing new sounds. | 118 | // stops playing new sounds. |
106 | virtual void setMuted(BOOL muted); | 119 | virtual void setMuted(bool muted); |
107 | virtual BOOL getMuted() const { return mMuted; } | 120 | virtual bool getMuted() const { return mMuted; } |
108 | 121 | ||
109 | F32 getMasterGain(); | 122 | F32 getMasterGain(); |
110 | void setMasterGain(F32 gain); | 123 | void setMasterGain(F32 gain); |
111 | 124 | ||
125 | F32 getSecondaryGain(S32 type); | ||
126 | void setSecondaryGain(S32 type, F32 gain); | ||
127 | |||
112 | F32 getInternetStreamGain(); | 128 | F32 getInternetStreamGain(); |
113 | 129 | ||
114 | virtual void setDopplerFactor(F32 factor); | 130 | virtual void setDopplerFactor(F32 factor); |
@@ -122,8 +138,10 @@ public: | |||
122 | 138 | ||
123 | // Methods actually related to setting up and removing sounds | 139 | // Methods actually related to setting up and removing sounds |
124 | // Owner ID is the owner of the object making the request | 140 | // Owner ID is the owner of the object making the request |
125 | void triggerSound(const LLUUID &sound_id, const LLUUID& owner_id, const F32 gain, const LLVector3d &pos_global = LLVector3d::zero); | 141 | void triggerSound(const LLUUID &sound_id, const LLUUID& owner_id, const F32 gain, |
126 | BOOL preloadSound(const LLUUID &id); | 142 | const S32 type = LLAudioEngine::AUDIO_TYPE_NONE, |
143 | const LLVector3d &pos_global = LLVector3d::zero); | ||
144 | bool preloadSound(const LLUUID &id); | ||
127 | 145 | ||
128 | void addAudioSource(LLAudioSource *asp); | 146 | void addAudioSource(LLAudioSource *asp); |
129 | void cleanupAudioSource(LLAudioSource *asp); | 147 | void cleanupAudioSource(LLAudioSource *asp); |
@@ -132,14 +150,16 @@ public: | |||
132 | LLAudioData *getAudioData(const LLUUID &audio_uuid); | 150 | LLAudioData *getAudioData(const LLUUID &audio_uuid); |
133 | 151 | ||
134 | 152 | ||
135 | virtual void startInternetStream(const std::string& url) = 0; | 153 | // Internet stream methods |
136 | virtual void stopInternetStream() = 0; | 154 | virtual void startInternetStream(const std::string& url); |
137 | virtual void pauseInternetStream(int pause) = 0; | 155 | virtual void stopInternetStream(); |
138 | virtual int isInternetStreamPlaying() = 0; | 156 | virtual void pauseInternetStream(int pause); |
139 | 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); | ||
140 | // use a value from 0.0 to 1.0, inclusive | 160 | // use a value from 0.0 to 1.0, inclusive |
141 | virtual void setInternetStreamGain(F32 vol) { mInternetStreamGain = vol; } | 161 | virtual void setInternetStreamGain(F32 vol); |
142 | virtual const std::string& getInternetStreamURL() { return LLStringUtil::null; } | 162 | virtual const std::string& getInternetStreamURL(); |
143 | 163 | ||
144 | // For debugging usage | 164 | // For debugging usage |
145 | virtual LLVector3 getListenerPos(); | 165 | virtual LLVector3 getListenerPos(); |
@@ -148,17 +168,16 @@ public: | |||
148 | LLAudioChannel *getFreeChannel(const F32 priority); // Get a free channel or flush an existing one if your priority is higher | 168 | LLAudioChannel *getFreeChannel(const F32 priority); // Get a free channel or flush an existing one if your priority is higher |
149 | void cleanupBuffer(LLAudioBuffer *bufferp); | 169 | void cleanupBuffer(LLAudioBuffer *bufferp); |
150 | 170 | ||
151 | BOOL hasDecodedFile(const LLUUID &uuid); | 171 | bool hasDecodedFile(const LLUUID &uuid); |
152 | BOOL hasLocalFile(const LLUUID &uuid); | 172 | bool hasLocalFile(const LLUUID &uuid); |
153 | 173 | ||
154 | BOOL updateBufferForData(LLAudioData *adp, const LLUUID &audio_uuid = LLUUID::null); | 174 | bool updateBufferForData(LLAudioData *adp, const LLUUID &audio_uuid = LLUUID::null); |
155 | 175 | ||
156 | 176 | ||
157 | // Asset callback when we're retrieved a sound from the asset server. | 177 | // Asset callback when we're retrieved a sound from the asset server. |
158 | void startNextTransfer(); | 178 | void startNextTransfer(); |
159 | static void assetCallback(LLVFS *vfs, const LLUUID &uuid, LLAssetType::EType type, void *user_data, S32 result_code, LLExtStat ext_status); | 179 | static void assetCallback(LLVFS *vfs, const LLUUID &uuid, LLAssetType::EType type, void *user_data, S32 result_code, LLExtStat ext_status); |
160 | 180 | ||
161 | |||
162 | friend class LLPipeline; // For debugging | 181 | friend class LLPipeline; // For debugging |
163 | public: | 182 | public: |
164 | F32 mMaxWindGain; // Hack. Public to set before fade in? | 183 | F32 mMaxWindGain; // Hack. Public to set before fade in? |
@@ -176,11 +195,6 @@ protected: | |||
176 | virtual void allocateListener() = 0; | 195 | virtual void allocateListener() = 0; |
177 | 196 | ||
178 | 197 | ||
179 | // Internet stream methods | ||
180 | virtual void initInternetStream() {} | ||
181 | virtual void updateInternetStream() {} | ||
182 | |||
183 | |||
184 | // listener methods | 198 | // listener methods |
185 | virtual void setListenerPos(LLVector3 vec); | 199 | virtual void setListenerPos(LLVector3 vec); |
186 | virtual void setListenerVelocity(LLVector3 vec); | 200 | virtual void setListenerVelocity(LLVector3 vec); |
@@ -195,13 +209,13 @@ protected: | |||
195 | protected: | 209 | protected: |
196 | LLListener *mListenerp; | 210 | LLListener *mListenerp; |
197 | 211 | ||
198 | BOOL mMuted; | 212 | bool mMuted; |
199 | void* mUserData; | 213 | void* mUserData; |
200 | 214 | ||
201 | S32 mLastStatus; | 215 | S32 mLastStatus; |
202 | 216 | ||
203 | S32 mNumChannels; | 217 | S32 mNumChannels; |
204 | BOOL mEnableWind; | 218 | bool mEnableWind; |
205 | 219 | ||
206 | LLUUID mCurrentTransfer; // Audio file currently being transferred by the system | 220 | LLUUID mCurrentTransfer; // Audio file currently being transferred by the system |
207 | LLFrameTimer mCurrentTransferTimer; | 221 | LLFrameTimer mCurrentTransferTimer; |
@@ -222,9 +236,11 @@ protected: | |||
222 | LLAudioBuffer *mBuffers[MAX_BUFFERS]; | 236 | LLAudioBuffer *mBuffers[MAX_BUFFERS]; |
223 | 237 | ||
224 | F32 mMasterGain; | 238 | F32 mMasterGain; |
239 | F32 mSecondaryGain[AUDIO_TYPE_COUNT]; | ||
225 | 240 | ||
226 | // Hack! Internet streams are treated differently from other sources! | 241 | // Hack! Internet streams are treated differently from other sources! |
227 | F32 mInternetStreamGain; | 242 | F32 mInternetStreamGain; |
243 | std::string mInternetStreamURL; | ||
228 | 244 | ||
229 | F32 mNextWindUpdate; | 245 | F32 mNextWindUpdate; |
230 | 246 | ||
@@ -232,6 +248,7 @@ protected: | |||
232 | 248 | ||
233 | private: | 249 | private: |
234 | void setDefaults(); | 250 | void setDefaults(); |
251 | LLMediaBase *mInternetStreamMedia; | ||
235 | }; | 252 | }; |
236 | 253 | ||
237 | 254 | ||
@@ -247,7 +264,7 @@ class LLAudioSource | |||
247 | public: | 264 | public: |
248 | // 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 |
249 | // play, for example, the owner of the object currently playing it | 266 | // play, for example, the owner of the object currently playing it |
250 | 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); |
251 | virtual ~LLAudioSource(); | 268 | virtual ~LLAudioSource(); |
252 | 269 | ||
253 | virtual void update(); // Update this audio source | 270 | virtual void update(); // Update this audio source |
@@ -255,24 +272,27 @@ public: | |||
255 | 272 | ||
256 | void preload(const LLUUID &audio_id); // Only used for preloading UI sounds, now. | 273 | void preload(const LLUUID &audio_id); // Only used for preloading UI sounds, now. |
257 | 274 | ||
258 | void addAudioData(LLAudioData *adp, BOOL set_current = TRUE); | 275 | void addAudioData(LLAudioData *adp, bool set_current = TRUE); |
276 | |||
277 | void setAmbient(const bool ambient) { mAmbient = ambient; } | ||
278 | bool isAmbient() const { return mAmbient; } | ||
259 | 279 | ||
260 | void setAmbient(const BOOL ambient) { mAmbient = ambient; } | 280 | void setLoop(const bool loop) { mLoop = loop; } |
261 | BOOL isAmbient() const { return mAmbient; } | 281 | bool isLoop() const { return mLoop; } |
262 | 282 | ||
263 | void setLoop(const BOOL loop) { mLoop = loop; } | 283 | void setSyncMaster(const bool master) { mSyncMaster = master; } |
264 | BOOL isLoop() const { return mLoop; } | 284 | bool isSyncMaster() const { return mSyncMaster; } |
265 | 285 | ||
266 | void setSyncMaster(const BOOL master) { mSyncMaster = master; } | 286 | void setSyncSlave(const bool slave) { mSyncSlave = slave; } |
267 | BOOL isSyncMaster() const { return mSyncMaster; } | 287 | bool isSyncSlave() const { return mSyncSlave; } |
268 | 288 | ||
269 | void setSyncSlave(const BOOL slave) { mSyncSlave = slave; } | 289 | void setQueueSounds(const bool queue) { mQueueSounds = queue; } |
270 | BOOL isSyncSlave() const { return mSyncSlave; } | 290 | bool isQueueSounds() const { return mQueueSounds; } |
271 | 291 | ||
272 | void setQueueSounds(const BOOL queue) { mQueueSounds = queue; } | 292 | void setPlayedOnce(const bool played_once) { mPlayedOnce = played_once; } |
273 | BOOL isQueueSounds() const { return mQueueSounds; } | ||
274 | 293 | ||
275 | void setPlayedOnce(const BOOL played_once) { mPlayedOnce = played_once; } | 294 | void setType(S32 type) { mType = type; } |
295 | S32 getType() { return mType; } | ||
276 | 296 | ||
277 | void setPositionGlobal(const LLVector3d &position_global) { mPositionGlobal = position_global; } | 297 | void setPositionGlobal(const LLVector3d &position_global) { mPositionGlobal = position_global; } |
278 | LLVector3d getPositionGlobal() const { return mPositionGlobal; } | 298 | LLVector3d getPositionGlobal() const { return mPositionGlobal; } |
@@ -284,16 +304,16 @@ public: | |||
284 | virtual void setGain(const F32 gain) { mGain = llclamp(gain, 0.f, 1.f); } | 304 | virtual void setGain(const F32 gain) { mGain = llclamp(gain, 0.f, 1.f); } |
285 | 305 | ||
286 | const LLUUID &getID() const { return mID; } | 306 | const LLUUID &getID() const { return mID; } |
287 | BOOL isDone(); | 307 | bool isDone(); |
288 | 308 | ||
289 | LLAudioData *getCurrentData(); | 309 | LLAudioData *getCurrentData(); |
290 | LLAudioData *getQueuedData(); | 310 | LLAudioData *getQueuedData(); |
291 | LLAudioBuffer *getCurrentBuffer(); | 311 | LLAudioBuffer *getCurrentBuffer(); |
292 | 312 | ||
293 | BOOL setupChannel(); | 313 | bool setupChannel(); |
294 | BOOL play(const LLUUID &audio_id); // Start the audio source playing | 314 | bool play(const LLUUID &audio_id); // Start the audio source playing |
295 | 315 | ||
296 | BOOL hasPendingPreloads() const; // Has preloads that haven't been done yet | 316 | bool hasPendingPreloads() const; // Has preloads that haven't been done yet |
297 | 317 | ||
298 | friend class LLAudioEngine; | 318 | friend class LLAudioEngine; |
299 | friend class LLAudioChannel; | 319 | friend class LLAudioChannel; |
@@ -306,12 +326,13 @@ protected: | |||
306 | LLUUID mOwnerID; // owner of the object playing the sound | 326 | LLUUID mOwnerID; // owner of the object playing the sound |
307 | F32 mPriority; | 327 | F32 mPriority; |
308 | F32 mGain; | 328 | F32 mGain; |
309 | BOOL mAmbient; | 329 | bool mAmbient; |
310 | BOOL mLoop; | 330 | bool mLoop; |
311 | BOOL mSyncMaster; | 331 | bool mSyncMaster; |
312 | BOOL mSyncSlave; | 332 | bool mSyncSlave; |
313 | BOOL mQueueSounds; | 333 | bool mQueueSounds; |
314 | BOOL mPlayedOnce; | 334 | bool mPlayedOnce; |
335 | S32 mType; | ||
315 | LLVector3d mPositionGlobal; | 336 | LLVector3d mPositionGlobal; |
316 | LLVector3 mVelocity; | 337 | LLVector3 mVelocity; |
317 | 338 | ||
@@ -340,27 +361,27 @@ class LLAudioData | |||
340 | { | 361 | { |
341 | public: | 362 | public: |
342 | LLAudioData(const LLUUID &uuid); | 363 | LLAudioData(const LLUUID &uuid); |
343 | BOOL load(); | 364 | bool load(); |
344 | 365 | ||
345 | LLUUID getID() const { return mID; } | 366 | LLUUID getID() const { return mID; } |
346 | LLAudioBuffer *getBuffer() const { return mBufferp; } | 367 | LLAudioBuffer *getBuffer() const { return mBufferp; } |
347 | 368 | ||
348 | BOOL hasLocalData() const { return mHasLocalData; } | 369 | bool hasLocalData() const { return mHasLocalData; } |
349 | BOOL hasDecodedData() const { return mHasDecodedData; } | 370 | bool hasDecodedData() const { return mHasDecodedData; } |
350 | BOOL hasValidData() const { return mHasValidData; } | 371 | bool hasValidData() const { return mHasValidData; } |
351 | 372 | ||
352 | void setHasLocalData(const BOOL hld) { mHasLocalData = hld; } | 373 | void setHasLocalData(const bool hld) { mHasLocalData = hld; } |
353 | void setHasDecodedData(const BOOL hdd) { mHasDecodedData = hdd; } | 374 | void setHasDecodedData(const bool hdd) { mHasDecodedData = hdd; } |
354 | void setHasValidData(const BOOL hvd) { mHasValidData = hvd; } | 375 | void setHasValidData(const bool hvd) { mHasValidData = hvd; } |
355 | 376 | ||
356 | friend class LLAudioEngine; // Severe laziness, bad. | 377 | friend class LLAudioEngine; // Severe laziness, bad. |
357 | 378 | ||
358 | protected: | 379 | protected: |
359 | LLUUID mID; | 380 | LLUUID mID; |
360 | LLAudioBuffer *mBufferp; // If this data is being used by the audio system, a pointer to the buffer will be set here. | 381 | LLAudioBuffer *mBufferp; // If this data is being used by the audio system, a pointer to the buffer will be set here. |
361 | BOOL mHasLocalData; | 382 | bool mHasLocalData; |
362 | BOOL mHasDecodedData; | 383 | bool mHasDecodedData; |
363 | BOOL mHasValidData; | 384 | bool mHasValidData; |
364 | }; | 385 | }; |
365 | 386 | ||
366 | 387 | ||
@@ -380,24 +401,28 @@ public: | |||
380 | virtual void setSource(LLAudioSource *sourcep); | 401 | virtual void setSource(LLAudioSource *sourcep); |
381 | LLAudioSource *getSource() const { return mCurrentSourcep; } | 402 | LLAudioSource *getSource() const { return mCurrentSourcep; } |
382 | 403 | ||
404 | void setSecondaryGain(F32 gain) { mSecondaryGain = gain; } | ||
405 | F32 getSecondaryGain() { return mSecondaryGain; } | ||
406 | |||
383 | friend class LLAudioEngine; | 407 | friend class LLAudioEngine; |
384 | friend class LLAudioSource; | 408 | friend class LLAudioSource; |
385 | protected: | 409 | protected: |
386 | virtual void play() = 0; | 410 | virtual void play() = 0; |
387 | virtual void playSynced(LLAudioChannel *channelp) = 0; | 411 | virtual void playSynced(LLAudioChannel *channelp) = 0; |
388 | virtual void cleanup() = 0; | 412 | virtual void cleanup() = 0; |
389 | virtual BOOL isPlaying() = 0; | 413 | virtual bool isPlaying() = 0; |
390 | void setWaiting(const BOOL waiting) { mWaiting = waiting; } | 414 | void setWaiting(const bool waiting) { mWaiting = waiting; } |
391 | BOOL isWaiting() const { return mWaiting; } | 415 | bool isWaiting() const { return mWaiting; } |
392 | 416 | ||
393 | virtual BOOL updateBuffer(); // Check to see if the buffer associated with the source changed, and update if necessary. | 417 | virtual bool updateBuffer(); // Check to see if the buffer associated with the source changed, and update if necessary. |
394 | virtual void update3DPosition() = 0; | 418 | virtual void update3DPosition() = 0; |
395 | virtual void updateLoop() = 0; // Update your loop/completion status, for use by queueing/syncing. | 419 | virtual void updateLoop() = 0; // Update your loop/completion status, for use by queueing/syncing. |
396 | protected: | 420 | protected: |
397 | LLAudioSource *mCurrentSourcep; | 421 | LLAudioSource *mCurrentSourcep; |
398 | LLAudioBuffer *mCurrentBufferp; | 422 | LLAudioBuffer *mCurrentBufferp; |
399 | BOOL mLoopedThisFrame; | 423 | bool mLoopedThisFrame; |
400 | BOOL mWaiting; // Waiting for sync. | 424 | bool mWaiting; // Waiting for sync. |
425 | F32 mSecondaryGain; | ||
401 | }; | 426 | }; |
402 | 427 | ||
403 | 428 | ||
@@ -412,14 +437,14 @@ class LLAudioBuffer | |||
412 | { | 437 | { |
413 | public: | 438 | public: |
414 | virtual ~LLAudioBuffer() {}; | 439 | virtual ~LLAudioBuffer() {}; |
415 | virtual BOOL loadWAV(const std::string& filename) = 0; | 440 | virtual bool loadWAV(const std::string& filename) = 0; |
416 | virtual U32 getLength() = 0; | 441 | virtual U32 getLength() = 0; |
417 | 442 | ||
418 | friend class LLAudioEngine; | 443 | friend class LLAudioEngine; |
419 | friend class LLAudioChannel; | 444 | friend class LLAudioChannel; |
420 | friend class LLAudioData; | 445 | friend class LLAudioData; |
421 | protected: | 446 | protected: |
422 | BOOL mInUse; | 447 | bool mInUse; |
423 | LLAudioData *mAudioDatap; | 448 | LLAudioData *mAudioDatap; |
424 | LLFrameTimer mLastUseTimer; | 449 | LLFrameTimer mLastUseTimer; |
425 | }; | 450 | }; |
diff --git a/linden/indra/llaudio/audioengine_fmod.cpp b/linden/indra/llaudio/audioengine_fmod.cpp index 16d820c..354ef95 100644 --- a/linden/indra/llaudio/audioengine_fmod.cpp +++ b/linden/indra/llaudio/audioengine_fmod.cpp | |||
@@ -1,7 +1,6 @@ | |||
1 | /** | 1 | /** |
2 | * @file audioengine_fmod.cpp | 2 | * @file audioengine_fmod.cpp |
3 | * @brief Implementation of LLAudioEngine class abstracting the audio | 3 | * @brief Implementation of LLAudioEngine class abstracting the audio support as a FMOD 3D implementation |
4 | * support as a FMOD 3D implementation | ||
5 | * | 4 | * |
6 | * $LicenseInfo:firstyear=2002&license=viewergpl$ | 5 | * $LicenseInfo:firstyear=2002&license=viewergpl$ |
7 | * | 6 | * |
@@ -46,27 +45,12 @@ | |||
46 | 45 | ||
47 | #include "sound_ids.h" | 46 | #include "sound_ids.h" |
48 | 47 | ||
48 | extern "C" { | ||
49 | void * F_CALLBACKAPI windCallback(void *originalbuffer, void *newbuffer, int length, void* userdata); | ||
50 | } | ||
49 | 51 | ||
50 | void * F_CALLBACKAPI windCallback(void *originalbuffer, void *newbuffer, int length, void* userdata); | ||
51 | FSOUND_DSPUNIT *gWindDSP = NULL; | 52 | FSOUND_DSPUNIT *gWindDSP = NULL; |
52 | 53 | ||
53 | // These globals for the wind filter. Blech! | ||
54 | F64 gbuf0 = 0.0; | ||
55 | F64 gbuf1 = 0.0; | ||
56 | F64 gbuf2 = 0.0; | ||
57 | F64 gbuf3 = 0.0; | ||
58 | F64 gbuf4 = 0.0; | ||
59 | F64 gbuf5 = 0.0; | ||
60 | F64 gY0 = 0.0; | ||
61 | F64 gY1 = 0.0; | ||
62 | |||
63 | F32 gTargetGain = 0.f; | ||
64 | F32 gCurrentGain = 0.f; | ||
65 | F32 gTargetFreq = 100.f; | ||
66 | F32 gCurrentFreq = 100.f; | ||
67 | F32 gTargetPanGainR = 0.5f; | ||
68 | F32 gCurrentPanGainR = 0.5f; | ||
69 | |||
70 | 54 | ||
71 | // Safe strcpy | 55 | // Safe strcpy |
72 | #if 0 //(unused) //LL_WINDOWS || LL_LINUX | 56 | #if 0 //(unused) //LL_WINDOWS || LL_LINUX |
@@ -94,9 +78,10 @@ static size_t strlcpy( char* dest, const char* src, size_t dst_size ) | |||
94 | 78 | ||
95 | LLAudioEngine_FMOD::LLAudioEngine_FMOD() | 79 | LLAudioEngine_FMOD::LLAudioEngine_FMOD() |
96 | { | 80 | { |
97 | mInited = FALSE; | 81 | mInited = false; |
98 | mCurrentInternetStreamp = NULL; | 82 | mCurrentInternetStreamp = NULL; |
99 | mInternetStreamChannel = -1; | 83 | mInternetStreamChannel = -1; |
84 | mWindGen = NULL; | ||
100 | } | 85 | } |
101 | 86 | ||
102 | 87 | ||
@@ -105,7 +90,7 @@ LLAudioEngine_FMOD::~LLAudioEngine_FMOD() | |||
105 | } | 90 | } |
106 | 91 | ||
107 | 92 | ||
108 | BOOL LLAudioEngine_FMOD::init(const S32 num_channels, void* userdata) | 93 | bool LLAudioEngine_FMOD::init(const S32 num_channels, void* userdata) |
109 | { | 94 | { |
110 | mFadeIn = -10000; | 95 | mFadeIn = -10000; |
111 | 96 | ||
@@ -124,7 +109,7 @@ BOOL LLAudioEngine_FMOD::init(const S32 num_channels, void* userdata) | |||
124 | { | 109 | { |
125 | LL_WARNS("AppInit") << "Error : You are using the wrong FMOD version (" << version | 110 | LL_WARNS("AppInit") << "Error : You are using the wrong FMOD version (" << version |
126 | << ")! You should be using FMOD " << FMOD_VERSION << LL_ENDL; | 111 | << ")! You should be using FMOD " << FMOD_VERSION << LL_ENDL; |
127 | //return FALSE; | 112 | //return false; |
128 | } | 113 | } |
129 | 114 | ||
130 | U32 fmod_flags = 0x0; | 115 | U32 fmod_flags = 0x0; |
@@ -139,7 +124,7 @@ BOOL LLAudioEngine_FMOD::init(const S32 num_channels, void* userdata) | |||
139 | { | 124 | { |
140 | LL_WARNS("AppInit") << "Error setting FMOD window: " | 125 | LL_WARNS("AppInit") << "Error setting FMOD window: " |
141 | << FMOD_ErrorString(FSOUND_GetError()) << LL_ENDL; | 126 | << FMOD_ErrorString(FSOUND_GetError()) << LL_ENDL; |
142 | return FALSE; | 127 | return false; |
143 | } | 128 | } |
144 | // Play audio when we don't have focus. | 129 | // Play audio when we don't have focus. |
145 | // (For example, IM client on top of us.) | 130 | // (For example, IM client on top of us.) |
@@ -167,7 +152,7 @@ BOOL LLAudioEngine_FMOD::init(const S32 num_channels, void* userdata) | |||
167 | // on top of ALSA is ironically more reliable than raw ALSA. | 152 | // on top of ALSA is ironically more reliable than raw ALSA. |
168 | // Ack, and ESD has more reliable failure modes - but has worse | 153 | // Ack, and ESD has more reliable failure modes - but has worse |
169 | // latency - than all of them, so wins for now. | 154 | // latency - than all of them, so wins for now. |
170 | BOOL audio_ok = FALSE; | 155 | bool audio_ok = false; |
171 | 156 | ||
172 | if (!audio_ok) | 157 | if (!audio_ok) |
173 | if (NULL == getenv("LL_BAD_ESD")) /*Flawfinder: ignore*/ | 158 | if (NULL == getenv("LL_BAD_ESD")) /*Flawfinder: ignore*/ |
@@ -178,7 +163,7 @@ BOOL LLAudioEngine_FMOD::init(const S32 num_channels, void* userdata) | |||
178 | { | 163 | { |
179 | LL_DEBUGS("AppInit") << "ESD audio output initialized OKAY" | 164 | LL_DEBUGS("AppInit") << "ESD audio output initialized OKAY" |
180 | << LL_ENDL; | 165 | << LL_ENDL; |
181 | audio_ok = TRUE; | 166 | audio_ok = true; |
182 | } else { | 167 | } else { |
183 | LL_WARNS("AppInit") << "ESD audio output FAILED to initialize: " | 168 | LL_WARNS("AppInit") << "ESD audio output FAILED to initialize: " |
184 | << FMOD_ErrorString(FSOUND_GetError()) << LL_ENDL; | 169 | << FMOD_ErrorString(FSOUND_GetError()) << LL_ENDL; |
@@ -195,7 +180,7 @@ BOOL LLAudioEngine_FMOD::init(const S32 num_channels, void* userdata) | |||
195 | FSOUND_Init(44100, num_channels, fmod_flags)) | 180 | FSOUND_Init(44100, num_channels, fmod_flags)) |
196 | { | 181 | { |
197 | LL_DEBUGS("AppInit") << "OSS audio output initialized OKAY" << LL_ENDL; | 182 | LL_DEBUGS("AppInit") << "OSS audio output initialized OKAY" << LL_ENDL; |
198 | audio_ok = TRUE; | 183 | audio_ok = true; |
199 | } else { | 184 | } else { |
200 | LL_WARNS("AppInit") << "OSS audio output FAILED to initialize: " | 185 | LL_WARNS("AppInit") << "OSS audio output FAILED to initialize: " |
201 | << FMOD_ErrorString(FSOUND_GetError()) << LL_ENDL; | 186 | << FMOD_ErrorString(FSOUND_GetError()) << LL_ENDL; |
@@ -212,7 +197,7 @@ BOOL LLAudioEngine_FMOD::init(const S32 num_channels, void* userdata) | |||
212 | FSOUND_Init(44100, num_channels, fmod_flags)) | 197 | FSOUND_Init(44100, num_channels, fmod_flags)) |
213 | { | 198 | { |
214 | LL_DEBUGS("AppInit") << "ALSA audio output initialized OKAY" << LL_ENDL; | 199 | LL_DEBUGS("AppInit") << "ALSA audio output initialized OKAY" << LL_ENDL; |
215 | audio_ok = TRUE; | 200 | audio_ok = true; |
216 | } else { | 201 | } else { |
217 | LL_WARNS("AppInit") << "ALSA audio output FAILED to initialize: " | 202 | LL_WARNS("AppInit") << "ALSA audio output FAILED to initialize: " |
218 | << FMOD_ErrorString(FSOUND_GetError()) << LL_ENDL; | 203 | << FMOD_ErrorString(FSOUND_GetError()) << LL_ENDL; |
@@ -224,7 +209,7 @@ BOOL LLAudioEngine_FMOD::init(const S32 num_channels, void* userdata) | |||
224 | if (!audio_ok) | 209 | if (!audio_ok) |
225 | { | 210 | { |
226 | LL_WARNS("AppInit") << "Overall audio init failure." << LL_ENDL; | 211 | LL_WARNS("AppInit") << "Overall audio init failure." << LL_ENDL; |
227 | return FALSE; | 212 | return false; |
228 | } | 213 | } |
229 | 214 | ||
230 | // On Linux, FMOD causes a SIGPIPE for some netstream error | 215 | // On Linux, FMOD causes a SIGPIPE for some netstream error |
@@ -250,7 +235,7 @@ BOOL LLAudioEngine_FMOD::init(const S32 num_channels, void* userdata) | |||
250 | { | 235 | { |
251 | LL_WARNS("AppInit") << "Error initializing FMOD: " | 236 | LL_WARNS("AppInit") << "Error initializing FMOD: " |
252 | << FMOD_ErrorString(FSOUND_GetError()) << LL_ENDL; | 237 | << FMOD_ErrorString(FSOUND_GetError()) << LL_ENDL; |
253 | return FALSE; | 238 | return false; |
254 | } | 239 | } |
255 | 240 | ||
256 | #endif | 241 | #endif |
@@ -259,17 +244,9 @@ BOOL LLAudioEngine_FMOD::init(const S32 num_channels, void* userdata) | |||
259 | 244 | ||
260 | LL_DEBUGS("AppInit") << "LLAudioEngine_FMOD::init() FMOD initialized correctly" << LL_ENDL; | 245 | LL_DEBUGS("AppInit") << "LLAudioEngine_FMOD::init() FMOD initialized correctly" << LL_ENDL; |
261 | 246 | ||
262 | mInited = TRUE; | 247 | mInited = true; |
263 | 248 | ||
264 | return TRUE; | 249 | return true; |
265 | } | ||
266 | |||
267 | |||
268 | void LLAudioEngine_FMOD::idle(F32 max_decode_time) | ||
269 | { | ||
270 | LLAudioEngine::idle(max_decode_time); | ||
271 | |||
272 | updateInternetStream(); | ||
273 | } | 250 | } |
274 | 251 | ||
275 | 252 | ||
@@ -287,7 +264,7 @@ void LLAudioEngine_FMOD::shutdown() | |||
287 | { | 264 | { |
288 | if (gWindDSP) | 265 | if (gWindDSP) |
289 | { | 266 | { |
290 | FSOUND_DSP_SetActive(gWindDSP,FALSE); | 267 | FSOUND_DSP_SetActive(gWindDSP,false); |
291 | FSOUND_DSP_Free(gWindDSP); | 268 | FSOUND_DSP_Free(gWindDSP); |
292 | } | 269 | } |
293 | 270 | ||
@@ -318,13 +295,15 @@ LLAudioChannel *LLAudioEngine_FMOD::createChannel() | |||
318 | 295 | ||
319 | void LLAudioEngine_FMOD::initWind() | 296 | void LLAudioEngine_FMOD::initWind() |
320 | { | 297 | { |
298 | mWindGen = new LLWindGen<MIXBUFFERFORMAT>; | ||
299 | |||
321 | if (!gWindDSP) | 300 | if (!gWindDSP) |
322 | { | 301 | { |
323 | gWindDSP = FSOUND_DSP_Create(&windCallback, FSOUND_DSP_DEFAULTPRIORITY_CLEARUNIT + 20, NULL); | 302 | gWindDSP = FSOUND_DSP_Create(&windCallback, FSOUND_DSP_DEFAULTPRIORITY_CLEARUNIT + 20, mWindGen); |
324 | } | 303 | } |
325 | if (gWindDSP) | 304 | if (gWindDSP) |
326 | { | 305 | { |
327 | FSOUND_DSP_SetActive(gWindDSP, TRUE); | 306 | FSOUND_DSP_SetActive(gWindDSP, true); |
328 | } | 307 | } |
329 | mNextWindUpdate = 0.0; | 308 | mNextWindUpdate = 0.0; |
330 | } | 309 | } |
@@ -334,10 +313,13 @@ void LLAudioEngine_FMOD::cleanupWind() | |||
334 | { | 313 | { |
335 | if (gWindDSP) | 314 | if (gWindDSP) |
336 | { | 315 | { |
337 | FSOUND_DSP_SetActive(gWindDSP, FALSE); | 316 | FSOUND_DSP_SetActive(gWindDSP, false); |
338 | FSOUND_DSP_Free(gWindDSP); | 317 | FSOUND_DSP_Free(gWindDSP); |
339 | gWindDSP = NULL; | 318 | gWindDSP = NULL; |
340 | } | 319 | } |
320 | |||
321 | delete mWindGen; | ||
322 | mWindGen = NULL; | ||
341 | } | 323 | } |
342 | 324 | ||
343 | 325 | ||
@@ -367,9 +349,9 @@ void LLAudioEngine_FMOD::updateWind(LLVector3 wind_vec, F32 camera_height_above_ | |||
367 | pitch = 1.0 + mapWindVecToPitch(wind_vec); | 349 | pitch = 1.0 + mapWindVecToPitch(wind_vec); |
368 | center_freq = 80.0 * pow(pitch,2.5*(mapWindVecToGain(wind_vec)+1.0)); | 350 | center_freq = 80.0 * pow(pitch,2.5*(mapWindVecToGain(wind_vec)+1.0)); |
369 | 351 | ||
370 | gTargetFreq = (F32)center_freq; | 352 | mWindGen->mTargetFreq = (F32)center_freq; |
371 | gTargetGain = (F32)mapWindVecToGain(wind_vec) * mMaxWindGain; | 353 | mWindGen->mTargetGain = (F32)mapWindVecToGain(wind_vec) * mMaxWindGain; |
372 | gTargetPanGainR = (F32)mapWindVecToPan(wind_vec); | 354 | mWindGen->mTargetPanGainR = (F32)mapWindVecToPan(wind_vec); |
373 | } | 355 | } |
374 | } | 356 | } |
375 | 357 | ||
@@ -457,11 +439,11 @@ LLAudioChannelFMOD::~LLAudioChannelFMOD() | |||
457 | } | 439 | } |
458 | 440 | ||
459 | 441 | ||
460 | BOOL LLAudioChannelFMOD::updateBuffer() | 442 | bool LLAudioChannelFMOD::updateBuffer() |
461 | { | 443 | { |
462 | if (LLAudioChannel::updateBuffer()) | 444 | if (LLAudioChannel::updateBuffer()) |
463 | { | 445 | { |
464 | // Base class update returned TRUE, which means that we need to actually | 446 | // Base class update returned true, which means that we need to actually |
465 | // set up the channel for a different buffer. | 447 | // set up the channel for a different buffer. |
466 | 448 | ||
467 | LLAudioBufferFMOD *bufferp = (LLAudioBufferFMOD *)mCurrentSourcep->getCurrentBuffer(); | 449 | LLAudioBufferFMOD *bufferp = (LLAudioBufferFMOD *)mCurrentSourcep->getCurrentBuffer(); |
@@ -473,13 +455,13 @@ BOOL LLAudioChannelFMOD::updateBuffer() | |||
473 | // This is bad, there should ALWAYS be a sample associated with a legit | 455 | // This is bad, there should ALWAYS be a sample associated with a legit |
474 | // buffer. | 456 | // buffer. |
475 | llerrs << "No FMOD sample!" << llendl; | 457 | llerrs << "No FMOD sample!" << llendl; |
476 | return FALSE; | 458 | return false; |
477 | } | 459 | } |
478 | 460 | ||
479 | 461 | ||
480 | // Actually play the sound. Start it off paused so we can do all the necessary | 462 | // Actually play the sound. Start it off paused so we can do all the necessary |
481 | // setup. | 463 | // setup. |
482 | mChannelID = FSOUND_PlaySoundEx(FSOUND_FREE, samplep, FSOUND_DSP_GetSFXUnit(), TRUE); | 464 | mChannelID = FSOUND_PlaySoundEx(FSOUND_FREE, samplep, FSOUND_DSP_GetSFXUnit(), true); |
483 | 465 | ||
484 | //llinfos << "Setting up channel " << std::hex << mChannelID << std::dec << llendl; | 466 | //llinfos << "Setting up channel " << std::hex << mChannelID << std::dec << llendl; |
485 | } | 467 | } |
@@ -501,7 +483,7 @@ BOOL LLAudioChannelFMOD::updateBuffer() | |||
501 | } | 483 | } |
502 | } | 484 | } |
503 | 485 | ||
504 | return TRUE; | 486 | return true; |
505 | } | 487 | } |
506 | 488 | ||
507 | 489 | ||
@@ -524,12 +506,12 @@ void LLAudioChannelFMOD::update3DPosition() | |||
524 | if (mCurrentSourcep->isAmbient()) | 506 | if (mCurrentSourcep->isAmbient()) |
525 | { | 507 | { |
526 | // Ambient sound, don't need to do any positional updates. | 508 | // Ambient sound, don't need to do any positional updates. |
527 | bufferp->set3DMode(FALSE); | 509 | bufferp->set3DMode(false); |
528 | } | 510 | } |
529 | else | 511 | else |
530 | { | 512 | { |
531 | // Localized sound. Update the position and velocity of the sound. | 513 | // Localized sound. Update the position and velocity of the sound. |
532 | bufferp->set3DMode(TRUE); | 514 | bufferp->set3DMode(true); |
533 | 515 | ||
534 | LLVector3 float_pos; | 516 | LLVector3 float_pos; |
535 | float_pos.setVec(mCurrentSourcep->getPositionGlobal()); | 517 | float_pos.setVec(mCurrentSourcep->getPositionGlobal()); |
@@ -556,7 +538,7 @@ void LLAudioChannelFMOD::updateLoop() | |||
556 | U32 cur_pos = FSOUND_GetCurrentPosition(mChannelID); | 538 | U32 cur_pos = FSOUND_GetCurrentPosition(mChannelID); |
557 | if (cur_pos < (U32)mLastSamplePos) | 539 | if (cur_pos < (U32)mLastSamplePos) |
558 | { | 540 | { |
559 | mLoopedThisFrame = TRUE; | 541 | mLoopedThisFrame = true; |
560 | } | 542 | } |
561 | mLastSamplePos = cur_pos; | 543 | mLastSamplePos = cur_pos; |
562 | } | 544 | } |
@@ -589,11 +571,11 @@ void LLAudioChannelFMOD::play() | |||
589 | return; | 571 | return; |
590 | } | 572 | } |
591 | 573 | ||
592 | if (!FSOUND_SetPaused(mChannelID, FALSE)) | 574 | if (!FSOUND_SetPaused(mChannelID, false)) |
593 | { | 575 | { |
594 | llwarns << "LLAudioChannelFMOD::play error: " << FMOD_ErrorString(FSOUND_GetError()) << llendl; | 576 | llwarns << "LLAudioChannelFMOD::play error: " << FMOD_ErrorString(FSOUND_GetError()) << llendl; |
595 | } | 577 | } |
596 | getSource()->setPlayedOnce(TRUE); | 578 | getSource()->setPlayedOnce(true); |
597 | } | 579 | } |
598 | 580 | ||
599 | 581 | ||
@@ -618,11 +600,11 @@ void LLAudioChannelFMOD::playSynced(LLAudioChannel *channelp) | |||
618 | } | 600 | } |
619 | 601 | ||
620 | 602 | ||
621 | BOOL LLAudioChannelFMOD::isPlaying() | 603 | bool LLAudioChannelFMOD::isPlaying() |
622 | { | 604 | { |
623 | if (!mChannelID) | 605 | if (!mChannelID) |
624 | { | 606 | { |
625 | return FALSE; | 607 | return false; |
626 | } | 608 | } |
627 | 609 | ||
628 | return FSOUND_IsPlaying(mChannelID) && (!FSOUND_GetPaused(mChannelID)); | 610 | return FSOUND_IsPlaying(mChannelID) && (!FSOUND_GetPaused(mChannelID)); |
@@ -652,14 +634,14 @@ LLAudioBufferFMOD::~LLAudioBufferFMOD() | |||
652 | } | 634 | } |
653 | 635 | ||
654 | 636 | ||
655 | BOOL LLAudioBufferFMOD::loadWAV(const std::string& filename) | 637 | bool LLAudioBufferFMOD::loadWAV(const std::string& filename) |
656 | { | 638 | { |
657 | // Try to open a wav file from disk. This will eventually go away, as we don't | 639 | // Try to open a wav file from disk. This will eventually go away, as we don't |
658 | // really want to block doing this. | 640 | // really want to block doing this. |
659 | if (filename.empty()) | 641 | if (filename.empty()) |
660 | { | 642 | { |
661 | // invalid filename, abort. | 643 | // invalid filename, abort. |
662 | return FALSE; | 644 | return false; |
663 | } | 645 | } |
664 | 646 | ||
665 | S32 file_size = 0; | 647 | S32 file_size = 0; |
@@ -667,7 +649,7 @@ BOOL LLAudioBufferFMOD::loadWAV(const std::string& filename) | |||
667 | if (!apr_file) | 649 | if (!apr_file) |
668 | { | 650 | { |
669 | // File not found, abort. | 651 | // File not found, abort. |
670 | return FALSE; | 652 | return false; |
671 | } | 653 | } |
672 | apr_file_close(apr_file); | 654 | apr_file_close(apr_file); |
673 | 655 | ||
@@ -717,11 +699,11 @@ BOOL LLAudioBufferFMOD::loadWAV(const std::string& filename) | |||
717 | // | 699 | // |
718 | // file is probably corrupt - remove it. | 700 | // file is probably corrupt - remove it. |
719 | LLFile::remove(filename); | 701 | LLFile::remove(filename); |
720 | return FALSE; | 702 | return false; |
721 | } | 703 | } |
722 | 704 | ||
723 | // Everything went well, return TRUE | 705 | // Everything went well, return true |
724 | return TRUE; | 706 | return true; |
725 | } | 707 | } |
726 | 708 | ||
727 | 709 | ||
@@ -736,7 +718,7 @@ U32 LLAudioBufferFMOD::getLength() | |||
736 | } | 718 | } |
737 | 719 | ||
738 | 720 | ||
739 | void LLAudioBufferFMOD::set3DMode(BOOL use3d) | 721 | void LLAudioBufferFMOD::set3DMode(bool use3d) |
740 | { | 722 | { |
741 | U16 current_mode = FSOUND_Sample_GetMode(mSamplep); | 723 | U16 current_mode = FSOUND_Sample_GetMode(mSamplep); |
742 | 724 | ||
@@ -765,7 +747,7 @@ void LLAudioEngine_FMOD::initInternetStream() | |||
765 | { | 747 | { |
766 | // Number of milliseconds of audio to buffer for the audio card. | 748 | // Number of milliseconds of audio to buffer for the audio card. |
767 | // Must be larger than the usual Second Life frame stutter time. | 749 | // Must be larger than the usual Second Life frame stutter time. |
768 | FSOUND_Stream_SetBufferSize(200); | 750 | FSOUND_Stream_SetBufferSize(200); |
769 | 751 | ||
770 | // Here's where we set the size of the network buffer and some buffering | 752 | // Here's where we set the size of the network buffer and some buffering |
771 | // parameters. In this case we want a network buffer of 16k, we want it | 753 | // parameters. In this case we want a network buffer of 16k, we want it |
@@ -810,19 +792,19 @@ signed char F_CALLBACKAPI LLAudioEngine_FMOD::callbackMetaData(char *name, char | |||
810 | if (!strcmp("ARTIST", name)) | 792 | if (!strcmp("ARTIST", name)) |
811 | { | 793 | { |
812 | strlcpy(self->mInternetStreamArtist, value, 256); | 794 | strlcpy(self->mInternetStreamArtist, value, 256); |
813 | self->mInternetStreamNewMetaData = TRUE; | 795 | self->mInternetStreamNewMetaData = true; |
814 | return TRUE; | 796 | return true; |
815 | } | 797 | } |
816 | 798 | ||
817 | if (!strcmp("TITLE", name)) | 799 | if (!strcmp("TITLE", name)) |
818 | { | 800 | { |
819 | strlcpy(self->mInternetStreamTitle, value, 256); | 801 | strlcpy(self->mInternetStreamTitle, value, 256); |
820 | self->mInternetStreamNewMetaData = TRUE; | 802 | self->mInternetStreamNewMetaData = true; |
821 | return TRUE; | 803 | return true; |
822 | } | 804 | } |
823 | */ | 805 | */ |
824 | 806 | ||
825 | return TRUE; | 807 | return true; |
826 | } | 808 | } |
827 | 809 | ||
828 | 810 | ||
@@ -867,7 +849,7 @@ void LLAudioEngine_FMOD::updateInternetStream() | |||
867 | { | 849 | { |
868 | // Reset volume to previously set volume | 850 | // Reset volume to previously set volume |
869 | setInternetStreamGain(mInternetStreamGain); | 851 | setInternetStreamGain(mInternetStreamGain); |
870 | FSOUND_SetPaused(mInternetStreamChannel, FALSE); | 852 | FSOUND_SetPaused(mInternetStreamChannel, false); |
871 | //FSOUND_Stream_Net_SetMetadataCallback(mInternetStream, callbackMetaData, this); | 853 | //FSOUND_Stream_Net_SetMetadataCallback(mInternetStream, callbackMetaData, this); |
872 | } | 854 | } |
873 | } | 855 | } |
@@ -909,7 +891,7 @@ void LLAudioEngine_FMOD::stopInternetStream() | |||
909 | { | 891 | { |
910 | if (mInternetStreamChannel != -1) | 892 | if (mInternetStreamChannel != -1) |
911 | { | 893 | { |
912 | FSOUND_SetPaused(mInternetStreamChannel, TRUE); | 894 | FSOUND_SetPaused(mInternetStreamChannel, true); |
913 | FSOUND_SetPriority(mInternetStreamChannel, 0); | 895 | FSOUND_SetPriority(mInternetStreamChannel, 0); |
914 | mInternetStreamChannel = -1; | 896 | mInternetStreamChannel = -1; |
915 | } | 897 | } |
@@ -971,16 +953,10 @@ int LLAudioEngine_FMOD::isInternetStreamPlaying() | |||
971 | } | 953 | } |
972 | 954 | ||
973 | 955 | ||
974 | void LLAudioEngine_FMOD::getInternetStreamInfo(char* artist_out, char* title_out) | ||
975 | { | ||
976 | //strlcpy(artist_out, mInternetStreamArtist, 256); | ||
977 | //strlcpy(title_out, mInternetStreamTitle, 256); | ||
978 | } | ||
979 | |||
980 | |||
981 | void LLAudioEngine_FMOD::setInternetStreamGain(F32 vol) | 956 | void LLAudioEngine_FMOD::setInternetStreamGain(F32 vol) |
982 | { | 957 | { |
983 | LLAudioEngine::setInternetStreamGain(vol); | 958 | mInternetStreamGain = vol; |
959 | |||
984 | if (mInternetStreamChannel != -1) | 960 | if (mInternetStreamChannel != -1) |
985 | { | 961 | { |
986 | vol = llclamp(vol, 0.f, 1.f); | 962 | vol = llclamp(vol, 0.f, 1.f); |
@@ -990,15 +966,9 @@ void LLAudioEngine_FMOD::setInternetStreamGain(F32 vol) | |||
990 | } | 966 | } |
991 | 967 | ||
992 | 968 | ||
993 | const std::string& LLAudioEngine_FMOD::getInternetStreamURL() | ||
994 | { | ||
995 | return mInternetStreamURL; | ||
996 | } | ||
997 | |||
998 | |||
999 | LLAudioStreamFMOD::LLAudioStreamFMOD(const std::string& url) : | 969 | LLAudioStreamFMOD::LLAudioStreamFMOD(const std::string& url) : |
1000 | mInternetStream(NULL), | 970 | mInternetStream(NULL), |
1001 | mReady(FALSE) | 971 | mReady(false) |
1002 | { | 972 | { |
1003 | mInternetStreamURL = url; | 973 | mInternetStreamURL = url; |
1004 | mInternetStream = FSOUND_Stream_Open(url.c_str(), FSOUND_NORMAL | FSOUND_NONBLOCKING, 0, 0); | 974 | mInternetStream = FSOUND_Stream_Open(url.c_str(), FSOUND_NORMAL | FSOUND_NONBLOCKING, 0, 0); |
@@ -1007,11 +977,11 @@ LLAudioStreamFMOD::LLAudioStreamFMOD(const std::string& url) : | |||
1007 | llwarns << "Couldn't open fmod stream, error " | 977 | llwarns << "Couldn't open fmod stream, error " |
1008 | << FMOD_ErrorString(FSOUND_GetError()) | 978 | << FMOD_ErrorString(FSOUND_GetError()) |
1009 | << llendl; | 979 | << llendl; |
1010 | mReady = FALSE; | 980 | mReady = false; |
1011 | return; | 981 | return; |
1012 | } | 982 | } |
1013 | 983 | ||
1014 | mReady = TRUE; | 984 | mReady = true; |
1015 | } | 985 | } |
1016 | 986 | ||
1017 | int LLAudioStreamFMOD::startStream() | 987 | int LLAudioStreamFMOD::startStream() |
@@ -1026,10 +996,10 @@ int LLAudioStreamFMOD::startStream() | |||
1026 | // Make sure the stream is set to 2D mode. | 996 | // Make sure the stream is set to 2D mode. |
1027 | FSOUND_Stream_SetMode(mInternetStream, FSOUND_2D); | 997 | FSOUND_Stream_SetMode(mInternetStream, FSOUND_2D); |
1028 | 998 | ||
1029 | return FSOUND_Stream_PlayEx(FSOUND_FREE, mInternetStream, NULL, TRUE); | 999 | return FSOUND_Stream_PlayEx(FSOUND_FREE, mInternetStream, NULL, true); |
1030 | } | 1000 | } |
1031 | 1001 | ||
1032 | BOOL LLAudioStreamFMOD::stopStream() | 1002 | bool LLAudioStreamFMOD::stopStream() |
1033 | { | 1003 | { |
1034 | if (mInternetStream) | 1004 | if (mInternetStream) |
1035 | { | 1005 | { |
@@ -1039,34 +1009,34 @@ BOOL LLAudioStreamFMOD::stopStream() | |||
1039 | unsigned int flags = 0x0; | 1009 | unsigned int flags = 0x0; |
1040 | FSOUND_Stream_Net_GetStatus(mInternetStream, &status, &read_percent, &bitrate, &flags); | 1010 | FSOUND_Stream_Net_GetStatus(mInternetStream, &status, &read_percent, &bitrate, &flags); |
1041 | 1011 | ||
1042 | BOOL close = TRUE; | 1012 | bool close = true; |
1043 | switch (status) | 1013 | switch (status) |
1044 | { | 1014 | { |
1045 | case FSOUND_STREAM_NET_CONNECTING: | 1015 | case FSOUND_STREAM_NET_CONNECTING: |
1046 | close = FALSE; | 1016 | close = false; |
1047 | break; | 1017 | break; |
1048 | case FSOUND_STREAM_NET_NOTCONNECTED: | 1018 | case FSOUND_STREAM_NET_NOTCONNECTED: |
1049 | case FSOUND_STREAM_NET_BUFFERING: | 1019 | case FSOUND_STREAM_NET_BUFFERING: |
1050 | case FSOUND_STREAM_NET_READY: | 1020 | case FSOUND_STREAM_NET_READY: |
1051 | case FSOUND_STREAM_NET_ERROR: | 1021 | case FSOUND_STREAM_NET_ERROR: |
1052 | default: | 1022 | default: |
1053 | close = TRUE; | 1023 | close = true; |
1054 | } | 1024 | } |
1055 | 1025 | ||
1056 | if (close) | 1026 | if (close) |
1057 | { | 1027 | { |
1058 | FSOUND_Stream_Close(mInternetStream); | 1028 | FSOUND_Stream_Close(mInternetStream); |
1059 | mInternetStream = NULL; | 1029 | mInternetStream = NULL; |
1060 | return TRUE; | 1030 | return true; |
1061 | } | 1031 | } |
1062 | else | 1032 | else |
1063 | { | 1033 | { |
1064 | return FALSE; | 1034 | return false; |
1065 | } | 1035 | } |
1066 | } | 1036 | } |
1067 | else | 1037 | else |
1068 | { | 1038 | { |
1069 | return TRUE; | 1039 | return true; |
1070 | } | 1040 | } |
1071 | } | 1041 | } |
1072 | 1042 | ||
@@ -1076,94 +1046,35 @@ int LLAudioStreamFMOD::getOpenState() | |||
1076 | return open_state; | 1046 | return open_state; |
1077 | } | 1047 | } |
1078 | 1048 | ||
1079 | /* This determines the format of the mixbuffer being passed in. change if you want to support int32 or float32 */ | 1049 | void * F_CALLBACKAPI windCallback(void *originalbuffer, void *newbuffer, int length, void* userdata) |
1080 | #if LL_DARWIN | ||
1081 | #define MIXBUFFERFORMAT S32 | ||
1082 | #else | ||
1083 | #define MIXBUFFERFORMAT S16 | ||
1084 | #endif | ||
1085 | |||
1086 | inline MIXBUFFERFORMAT clipSample(MIXBUFFERFORMAT sample, MIXBUFFERFORMAT min, MIXBUFFERFORMAT max) | ||
1087 | { | ||
1088 | if (sample > max) | ||
1089 | sample = max; | ||
1090 | else if (sample < min) | ||
1091 | sample = min; | ||
1092 | |||
1093 | return sample; | ||
1094 | } | ||
1095 | |||
1096 | void * F_CALLBACKAPI windCallback(void *originalbuffer, void *newbuffer, int length, void*) | ||
1097 | { | 1050 | { |
1098 | // originalbuffer = fsounds original mixbuffer. | 1051 | // originalbuffer = fmod's original mixbuffer. |
1099 | // newbuffer = the buffer passed from the previous DSP unit. | 1052 | // newbuffer = the buffer passed from the previous DSP unit. |
1100 | // length = length in samples at this mix time. | 1053 | // length = length in samples at this mix time. |
1101 | // param = user parameter passed through in FSOUND_DSP_Create. | 1054 | // param = user parameter passed through in FSOUND_DSP_Create. |
1102 | // | 1055 | // |
1103 | // modify the buffer in some fashion | 1056 | // modify the buffer in some fashion |
1104 | 1057 | ||
1105 | U8 *cursamplep = (U8*)newbuffer; | 1058 | LLWindGen<LLAudioEngine_FMOD::MIXBUFFERFORMAT> *windgen = |
1106 | U8 wordsize = 2; | 1059 | (LLWindGen<LLAudioEngine_FMOD::MIXBUFFERFORMAT> *)userdata; |
1060 | U8 stride; | ||
1107 | 1061 | ||
1108 | #if LL_DARWIN | 1062 | #if LL_DARWIN |
1109 | wordsize = sizeof(MIXBUFFERFORMAT); | 1063 | stride = sizeof(LLAudioEngine_FMOD::MIXBUFFERFORMAT); |
1110 | #else | 1064 | #else |
1111 | int mixertype = FSOUND_GetMixer(); | 1065 | int mixertype = FSOUND_GetMixer(); |
1112 | if (mixertype == FSOUND_MIXER_BLENDMODE || mixertype == FSOUND_MIXER_QUALITY_FPU) | 1066 | if (mixertype == FSOUND_MIXER_BLENDMODE || |
1113 | { | 1067 | mixertype == FSOUND_MIXER_QUALITY_FPU) |
1114 | wordsize = 4; | 1068 | { |
1115 | } | 1069 | stride = 4; |
1116 | #endif | 1070 | } |
1117 | 1071 | else | |
1118 | double bandwidth = 50; | 1072 | { |
1119 | double inputSamplingRate = 44100; | 1073 | stride = 2; |
1120 | double a0,b1,b2; | 1074 | } |
1121 | |||
1122 | // calculate resonant filter coeffs | ||
1123 | b2 = exp(-(F_TWO_PI) * (bandwidth / inputSamplingRate)); | ||
1124 | |||
1125 | while (length--) | ||
1126 | { | ||
1127 | gCurrentFreq = (float)((0.999 * gCurrentFreq) + (0.001 * gTargetFreq)); | ||
1128 | gCurrentGain = (float)((0.999 * gCurrentGain) + (0.001 * gTargetGain)); | ||
1129 | gCurrentPanGainR = (float)((0.999 * gCurrentPanGainR) + (0.001 * gTargetPanGainR)); | ||
1130 | b1 = (-4.0 * b2) / (1.0 + b2) * cos(F_TWO_PI * (gCurrentFreq / inputSamplingRate)); | ||
1131 | a0 = (1.0 - b2) * sqrt(1.0 - (b1 * b1) / (4.0 * b2)); | ||
1132 | double nextSample; | ||
1133 | |||
1134 | // start with white noise | ||
1135 | nextSample = ll_frand(2.0f) - 1.0f; | ||
1136 | |||
1137 | #if 1 // LLAE_WIND_PINK apply pinking filter | ||
1138 | gbuf0 = 0.997f * gbuf0 + 0.0126502f * nextSample; | ||
1139 | gbuf1 = 0.985f * gbuf1 + 0.0139083f * nextSample; | ||
1140 | gbuf2 = 0.950f * gbuf2 + 0.0205439f * nextSample; | ||
1141 | gbuf3 = 0.850f * gbuf3 + 0.0387225f * nextSample; | ||
1142 | gbuf4 = 0.620f * gbuf4 + 0.0465932f * nextSample; | ||
1143 | gbuf5 = 0.250f * gbuf5 + 0.1093477f * nextSample; | ||
1144 | |||
1145 | nextSample = gbuf0 + gbuf1 + gbuf2 + gbuf3 + gbuf4 + gbuf5; | ||
1146 | #endif | ||
1147 | |||
1148 | #if 1 //LLAE_WIND_RESONANT // do a resonant filter on the noise | ||
1149 | nextSample = (double)( a0 * nextSample - b1 * gY0 - b2 * gY1 ); | ||
1150 | |||
1151 | gY1 = gY0; | ||
1152 | gY0 = nextSample; | ||
1153 | #endif | 1075 | #endif |
1154 | 1076 | ||
1155 | nextSample *= gCurrentGain; | 1077 | newbuffer = windgen->windGenerate((LLAudioEngine_FMOD::MIXBUFFERFORMAT *)newbuffer, length, stride); |
1156 | |||
1157 | MIXBUFFERFORMAT sample; | ||
1158 | |||
1159 | sample = llfloor(((F32)nextSample*32768.f*(1.0f - gCurrentPanGainR))+0.5f); | ||
1160 | *(MIXBUFFERFORMAT*)cursamplep = clipSample((*(MIXBUFFERFORMAT*)cursamplep) + sample, -32768, 32767); | ||
1161 | cursamplep += wordsize; | ||
1162 | |||
1163 | sample = llfloor(((F32)nextSample*32768.f*gCurrentPanGainR)+0.5f); | ||
1164 | *(MIXBUFFERFORMAT*)cursamplep = clipSample((*(MIXBUFFERFORMAT*)cursamplep) + sample, -32768, 32767); | ||
1165 | cursamplep += wordsize; | ||
1166 | } | ||
1167 | 1078 | ||
1168 | return newbuffer; | 1079 | return newbuffer; |
1169 | } | 1080 | } |
diff --git a/linden/indra/llaudio/audioengine_fmod.h b/linden/indra/llaudio/audioengine_fmod.h index 41177b6..132afb1 100644 --- a/linden/indra/llaudio/audioengine_fmod.h +++ b/linden/indra/llaudio/audioengine_fmod.h | |||
@@ -35,6 +35,7 @@ | |||
35 | 35 | ||
36 | #include "audioengine.h" | 36 | #include "audioengine.h" |
37 | #include "listener_fmod.h" | 37 | #include "listener_fmod.h" |
38 | #include "windgen.h" | ||
38 | 39 | ||
39 | #include "fmod.h" | 40 | #include "fmod.h" |
40 | 41 | ||
@@ -47,13 +48,11 @@ public: | |||
47 | virtual ~LLAudioEngine_FMOD(); | 48 | virtual ~LLAudioEngine_FMOD(); |
48 | 49 | ||
49 | // initialization/startup/shutdown | 50 | // initialization/startup/shutdown |
50 | virtual BOOL init(const S32 num_channels, void *user_data); | 51 | virtual bool init(const S32 num_channels, void *user_data); |
51 | virtual void allocateListener(); | 52 | virtual void allocateListener(); |
52 | 53 | ||
53 | virtual void shutdown(); | 54 | virtual void shutdown(); |
54 | 55 | ||
55 | virtual void idle(F32 max_decode_time = 0.f); | ||
56 | |||
57 | // Internet stream methods | 56 | // Internet stream methods |
58 | virtual void initInternetStream(); | 57 | virtual void initInternetStream(); |
59 | virtual void startInternetStream(const std::string& url); | 58 | virtual void startInternetStream(const std::string& url); |
@@ -61,15 +60,19 @@ public: | |||
61 | virtual void stopInternetStream(); | 60 | virtual void stopInternetStream(); |
62 | virtual void pauseInternetStream(int pause); | 61 | virtual void pauseInternetStream(int pause); |
63 | virtual int isInternetStreamPlaying(); | 62 | virtual int isInternetStreamPlaying(); |
64 | virtual void getInternetStreamInfo(char* artist, char* title); | ||
65 | virtual void setInternetStreamGain(F32 vol); | 63 | virtual void setInternetStreamGain(F32 vol); |
66 | virtual const std::string& getInternetStreamURL(); | ||
67 | 64 | ||
68 | /*virtual*/ void initWind(); | 65 | /*virtual*/ void initWind(); |
69 | /*virtual*/ void cleanupWind(); | 66 | /*virtual*/ void cleanupWind(); |
70 | 67 | ||
71 | /*virtual*/void updateWind(LLVector3 direction, F32 camera_height_above_water); | 68 | /*virtual*/void updateWind(LLVector3 direction, F32 camera_height_above_water); |
72 | 69 | ||
70 | #if LL_DARWIN | ||
71 | typedef S32 MIXBUFFERFORMAT; | ||
72 | #else | ||
73 | typedef S16 MIXBUFFERFORMAT; | ||
74 | #endif | ||
75 | |||
73 | protected: | 76 | protected: |
74 | /*virtual*/ LLAudioBuffer *createBuffer(); // Get a free buffer, or flush an existing one if you have to. | 77 | /*virtual*/ LLAudioBuffer *createBuffer(); // Get a free buffer, or flush an existing one if you have to. |
75 | /*virtual*/ LLAudioChannel *createChannel(); // Create a new audio channel. | 78 | /*virtual*/ LLAudioChannel *createChannel(); // Create a new audio channel. |
@@ -79,7 +82,6 @@ protected: | |||
79 | static signed char F_CALLBACKAPI callbackMetaData(char* name, char* value, void* userdata); | 82 | static signed char F_CALLBACKAPI callbackMetaData(char* name, char* value, void* userdata); |
80 | 83 | ||
81 | LLAudioStreamFMOD *mCurrentInternetStreamp; | 84 | LLAudioStreamFMOD *mCurrentInternetStreamp; |
82 | std::string mInternetStreamURL; | ||
83 | int mInternetStreamChannel; | 85 | int mInternetStreamChannel; |
84 | 86 | ||
85 | std::list<LLAudioStreamFMOD *> mDeadStreams; | 87 | std::list<LLAudioStreamFMOD *> mDeadStreams; |
@@ -88,11 +90,12 @@ protected: | |||
88 | //F32 mMaxDistance[MAX_BUFFERS]; | 90 | //F32 mMaxDistance[MAX_BUFFERS]; |
89 | 91 | ||
90 | S32 mFadeIn; | 92 | S32 mFadeIn; |
91 | BOOL mInited; | 93 | bool mInited; |
92 | 94 | ||
93 | // On Windows, userdata is the HWND of the application window. | 95 | // On Windows, userdata is the HWND of the application window. |
94 | void* mUserData; | 96 | void* mUserData; |
95 | 97 | ||
98 | LLWindGen<MIXBUFFERFORMAT> *mWindGen; | ||
96 | }; | 99 | }; |
97 | 100 | ||
98 | 101 | ||
@@ -106,9 +109,9 @@ protected: | |||
106 | /*virtual*/ void play(); | 109 | /*virtual*/ void play(); |
107 | /*virtual*/ void playSynced(LLAudioChannel *channelp); | 110 | /*virtual*/ void playSynced(LLAudioChannel *channelp); |
108 | /*virtual*/ void cleanup(); | 111 | /*virtual*/ void cleanup(); |
109 | /*virtual*/ BOOL isPlaying(); | 112 | /*virtual*/ bool isPlaying(); |
110 | 113 | ||
111 | /*virtual*/ BOOL updateBuffer(); | 114 | /*virtual*/ bool updateBuffer(); |
112 | /*virtual*/ void update3DPosition(); | 115 | /*virtual*/ void update3DPosition(); |
113 | /*virtual*/ void updateLoop(); | 116 | /*virtual*/ void updateLoop(); |
114 | 117 | ||
@@ -124,11 +127,11 @@ public: | |||
124 | LLAudioBufferFMOD(); | 127 | LLAudioBufferFMOD(); |
125 | virtual ~LLAudioBufferFMOD(); | 128 | virtual ~LLAudioBufferFMOD(); |
126 | 129 | ||
127 | /*virtual*/ BOOL loadWAV(const std::string& filename); | 130 | /*virtual*/ bool loadWAV(const std::string& filename); |
128 | /*virtual*/ U32 getLength(); | 131 | /*virtual*/ U32 getLength(); |
129 | friend class LLAudioChannelFMOD; | 132 | friend class LLAudioChannelFMOD; |
130 | 133 | ||
131 | void set3DMode(BOOL use3d); | 134 | void set3DMode(bool use3d); |
132 | protected: | 135 | protected: |
133 | FSOUND_SAMPLE *getSample() { return mSamplep; } | 136 | FSOUND_SAMPLE *getSample() { return mSamplep; } |
134 | protected: | 137 | protected: |
@@ -140,15 +143,15 @@ class LLAudioStreamFMOD | |||
140 | public: | 143 | public: |
141 | LLAudioStreamFMOD(const std::string& url); | 144 | LLAudioStreamFMOD(const std::string& url); |
142 | int startStream(); | 145 | int startStream(); |
143 | BOOL stopStream(); // Returns true if the stream was successfully stopped. | 146 | bool stopStream(); // Returns true if the stream was successfully stopped. |
144 | BOOL ready(); | 147 | bool ready(); |
145 | 148 | ||
146 | const std::string& getURL() { return mInternetStreamURL; } | 149 | const std::string& getURL() { return mInternetStreamURL; } |
147 | 150 | ||
148 | int getOpenState(); | 151 | int getOpenState(); |
149 | protected: | 152 | protected: |
150 | FSOUND_STREAM* mInternetStream; | 153 | FSOUND_STREAM* mInternetStream; |
151 | BOOL mReady; | 154 | bool mReady; |
152 | 155 | ||
153 | std::string mInternetStreamURL; | 156 | std::string mInternetStreamURL; |
154 | }; | 157 | }; |
diff --git a/linden/indra/llaudio/audioengine_openal.cpp b/linden/indra/llaudio/audioengine_openal.cpp new file mode 100644 index 0000000..002dfba --- /dev/null +++ b/linden/indra/llaudio/audioengine_openal.cpp | |||
@@ -0,0 +1,544 @@ | |||
1 | /** | ||
2 | * @file audioengine_openal.cpp | ||
3 | * @brief implementation of audio engine using OpenAL | ||
4 | * support as a OpenAL 3D implementation | ||
5 | * | ||
6 | * $LicenseInfo:firstyear=2002&license=viewergpl$ | ||
7 | * | ||
8 | * Copyright (c) 2002-2008, Linden Research, Inc. | ||
9 | * | ||
10 | * Second Life Viewer Source Code | ||
11 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
12 | * to you under the terms of the GNU General Public License, version 2.0 | ||
13 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
14 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
15 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
16 | * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 | ||
17 | * | ||
18 | * There are special exceptions to the terms and conditions of the GPL as | ||
19 | * it is applied to this Source Code. View the full text of the exception | ||
20 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
21 | * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
22 | * | ||
23 | * By copying, modifying or distributing this software, you acknowledge | ||
24 | * that you have read and understood your obligations described above, | ||
25 | * and agree to abide by those obligations. | ||
26 | * | ||
27 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
28 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
29 | * COMPLETENESS OR PERFORMANCE. | ||
30 | * $/LicenseInfo$ | ||
31 | */ | ||
32 | |||
33 | #include "linden_common.h" | ||
34 | #include "lldir.h" | ||
35 | |||
36 | #include "audioengine_openal.h" | ||
37 | #include "listener_openal.h" | ||
38 | |||
39 | |||
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) | ||
49 | { | ||
50 | } | ||
51 | |||
52 | // virtual | ||
53 | LLAudioEngine_OpenAL::~LLAudioEngine_OpenAL() | ||
54 | { | ||
55 | } | ||
56 | |||
57 | // virtual | ||
58 | bool LLAudioEngine_OpenAL::init(const S32 num_channels, void* userdata) | ||
59 | { | ||
60 | mWindGen = NULL; | ||
61 | LLAudioEngine::init(num_channels, userdata); | ||
62 | |||
63 | if(!alutInit(NULL, NULL)) | ||
64 | { | ||
65 | llwarns << "LLAudioEngine_OpenAL::init() ALUT initialization failed: " << alutGetErrorString (alutGetError ()) << llendl; | ||
66 | return false; | ||
67 | } | ||
68 | |||
69 | llinfos << "LLAudioEngine_OpenAL::init() OpenAL successfully initialized" << llendl; | ||
70 | |||
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; | ||
81 | |||
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; | ||
94 | } | ||
95 | |||
96 | // virtual | ||
97 | std::string LLAudioEngine_OpenAL::getDriverName(bool verbose) | ||
98 | { | ||
99 | ALCdevice *device = alcGetContextsDevice(alcGetCurrentContext()); | ||
100 | std::ostringstream version; | ||
101 | |||
102 | version << | ||
103 | "OpenAL"; | ||
104 | |||
105 | if (verbose) | ||
106 | { | ||
107 | version << | ||
108 | ", version " << | ||
109 | ll_safe_string(alGetString(AL_VERSION)) << | ||
110 | " / " << | ||
111 | ll_safe_string(alGetString(AL_VENDOR)) << | ||
112 | " / " << | ||
113 | ll_safe_string(alGetString(AL_RENDERER)); | ||
114 | |||
115 | if (device) | ||
116 | version << | ||
117 | ": " << | ||
118 | ll_safe_string(alcGetString(device, | ||
119 | ALC_DEFAULT_DEVICE_SPECIFIER)); | ||
120 | } | ||
121 | |||
122 | return version.str(); | ||
123 | } | ||
124 | |||
125 | // virtual | ||
126 | void LLAudioEngine_OpenAL::allocateListener() | ||
127 | { | ||
128 | mListenerp = (LLListener *) new LLListener_OpenAL(); | ||
129 | if(!mListenerp) | ||
130 | { | ||
131 | llwarns << "LLAudioEngine_OpenAL::allocateListener() Listener creation failed" << llendl; | ||
132 | } | ||
133 | } | ||
134 | |||
135 | // virtual | ||
136 | void LLAudioEngine_OpenAL::shutdown() | ||
137 | { | ||
138 | llinfos << "About to LLAudioEngine::shutdown()" << llendl; | ||
139 | LLAudioEngine::shutdown(); | ||
140 | |||
141 | llinfos << "About to alutExit()" << llendl; | ||
142 | if(!alutExit()) | ||
143 | { | ||
144 | llwarns << "Nuts." << llendl; | ||
145 | llwarns << "LLAudioEngine_OpenAL::shutdown() ALUT shutdown failed: " << alutGetErrorString (alutGetError ()) << llendl; | ||
146 | } | ||
147 | |||
148 | llinfos << "LLAudioEngine_OpenAL::shutdown() OpenAL successfully shut down" << llendl; | ||
149 | |||
150 | delete mListenerp; | ||
151 | mListenerp = NULL; | ||
152 | } | ||
153 | |||
154 | LLAudioBuffer *LLAudioEngine_OpenAL::createBuffer() | ||
155 | { | ||
156 | return new LLAudioBufferOpenAL(); | ||
157 | } | ||
158 | |||
159 | LLAudioChannel *LLAudioEngine_OpenAL::createChannel() | ||
160 | { | ||
161 | return new LLAudioChannelOpenAL(); | ||
162 | } | ||
163 | |||
164 | void LLAudioEngine_OpenAL::setInternalGain(F32 gain) | ||
165 | { | ||
166 | //llinfos << "LLAudioEngine_OpenAL::setInternalGain() Gain: " << gain << llendl; | ||
167 | alListenerf(AL_GAIN, gain); | ||
168 | } | ||
169 | |||
170 | LLAudioChannelOpenAL::LLAudioChannelOpenAL() | ||
171 | : | ||
172 | mALSource(AL_NONE), | ||
173 | mLastSamplePos(0) | ||
174 | { | ||
175 | alGenSources(1, &mALSource); | ||
176 | } | ||
177 | |||
178 | LLAudioChannelOpenAL::~LLAudioChannelOpenAL() | ||
179 | { | ||
180 | cleanup(); | ||
181 | alDeleteSources(1, &mALSource); | ||
182 | } | ||
183 | |||
184 | void LLAudioChannelOpenAL::cleanup() | ||
185 | { | ||
186 | alSourceStop(mALSource); | ||
187 | mCurrentBufferp = NULL; | ||
188 | } | ||
189 | |||
190 | void LLAudioChannelOpenAL::play() | ||
191 | { | ||
192 | if (mALSource == AL_NONE) | ||
193 | { | ||
194 | llwarns << "Playing without a mALSource, aborting" << llendl; | ||
195 | return; | ||
196 | } | ||
197 | |||
198 | if(!isPlaying()) | ||
199 | { | ||
200 | alSourcePlay(mALSource); | ||
201 | getSource()->setPlayedOnce(true); | ||
202 | } | ||
203 | } | ||
204 | |||
205 | void LLAudioChannelOpenAL::playSynced(LLAudioChannel *channelp) | ||
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 | } | ||
225 | play(); | ||
226 | } | ||
227 | |||
228 | bool LLAudioChannelOpenAL::isPlaying() | ||
229 | { | ||
230 | if (mALSource != AL_NONE) | ||
231 | { | ||
232 | ALint state; | ||
233 | alGetSourcei(mALSource, AL_SOURCE_STATE, &state); | ||
234 | if(state == AL_PLAYING) | ||
235 | { | ||
236 | return true; | ||
237 | } | ||
238 | } | ||
239 | |||
240 | return false; | ||
241 | } | ||
242 | |||
243 | bool LLAudioChannelOpenAL::updateBuffer() | ||
244 | { | ||
245 | if (LLAudioChannel::updateBuffer()) | ||
246 | { | ||
247 | // Base class update returned true, which means that we need to actually | ||
248 | // set up the source for a different buffer. | ||
249 | LLAudioBufferOpenAL *bufferp = (LLAudioBufferOpenAL *)mCurrentSourcep->getCurrentBuffer(); | ||
250 | ALuint buffer = bufferp->getBuffer(); | ||
251 | alSourcei(mALSource, AL_BUFFER, buffer); | ||
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()); | ||
265 | } | ||
266 | |||
267 | return true; | ||
268 | } | ||
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 | |||
292 | void LLAudioChannelOpenAL::update3DPosition() | ||
293 | { | ||
294 | if(!mCurrentSourcep) | ||
295 | { | ||
296 | return; | ||
297 | } | ||
298 | if (mCurrentSourcep->isAmbient()) | ||
299 | { | ||
300 | alSource3f(mALSource, AL_POSITION, 0.0, 0.0, 0.0); | ||
301 | alSource3f(mALSource, AL_VELOCITY, 0.0, 0.0, 0.0); | ||
302 | //alSource3f(mALSource, AL_DIRECTION, 0.0, 0.0, 0.0); | ||
303 | alSourcei (mALSource, AL_SOURCE_RELATIVE, AL_TRUE); | ||
304 | } else { | ||
305 | LLVector3 float_pos; | ||
306 | float_pos.setVec(mCurrentSourcep->getPositionGlobal()); | ||
307 | alSourcefv(mALSource, AL_POSITION, float_pos.mV); | ||
308 | alSourcefv(mALSource, AL_VELOCITY, mCurrentSourcep->getVelocity().mV); | ||
309 | //alSource3f(mALSource, AL_DIRECTION, 0.0, 0.0, 0.0); | ||
310 | alSourcei (mALSource, AL_SOURCE_RELATIVE, AL_FALSE); | ||
311 | } | ||
312 | |||
313 | alSourcef(mALSource, AL_GAIN, mCurrentSourcep->getGain() * getSecondaryGain()); | ||
314 | } | ||
315 | |||
316 | LLAudioBufferOpenAL::LLAudioBufferOpenAL() | ||
317 | { | ||
318 | mALBuffer = AL_NONE; | ||
319 | } | ||
320 | |||
321 | LLAudioBufferOpenAL::~LLAudioBufferOpenAL() | ||
322 | { | ||
323 | cleanup(); | ||
324 | } | ||
325 | |||
326 | void LLAudioBufferOpenAL::cleanup() | ||
327 | { | ||
328 | if(mALBuffer != AL_NONE) | ||
329 | { | ||
330 | alDeleteBuffers(1, &mALBuffer); | ||
331 | mALBuffer = AL_NONE; | ||
332 | } | ||
333 | } | ||
334 | |||
335 | bool LLAudioBufferOpenAL::loadWAV(const std::string& filename) | ||
336 | { | ||
337 | cleanup(); | ||
338 | mALBuffer = alutCreateBufferFromFile(filename.c_str()); | ||
339 | if(mALBuffer == AL_NONE) | ||
340 | { | ||
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; | ||
358 | } | ||
359 | |||
360 | return true; | ||
361 | } | ||
362 | |||
363 | U32 LLAudioBufferOpenAL::getLength() | ||
364 | { | ||
365 | if(mALBuffer == AL_NONE) | ||
366 | { | ||
367 | return 0; | ||
368 | } | ||
369 | ALint length; | ||
370 | alGetBufferi(mALBuffer, AL_SIZE, &length); | ||
371 | return length >> 2; | ||
372 | } | ||
373 | |||
374 | // ------------ | ||
375 | |||
376 | void LLAudioEngine_OpenAL::initWind() | ||
377 | { | ||
378 | ALenum error; | ||
379 | llinfos << "LLAudioEngine_OpenAL::initWind() start" << llendl; | ||
380 | |||
381 | mNumEmptyWindALBuffers = MAX_NUM_WIND_BUFFERS; | ||
382 | |||
383 | alGetError(); /* clear error */ | ||
384 | |||
385 | alGenSources(1,&mWindSource); | ||
386 | |||
387 | if((error=alGetError()) != AL_NO_ERROR) | ||
388 | { | ||
389 | llwarns << "LLAudioEngine_OpenAL::initWind() Error creating wind sources: "<<error<<llendl; | ||
390 | } | ||
391 | |||
392 | mWindGen = new LLWindGen<WIND_SAMPLE_T>; | ||
393 | |||
394 | mWindBufFreq = mWindGen->getInputSamplingRate(); | ||
395 | mWindBufSamples = llceil(mWindBufFreq * WIND_BUFFER_SIZE_SEC); | ||
396 | mWindBufBytes = mWindBufSamples * 2 /*stereo*/ * sizeof(WIND_SAMPLE_T); | ||
397 | |||
398 | mWindBuf = new WIND_SAMPLE_T [mWindBufSamples * 2 /*stereo*/]; | ||
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; | ||
407 | } | ||
408 | |||
409 | void LLAudioEngine_OpenAL::cleanupWind() | ||
410 | { | ||
411 | llinfos << "LLAudioEngine_OpenAL::cleanupWind()" << llendl; | ||
412 | |||
413 | if (mWindSource != AL_NONE) | ||
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 | } | ||
425 | |||
426 | // delete the wind source itself | ||
427 | alDeleteSources(1, &mWindSource); | ||
428 | |||
429 | mWindSource = AL_NONE; | ||
430 | } | ||
431 | |||
432 | delete[] mWindBuf; | ||
433 | mWindBuf = NULL; | ||
434 | |||
435 | delete mWindGen; | ||
436 | mWindGen = NULL; | ||
437 | } | ||
438 | |||
439 | void LLAudioEngine_OpenAL::updateWind(LLVector3 wind_vec, F32 camera_altitude) | ||
440 | { | ||
441 | LLVector3 wind_pos; | ||
442 | F64 pitch; | ||
443 | F64 center_freq; | ||
444 | ALenum error; | ||
445 | |||
446 | if (!mEnableWind) | ||
447 | return; | ||
448 | |||
449 | if(!mWindBuf) | ||
450 | return; | ||
451 | |||
452 | if (mWindUpdateTimer.checkExpirationAndReset(LL_WIND_UPDATE_INTERVAL)) | ||
453 | { | ||
454 | |||
455 | // wind comes in as Linden coordinate (+X = forward, +Y = left, +Z = up) | ||
456 | // need to convert this to the conventional orientation DS3D and OpenAL use | ||
457 | // where +X = right, +Y = up, +Z = backwards | ||
458 | |||
459 | wind_vec.setVec(-wind_vec.mV[1], wind_vec.mV[2], -wind_vec.mV[0]); | ||
460 | |||
461 | pitch = 1.0 + mapWindVecToPitch(wind_vec); | ||
462 | center_freq = 80.0 * pow(pitch,2.5*(mapWindVecToGain(wind_vec)+1.0)); | ||
463 | |||
464 | mWindGen->mTargetFreq = (F32)center_freq; | ||
465 | mWindGen->mTargetGain = (F32)mapWindVecToGain(wind_vec) * mMaxWindGain; | ||
466 | mWindGen->mTargetPanGainR = (F32)mapWindVecToPan(wind_vec); | ||
467 | |||
468 | alSourcei(mWindSource, AL_LOOPING, AL_FALSE); | ||
469 | alSource3f(mWindSource, AL_POSITION, 0.0, 0.0, 0.0); | ||
470 | alSource3f(mWindSource, AL_VELOCITY, 0.0, 0.0, 0.0); | ||
471 | alSourcef(mWindSource, AL_ROLLOFF_FACTOR, 0.0); | ||
472 | alSourcei(mWindSource, AL_SOURCE_RELATIVE, AL_TRUE); | ||
473 | } | ||
474 | |||
475 | // ok lets make a wind buffer now | ||
476 | |||
477 | int processed, queued, unprocessed; | ||
478 | alGetSourcei(mWindSource, AL_BUFFERS_PROCESSED, &processed); | ||
479 | alGetSourcei(mWindSource, AL_BUFFERS_QUEUED, &queued); | ||
480 | unprocessed = queued - processed; | ||
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); | ||
486 | |||
487 | //llinfos << "mNumEmptyWindALBuffers: " << mNumEmptyWindALBuffers <<" (" << unprocessed << ":" << processed << ")" << llendl; | ||
488 | |||
489 | while(processed--) // unqueue old buffers | ||
490 | { | ||
491 | ALuint buffer; | ||
492 | int error; | ||
493 | alGetError(); /* clear error */ | ||
494 | alSourceUnqueueBuffers(mWindSource, 1, &buffer); | ||
495 | error = alGetError(); | ||
496 | if(error != AL_NO_ERROR) | ||
497 | { | ||
498 | llwarns << "LLAudioEngine_OpenAL::updateWind() error swapping (unqueuing) buffers" << llendl; | ||
499 | } | ||
500 | else | ||
501 | { | ||
502 | alDeleteBuffers(1, &buffer); | ||
503 | } | ||
504 | } | ||
505 | |||
506 | unprocessed += mNumEmptyWindALBuffers; | ||
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 | } | ||
517 | |||
518 | alBufferData(buffer, | ||
519 | AL_FORMAT_STEREO16, | ||
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; | ||
532 | |||
533 | --mNumEmptyWindALBuffers; | ||
534 | } | ||
535 | |||
536 | int playing; | ||
537 | alGetSourcei(mWindSource, AL_SOURCE_STATE, &playing); | ||
538 | if(playing != AL_PLAYING) | ||
539 | { | ||
540 | alSourcePlay(mWindSource); | ||
541 | |||
542 | llinfos << "Wind had stopped - probably ran out of buffers - restarting: " << (unprocessed+mNumEmptyWindALBuffers) << " now queued." << llendl; | ||
543 | } | ||
544 | } | ||
diff --git a/linden/indra/llaudio/audioengine_openal.h b/linden/indra/llaudio/audioengine_openal.h new file mode 100644 index 0000000..b03153a --- /dev/null +++ b/linden/indra/llaudio/audioengine_openal.h | |||
@@ -0,0 +1,113 @@ | |||
1 | /** | ||
2 | * @file audioengine_openal.cpp | ||
3 | * @brief implementation of audio engine using OpenAL | ||
4 | * support as a OpenAL 3D implementation | ||
5 | * | ||
6 | * | ||
7 | * $LicenseInfo:firstyear=2002&license=viewergpl$ | ||
8 | * | ||
9 | * Copyright (c) 2002-2008, Linden Research, Inc. | ||
10 | * | ||
11 | * Second Life Viewer Source Code | ||
12 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
13 | * to you under the terms of the GNU General Public License, version 2.0 | ||
14 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
15 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
16 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
17 | * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 | ||
18 | * | ||
19 | * There are special exceptions to the terms and conditions of the GPL as | ||
20 | * it is applied to this Source Code. View the full text of the exception | ||
21 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
22 | * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception | ||
23 | * | ||
24 | * By copying, modifying or distributing this software, you acknowledge | ||
25 | * that you have read and understood your obligations described above, | ||
26 | * and agree to abide by those obligations. | ||
27 | * | ||
28 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
29 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
30 | * COMPLETENESS OR PERFORMANCE. | ||
31 | * $/LicenseInfo$ | ||
32 | */ | ||
33 | |||
34 | |||
35 | #ifndef LL_AUDIOENGINE_OPENAL_H | ||
36 | #define LL_AUDIOENGINE_OPENAL_H | ||
37 | |||
38 | #include "audioengine.h" | ||
39 | #include "listener_openal.h" | ||
40 | #include "windgen.h" | ||
41 | |||
42 | class LLAudioEngine_OpenAL : public LLAudioEngine | ||
43 | { | ||
44 | public: | ||
45 | LLAudioEngine_OpenAL(); | ||
46 | virtual ~LLAudioEngine_OpenAL(); | ||
47 | |||
48 | virtual bool init(const S32 num_channels, void *user_data); | ||
49 | virtual std::string getDriverName(bool verbose); | ||
50 | virtual void allocateListener(); | ||
51 | |||
52 | virtual void shutdown(); | ||
53 | |||
54 | void setInternalGain(F32 gain); | ||
55 | |||
56 | LLAudioBuffer* createBuffer(); | ||
57 | LLAudioChannel* createChannel(); | ||
58 | |||
59 | /*virtual*/ void initWind(); | ||
60 | /*virtual*/ void cleanupWind(); | ||
61 | /*virtual*/ void updateWind(LLVector3 direction, F32 camera_altitude); | ||
62 | |||
63 | private: | ||
64 | void * windDSP(void *newbuffer, int length); | ||
65 | typedef S16 WIND_SAMPLE_T; | ||
66 | LLWindGen<WIND_SAMPLE_T> *mWindGen; | ||
67 | S16 *mWindBuf; | ||
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 | ||
76 | }; | ||
77 | |||
78 | class LLAudioChannelOpenAL : public LLAudioChannel | ||
79 | { | ||
80 | public: | ||
81 | LLAudioChannelOpenAL(); | ||
82 | virtual ~LLAudioChannelOpenAL(); | ||
83 | protected: | ||
84 | /*virtual*/ void play(); | ||
85 | /*virtual*/ void playSynced(LLAudioChannel *channelp); | ||
86 | /*virtual*/ void cleanup(); | ||
87 | /*virtual*/ bool isPlaying(); | ||
88 | |||
89 | /*virtual*/ bool updateBuffer(); | ||
90 | /*virtual*/ void update3DPosition(); | ||
91 | /*virtual*/ void updateLoop(); | ||
92 | |||
93 | ALuint mALSource; | ||
94 | ALint mLastSamplePos; | ||
95 | }; | ||
96 | |||
97 | class LLAudioBufferOpenAL : public LLAudioBuffer{ | ||
98 | public: | ||
99 | LLAudioBufferOpenAL(); | ||
100 | virtual ~LLAudioBufferOpenAL(); | ||
101 | |||
102 | bool loadWAV(const std::string& filename); | ||
103 | U32 getLength(); | ||
104 | |||
105 | friend class LLAudioChannelOpenAL; | ||
106 | protected: | ||
107 | void cleanup(); | ||
108 | ALuint getBuffer() {return mALBuffer;} | ||
109 | |||
110 | ALuint mALBuffer; | ||
111 | }; | ||
112 | |||
113 | #endif | ||
diff --git a/linden/indra/llaudio/listener_fmod.h b/linden/indra/llaudio/listener_fmod.h index 7b7c4c6..95b31ac 100644 --- a/linden/indra/llaudio/listener_fmod.h +++ b/linden/indra/llaudio/listener_fmod.h | |||
@@ -37,11 +37,6 @@ | |||
37 | 37 | ||
38 | class LLListener_FMOD : public LLListener | 38 | class LLListener_FMOD : public LLListener |
39 | { | 39 | { |
40 | protected: | ||
41 | F32 mDopplerFactor; | ||
42 | F32 mDistanceFactor; | ||
43 | F32 mRolloffFactor; | ||
44 | |||
45 | public: | 40 | public: |
46 | LLListener_FMOD(); | 41 | LLListener_FMOD(); |
47 | virtual ~LLListener_FMOD(); | 42 | virtual ~LLListener_FMOD(); |
@@ -59,6 +54,11 @@ class LLListener_FMOD : public LLListener | |||
59 | virtual F32 getDistanceFactor(); | 54 | virtual F32 getDistanceFactor(); |
60 | virtual void setRolloffFactor(F32 factor); | 55 | virtual void setRolloffFactor(F32 factor); |
61 | virtual F32 getRolloffFactor(); | 56 | virtual F32 getRolloffFactor(); |
57 | |||
58 | protected: | ||
59 | F32 mDopplerFactor; | ||
60 | F32 mDistanceFactor; | ||
61 | F32 mRolloffFactor; | ||
62 | }; | 62 | }; |
63 | 63 | ||
64 | #endif | 64 | #endif |
diff --git a/linden/indra/llaudio/listener_openal.cpp b/linden/indra/llaudio/listener_openal.cpp new file mode 100644 index 0000000..637af30 --- /dev/null +++ b/linden/indra/llaudio/listener_openal.cpp | |||
@@ -0,0 +1,98 @@ | |||
1 | /** | ||
2 | * @file audioengine_openal.cpp | ||
3 | * @brief implementation of audio engine using OpenAL | ||
4 | * support as a OpenAL 3D implementation | ||
5 | * | ||
6 | * $LicenseInfo:firstyear=2002&license=viewergpl$ | ||
7 | * | ||
8 | * Copyright (c) 2002-2007, Linden Research, Inc. | ||
9 | * | ||
10 | * Second Life Viewer Source Code | ||
11 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
12 | * to you under the terms of the GNU General Public License, version 2.0 | ||
13 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
14 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
15 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
16 | * online at http://secondlife.com/developers/opensource/gplv2 | ||
17 | * | ||
18 | * There are special exceptions to the terms and conditions of the GPL as | ||
19 | * it is applied to this Source Code. View the full text of the exception | ||
20 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
21 | * online at http://secondlife.com/developers/opensource/flossexception | ||
22 | * | ||
23 | * By copying, modifying or distributing this software, you acknowledge | ||
24 | * that you have read and understood your obligations described above, | ||
25 | * and agree to abide by those obligations. | ||
26 | * | ||
27 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
28 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
29 | * COMPLETENESS OR PERFORMANCE. | ||
30 | * $/LicenseInfo$ | ||
31 | */ | ||
32 | |||
33 | #include "linden_common.h" | ||
34 | #include "audioengine.h" | ||
35 | |||
36 | #include "listener_openal.h" | ||
37 | |||
38 | LLListener_OpenAL::LLListener_OpenAL(){ | ||
39 | init(); | ||
40 | } | ||
41 | |||
42 | LLListener_OpenAL::~LLListener_OpenAL(){ | ||
43 | } | ||
44 | |||
45 | void LLListener_OpenAL::translate(LLVector3 offset){ | ||
46 | LLListener::translate(offset); | ||
47 | llinfos << "LLListener_OpenAL::translate() : " << offset << llendl; | ||
48 | } | ||
49 | |||
50 | void LLListener_OpenAL::setPosition(LLVector3 pos){ | ||
51 | LLListener::setPosition(pos); | ||
52 | //llinfos << "LLListener_OpenAL::setPosition() : " << pos << llendl; | ||
53 | } | ||
54 | |||
55 | void LLListener_OpenAL::setVelocity(LLVector3 vel){ | ||
56 | LLListener::setVelocity(vel); | ||
57 | } | ||
58 | |||
59 | void LLListener_OpenAL::orient(LLVector3 up, LLVector3 at){ | ||
60 | LLListener::orient(up, at); | ||
61 | //llinfos << "LLListener_OpenAL::orient() up: " << up << " at: " << at << llendl; | ||
62 | } | ||
63 | |||
64 | void LLListener_OpenAL::commitDeferredChanges(){ | ||
65 | ALfloat orientation[6]; | ||
66 | orientation[0] = mListenAt.mV[0]; | ||
67 | orientation[1] = mListenAt.mV[1]; | ||
68 | orientation[2] = mListenAt.mV[2]; | ||
69 | orientation[3] = mListenUp.mV[0]; | ||
70 | orientation[4] = mListenUp.mV[1]; | ||
71 | orientation[5] = mListenUp.mV[2]; | ||
72 | |||
73 | ALfloat velocity[3]; | ||
74 | velocity[0] = mVelocity.mV[0]; | ||
75 | velocity[1] = mVelocity.mV[1]; | ||
76 | velocity[2] = mVelocity.mV[2]; | ||
77 | |||
78 | alListenerfv(AL_ORIENTATION, orientation); | ||
79 | alListenerfv(AL_POSITION, mPosition.mV); | ||
80 | alListenerfv(AL_VELOCITY, velocity); | ||
81 | } | ||
82 | |||
83 | void LLListener_OpenAL::setDopplerFactor(F32 factor){ | ||
84 | // Effect is way too strong by default, scale it down here. | ||
85 | // Scaling the speed of sound up causes crashes. | ||
86 | factor *= 0.005f; | ||
87 | //llinfos << "LLListener_OpenAL::setDopplerFactor() : " << factor << llendl; | ||
88 | alDopplerFactor(factor); | ||
89 | } | ||
90 | |||
91 | F32 LLListener_OpenAL::getDopplerFactor(){ | ||
92 | ALfloat factor; | ||
93 | factor = 0.0f; | ||
94 | alDopplerFactor(factor); | ||
95 | llinfos << "LLListener_OpenAL::getDopplerFactor() : " << factor << llendl; | ||
96 | return factor; | ||
97 | } | ||
98 | |||
diff --git a/linden/indra/llaudio/listener_openal.h b/linden/indra/llaudio/listener_openal.h index cc4bb9e..7551161 100644 --- a/linden/indra/llaudio/listener_openal.h +++ b/linden/indra/llaudio/listener_openal.h | |||
@@ -35,7 +35,8 @@ | |||
35 | 35 | ||
36 | #include "listener.h" | 36 | #include "listener.h" |
37 | 37 | ||
38 | #include "AL/al.h" | 38 | |
39 | //#include "AL/al.h" | ||
39 | #include "AL/alut.h" | 40 | #include "AL/alut.h" |
40 | 41 | ||
41 | class LLListener_OpenAL : public LLListener | 42 | class LLListener_OpenAL : public LLListener |
@@ -54,6 +55,10 @@ class LLListener_OpenAL : public LLListener | |||
54 | virtual void setPosition(LLVector3 pos); | 55 | virtual void setPosition(LLVector3 pos); |
55 | virtual void setVelocity(LLVector3 vel); | 56 | virtual void setVelocity(LLVector3 vel); |
56 | virtual void orient(LLVector3 up, LLVector3 at); | 57 | virtual void orient(LLVector3 up, LLVector3 at); |
58 | virtual void commitDeferredChanges(); | ||
59 | |||
60 | virtual void setDopplerFactor(F32 factor); | ||
61 | virtual F32 getDopplerFactor(); | ||
57 | }; | 62 | }; |
58 | 63 | ||
59 | #endif | 64 | #endif |
diff --git a/linden/indra/llaudio/llaudiodecodemgr.cpp b/linden/indra/llaudio/llaudiodecodemgr.cpp index 7cd48a9..cfd0500 100644 --- a/linden/indra/llaudio/llaudiodecodemgr.cpp +++ b/linden/indra/llaudio/llaudiodecodemgr.cpp | |||
@@ -374,16 +374,16 @@ BOOL LLVorbisDecodeState::finishDecode() | |||
374 | 374 | ||
375 | // write "data" chunk length, in little-endian format | 375 | // write "data" chunk length, in little-endian format |
376 | S32 data_length = mWAVBuffer.size() - WAV_HEADER_SIZE; | 376 | S32 data_length = mWAVBuffer.size() - WAV_HEADER_SIZE; |
377 | mWAVBuffer[40] = (data_length) & 0x000000FF; | 377 | mWAVBuffer[40] = (data_length - 8) & 0x000000FF; |
378 | mWAVBuffer[41] = (data_length >> 8) & 0x000000FF; | 378 | mWAVBuffer[41] = ((data_length - 8)>> 8) & 0x000000FF; |
379 | mWAVBuffer[42] = (data_length >> 16) & 0x000000FF; | 379 | mWAVBuffer[42] = ((data_length - 8)>> 16) & 0x000000FF; |
380 | mWAVBuffer[43] = (data_length >> 24) & 0x000000FF; | 380 | mWAVBuffer[43] = ((data_length - 8)>> 24) & 0x000000FF; |
381 | |||
381 | // write overall "RIFF" length, in little-endian format | 382 | // write overall "RIFF" length, in little-endian format |
382 | data_length += 36; | 383 | mWAVBuffer[4] = (data_length + 28) & 0x000000FF; |
383 | mWAVBuffer[4] = (data_length) & 0x000000FF; | 384 | mWAVBuffer[5] = ((data_length + 28) >> 8) & 0x000000FF; |
384 | mWAVBuffer[5] = (data_length >> 8) & 0x000000FF; | 385 | mWAVBuffer[6] = ((data_length + 28) >> 16) & 0x000000FF; |
385 | mWAVBuffer[6] = (data_length >> 16) & 0x000000FF; | 386 | mWAVBuffer[7] = ((data_length + 28) >> 24) & 0x000000FF; |
386 | mWAVBuffer[7] = (data_length >> 24) & 0x000000FF; | ||
387 | 387 | ||
388 | // | 388 | // |
389 | // FUDGECAKES!!! Vorbis encode/decode messes up loop point transitions (pop) | 389 | // FUDGECAKES!!! Vorbis encode/decode messes up loop point transitions (pop) |
@@ -395,7 +395,8 @@ BOOL LLVorbisDecodeState::finishDecode() | |||
395 | S32 fade_length; | 395 | S32 fade_length; |
396 | char pcmout[4096]; /*Flawfinder: ignore*/ | 396 | char pcmout[4096]; /*Flawfinder: ignore*/ |
397 | 397 | ||
398 | fade_length = llmin((S32)128,(S32)(data_length-36)/8); | 398 | fade_length = llmin((S32)128,(S32)(data_length)/8); |
399 | |||
399 | if((S32)mWAVBuffer.size() >= (WAV_HEADER_SIZE + 2* fade_length)) | 400 | if((S32)mWAVBuffer.size() >= (WAV_HEADER_SIZE + 2* fade_length)) |
400 | { | 401 | { |
401 | memcpy(pcmout, &mWAVBuffer[WAV_HEADER_SIZE], (2 * fade_length)); /*Flawfinder: ignore*/ | 402 | memcpy(pcmout, &mWAVBuffer[WAV_HEADER_SIZE], (2 * fade_length)); /*Flawfinder: ignore*/ |
@@ -435,7 +436,7 @@ BOOL LLVorbisDecodeState::finishDecode() | |||
435 | } | 436 | } |
436 | } | 437 | } |
437 | 438 | ||
438 | if (36 == data_length) | 439 | if (0 == data_length) |
439 | { | 440 | { |
440 | llwarns << "BAD Vorbis decode in finishDecode!" << llendl; | 441 | llwarns << "BAD Vorbis decode in finishDecode!" << llendl; |
441 | mValid = FALSE; | 442 | mValid = FALSE; |
diff --git a/linden/indra/llaudio/windgen.h b/linden/indra/llaudio/windgen.h new file mode 100644 index 0000000..39ce568 --- /dev/null +++ b/linden/indra/llaudio/windgen.h | |||
@@ -0,0 +1,138 @@ | |||
1 | /** | ||
2 | * @file windgen.h | ||
3 | * @brief Templated wind noise generation | ||
4 | * | ||
5 | * $LicenseInfo:firstyear=2002&license=viewergpl$ | ||
6 | * | ||
7 | * Copyright (c) 2002-2008, Linden Research, Inc. | ||
8 | * | ||
9 | * Second Life Viewer Source Code | ||
10 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
11 | * to you under the terms of the GNU General Public License, version 2.0 | ||
12 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
13 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
14 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
15 | * online at http://secondlife.com/developers/opensource/gplv2 | ||
16 | * | ||
17 | * There are special exceptions to the terms and conditions of the GPL as | ||
18 | * it is applied to this Source Code. View the full text of the exception | ||
19 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
20 | * online at http://secondlife.com/developers/opensource/flossexception | ||
21 | * | ||
22 | * By copying, modifying or distributing this software, you acknowledge | ||
23 | * that you have read and understood your obligations described above, | ||
24 | * and agree to abide by those obligations. | ||
25 | * | ||
26 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
27 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
28 | * COMPLETENESS OR PERFORMANCE. | ||
29 | * $/LicenseInfo$ | ||
30 | */ | ||
31 | #ifndef WINDGEN_H | ||
32 | #define WINDGEN_H | ||
33 | |||
34 | #include "llcommon.h" | ||
35 | #include "llrand.h" | ||
36 | |||
37 | template <class MIXBUFFERFORMAT_T> | ||
38 | class LLWindGen | ||
39 | { | ||
40 | public: | ||
41 | LLWindGen() : | ||
42 | mTargetGain(0.f), | ||
43 | mTargetFreq(100.f), | ||
44 | mTargetPanGainR(0.5f), | ||
45 | mbuf0(0.0), | ||
46 | mbuf1(0.0), | ||
47 | mbuf2(0.0), | ||
48 | mbuf3(0.0), | ||
49 | mbuf4(0.0), | ||
50 | mbuf5(0.0), | ||
51 | mY0(0.0), | ||
52 | mY1(0.0), | ||
53 | mCurrentGain(0.f), | ||
54 | mCurrentFreq(100.f), | ||
55 | mCurrentPanGainR(0.5f) {}; | ||
56 | |||
57 | static const U32 getInputSamplingRate() {return mInputSamplingRate;} | ||
58 | |||
59 | // newbuffer = the buffer passed from the previous DSP unit. | ||
60 | // numsamples = length in samples-per-channel at this mix time. | ||
61 | // stride = number of bytes between start of each sample. | ||
62 | // NOTE: generates L/R interleaved stereo | ||
63 | MIXBUFFERFORMAT_T* windGenerate(MIXBUFFERFORMAT_T *newbuffer, int numsamples, int stride) | ||
64 | { | ||
65 | U8 *cursamplep = (U8*)newbuffer; | ||
66 | |||
67 | double bandwidth = 50.0F; | ||
68 | double a0,b1,b2; | ||
69 | |||
70 | // calculate resonant filter coeffs | ||
71 | b2 = exp(-(F_TWO_PI) * (bandwidth / mInputSamplingRate)); | ||
72 | |||
73 | while (numsamples--) | ||
74 | { | ||
75 | mCurrentFreq = (float)((0.999 * mCurrentFreq) + (0.001 * mTargetFreq)); | ||
76 | mCurrentGain = (float)((0.999 * mCurrentGain) + (0.001 * mTargetGain)); | ||
77 | mCurrentPanGainR = (float)((0.999 * mCurrentPanGainR) + (0.001 * mTargetPanGainR)); | ||
78 | b1 = (-4.0 * b2) / (1.0 + b2) * cos(F_TWO_PI * (mCurrentFreq / mInputSamplingRate)); | ||
79 | a0 = (1.0 - b2) * sqrt(1.0 - (b1 * b1) / (4.0 * b2)); | ||
80 | double nextSample; | ||
81 | |||
82 | // start with white noise | ||
83 | nextSample = ll_frand(2.0f) - 1.0f; | ||
84 | |||
85 | #if 1 // LLAE_WIND_PINK apply pinking filter | ||
86 | mbuf0 = 0.997f * mbuf0 + 0.0126502f * nextSample; | ||
87 | mbuf1 = 0.985f * mbuf1 + 0.0139083f * nextSample; | ||
88 | mbuf2 = 0.950f * mbuf2 + 0.0205439f * nextSample; | ||
89 | mbuf3 = 0.850f * mbuf3 + 0.0387225f * nextSample; | ||
90 | mbuf4 = 0.620f * mbuf4 + 0.0465932f * nextSample; | ||
91 | mbuf5 = 0.250f * mbuf5 + 0.1093477f * nextSample; | ||
92 | |||
93 | nextSample = mbuf0 + mbuf1 + mbuf2 + mbuf3 + mbuf4 + mbuf5; | ||
94 | #endif | ||
95 | |||
96 | #if 1 //LLAE_WIND_RESONANT // do a resonant filter on the noise | ||
97 | nextSample = (double)( a0 * nextSample - b1 * mY0 - b2 * mY1 ); | ||
98 | |||
99 | mY1 = mY0; | ||
100 | mY0 = nextSample; | ||
101 | #endif | ||
102 | |||
103 | nextSample *= mCurrentGain; | ||
104 | |||
105 | MIXBUFFERFORMAT_T sample; | ||
106 | |||
107 | sample = llfloor(((F32)nextSample*32768.f*(1.0f - mCurrentPanGainR))+0.5f); | ||
108 | *(MIXBUFFERFORMAT_T*)cursamplep = llclamp(sample, (MIXBUFFERFORMAT_T)-32768, (MIXBUFFERFORMAT_T)32767); | ||
109 | cursamplep += stride; | ||
110 | |||
111 | sample = llfloor(((F32)nextSample*32768.f*mCurrentPanGainR)+0.5f); | ||
112 | *(MIXBUFFERFORMAT_T*)cursamplep = llclamp(sample, (MIXBUFFERFORMAT_T)-32768, (MIXBUFFERFORMAT_T)32767); | ||
113 | cursamplep += stride; | ||
114 | } | ||
115 | |||
116 | return newbuffer; | ||
117 | } | ||
118 | |||
119 | F32 mTargetGain; | ||
120 | F32 mTargetFreq; | ||
121 | F32 mTargetPanGainR; | ||
122 | |||
123 | private: | ||
124 | static const U32 mInputSamplingRate = 44100; | ||
125 | F64 mbuf0; | ||
126 | F64 mbuf1; | ||
127 | F64 mbuf2; | ||
128 | F64 mbuf3; | ||
129 | F64 mbuf4; | ||
130 | F64 mbuf5; | ||
131 | F64 mY0; | ||
132 | F64 mY1; | ||
133 | F32 mCurrentGain; | ||
134 | F32 mCurrentFreq; | ||
135 | F32 mCurrentPanGainR; | ||
136 | }; | ||
137 | |||
138 | #endif | ||