aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llaudio
diff options
context:
space:
mode:
Diffstat (limited to 'linden/indra/llaudio')
-rw-r--r--linden/indra/llaudio/CMakeLists.txt19
-rw-r--r--linden/indra/llaudio/audioengine.cpp361
-rw-r--r--linden/indra/llaudio/audioengine.h161
-rw-r--r--linden/indra/llaudio/audioengine_fmod.cpp271
-rw-r--r--linden/indra/llaudio/audioengine_fmod.h31
-rw-r--r--linden/indra/llaudio/audioengine_openal.cpp544
-rw-r--r--linden/indra/llaudio/audioengine_openal.h113
-rw-r--r--linden/indra/llaudio/listener_fmod.h10
-rw-r--r--linden/indra/llaudio/listener_openal.cpp98
-rw-r--r--linden/indra/llaudio/listener_openal.h7
-rw-r--r--linden/indra/llaudio/llaudiodecodemgr.cpp23
-rw-r--r--linden/indra/llaudio/windgen.h138
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)
9include(LLMath) 9include(LLMath)
10include(LLMessage) 10include(LLMessage)
11include(LLVFS) 11include(LLVFS)
12include(LLMedia)
12 13
13include_directories( 14include_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
25set(llaudio_SOURCE_FILES 30set(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
43if (FMOD) 49if (FMOD)
@@ -59,6 +65,19 @@ if (FMOD)
59 endif (LINUX) 65 endif (LINUX)
60endif (FMOD) 66endif (FMOD)
61 67
68if (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
79endif (OPENAL)
80
62set_source_files_properties(${llaudio_HEADER_FILES} 81set_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)
48extern void request_sound(const LLUUID &sound_guid); 50extern void request_sound(const LLUUID &sound_guid);
49 51
50LLAudioEngine* gAudiop = NULL; 52LLAudioEngine* gAudiop = NULL;
51 53
52// Maximum amount of time we wait for a transfer to complete before starting
53// off another one.
54const 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
102BOOL LLAudioEngine::init(const S32 num_channels, void* userdata) 107bool 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
172void 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
206void 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
222void 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
245void LLAudioEngine::updateInternetStream()
246{
247 if (mInternetStreamMedia)
248 mInternetStreamMedia->updateMedia();
249}
250
251// virtual
252int 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
271void LLAudioEngine::getInternetStreamInfo(char* artist, char* title)
272{
273 artist[0] = 0;
274 title[0] = 0;
275}
276
277// virtual
278void 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
291const 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
442BOOL LLAudioEngine::updateBufferForData(LLAudioData *adp, const LLUUID &audio_uuid) 585
586
587bool 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
476void LLAudioEngine::enableWind(BOOL enable) 621void 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
604BOOL LLAudioEngine::preloadSound(const LLUUID &uuid) 749bool 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
622BOOL LLAudioEngine::isWindEnabled() 767bool LLAudioEngine::isWindEnabled()
623{ 768{
624 return mEnableWind; 769 return mEnableWind;
625} 770}
626 771
627 772
628void LLAudioEngine::setMuted(BOOL muted) 773void 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
791void LLAudioEngine::setSecondaryGain(S32 type, F32 gain)
792{
793 llassert(type < LLAudioEngine::AUDIO_TYPE_COUNT);
794
795 mSecondaryGain[type] = gain;
796}
797
798F32 LLAudioEngine::getSecondaryGain(S32 type)
799{
800 return mSecondaryGain[type];
801}
802
646F32 LLAudioEngine::getInternetStreamGain() 803F32 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
721void LLAudioEngine::triggerSound(const LLUUID &audio_uuid, const LLUUID& owner_id, const F32 gain, const LLVector3d &pos_global) 878void 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
917BOOL LLAudioEngine::hasDecodedFile(const LLUUID &uuid) 1075bool 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
937BOOL LLAudioEngine::hasLocalFile(const LLUUID &uuid) 1095bool 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
1183LLAudioSource::LLAudioSource(const LLUUID& id, const LLUUID& owner_id, const F32 gain) 1341LLAudioSource::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
1257BOOL LLAudioSource::setupChannel() 1416bool 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
1291BOOL LLAudioSource::play(const LLUUID &audio_uuid) 1450bool 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
1336BOOL LLAudioSource::isDone() 1495bool 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
1400void LLAudioSource::addAudioData(LLAudioData *adp, const BOOL set_current) 1560void 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
1468BOOL LLAudioSource::hasPendingPreloads() const 1628bool 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()
1514LLAudioChannel::LLAudioChannel() : 1674LLAudioChannel::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
1561BOOL LLAudioChannel::updateBuffer() 1722bool 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()
1612LLAudioData::LLAudioData(const LLUUID &uuid) : 1773LLAudioData::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
1638BOOL LLAudioData::load() 1799bool 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
48class LLMediaBase;
49
48const F32 LL_WIND_UPDATE_INTERVAL = 0.1f; 50const F32 LL_WIND_UPDATE_INTERVAL = 0.1f;
49const F32 LL_ROLLOFF_MULTIPLIER_UNDER_WATER = 5.f; // How much sounds are weaker under water 51const F32 LL_ROLLOFF_MULTIPLIER_UNDER_WATER = 5.f; // How much sounds are weaker under water
50const F32 LL_WIND_UNDERWATER_CENTER_FREQ = 20.f; 52const F32 LL_WIND_UNDERWATER_CENTER_FREQ = 20.f;
@@ -67,6 +69,7 @@ class LLVFS;
67class LLAudioSource; 69class LLAudioSource;
68class LLAudioData; 70class LLAudioData;
69class LLAudioChannel; 71class LLAudioChannel;
72class LLAudioChannelOpenAL;
70class LLAudioBuffer; 73class LLAudioBuffer;
71 74
72 75
@@ -77,14 +80,24 @@ class LLAudioBuffer;
77 80
78class LLAudioEngine 81class LLAudioEngine
79{ 82{
83 friend class LLAudioChannelOpenAL; // bleh. channel needs some listener methods.
84
80public: 85public:
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
163public: 182public:
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:
195protected: 209protected:
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
233private: 249private:
234 void setDefaults(); 250 void setDefaults();
251 LLMediaBase *mInternetStreamMedia;
235}; 252};
236 253
237 254
@@ -247,7 +264,7 @@ class LLAudioSource
247public: 264public:
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{
341public: 362public:
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
358protected: 379protected:
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;
385protected: 409protected:
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.
396protected: 420protected:
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{
413public: 438public:
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;
421protected: 446protected:
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
48extern "C" {
49 void * F_CALLBACKAPI windCallback(void *originalbuffer, void *newbuffer, int length, void* userdata);
50}
49 51
50void * F_CALLBACKAPI windCallback(void *originalbuffer, void *newbuffer, int length, void* userdata);
51FSOUND_DSPUNIT *gWindDSP = NULL; 52FSOUND_DSPUNIT *gWindDSP = NULL;
52 53
53// These globals for the wind filter. Blech!
54F64 gbuf0 = 0.0;
55F64 gbuf1 = 0.0;
56F64 gbuf2 = 0.0;
57F64 gbuf3 = 0.0;
58F64 gbuf4 = 0.0;
59F64 gbuf5 = 0.0;
60F64 gY0 = 0.0;
61F64 gY1 = 0.0;
62
63F32 gTargetGain = 0.f;
64F32 gCurrentGain = 0.f;
65F32 gTargetFreq = 100.f;
66F32 gCurrentFreq = 100.f;
67F32 gTargetPanGainR = 0.5f;
68F32 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
95LLAudioEngine_FMOD::LLAudioEngine_FMOD() 79LLAudioEngine_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
108BOOL LLAudioEngine_FMOD::init(const S32 num_channels, void* userdata) 93bool 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
268void 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
319void LLAudioEngine_FMOD::initWind() 296void 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
460BOOL LLAudioChannelFMOD::updateBuffer() 442bool 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
621BOOL LLAudioChannelFMOD::isPlaying() 603bool 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
655BOOL LLAudioBufferFMOD::loadWAV(const std::string& filename) 637bool 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
739void LLAudioBufferFMOD::set3DMode(BOOL use3d) 721void 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
974void 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
981void LLAudioEngine_FMOD::setInternetStreamGain(F32 vol) 956void 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
993const std::string& LLAudioEngine_FMOD::getInternetStreamURL()
994{
995 return mInternetStreamURL;
996}
997
998
999LLAudioStreamFMOD::LLAudioStreamFMOD(const std::string& url) : 969LLAudioStreamFMOD::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
1017int LLAudioStreamFMOD::startStream() 987int 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
1032BOOL LLAudioStreamFMOD::stopStream() 1002bool 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 */ 1049void * 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
1086inline 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
1096void * 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
73protected: 76protected:
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);
132protected: 135protected:
133 FSOUND_SAMPLE *getSample() { return mSamplep; } 136 FSOUND_SAMPLE *getSample() { return mSamplep; }
134protected: 137protected:
@@ -140,15 +143,15 @@ class LLAudioStreamFMOD
140public: 143public:
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();
149protected: 152protected:
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
40LLAudioEngine_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
53LLAudioEngine_OpenAL::~LLAudioEngine_OpenAL()
54{
55}
56
57// virtual
58bool 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
97std::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
126void 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
136void 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
154LLAudioBuffer *LLAudioEngine_OpenAL::createBuffer()
155{
156 return new LLAudioBufferOpenAL();
157}
158
159LLAudioChannel *LLAudioEngine_OpenAL::createChannel()
160{
161 return new LLAudioChannelOpenAL();
162}
163
164void LLAudioEngine_OpenAL::setInternalGain(F32 gain)
165{
166 //llinfos << "LLAudioEngine_OpenAL::setInternalGain() Gain: " << gain << llendl;
167 alListenerf(AL_GAIN, gain);
168}
169
170LLAudioChannelOpenAL::LLAudioChannelOpenAL()
171 :
172 mALSource(AL_NONE),
173 mLastSamplePos(0)
174{
175 alGenSources(1, &mALSource);
176}
177
178LLAudioChannelOpenAL::~LLAudioChannelOpenAL()
179{
180 cleanup();
181 alDeleteSources(1, &mALSource);
182}
183
184void LLAudioChannelOpenAL::cleanup()
185{
186 alSourceStop(mALSource);
187 mCurrentBufferp = NULL;
188}
189
190void 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
205void 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
228bool 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
243bool 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
271void 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
292void 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
316LLAudioBufferOpenAL::LLAudioBufferOpenAL()
317{
318 mALBuffer = AL_NONE;
319}
320
321LLAudioBufferOpenAL::~LLAudioBufferOpenAL()
322{
323 cleanup();
324}
325
326void LLAudioBufferOpenAL::cleanup()
327{
328 if(mALBuffer != AL_NONE)
329 {
330 alDeleteBuffers(1, &mALBuffer);
331 mALBuffer = AL_NONE;
332 }
333}
334
335bool 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
363U32 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
376void 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
409void 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
439void 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
42class 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
78class 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
97class 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
38class LLListener_FMOD : public LLListener 38class 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
38LLListener_OpenAL::LLListener_OpenAL(){
39 init();
40}
41
42LLListener_OpenAL::~LLListener_OpenAL(){
43}
44
45void LLListener_OpenAL::translate(LLVector3 offset){
46 LLListener::translate(offset);
47 llinfos << "LLListener_OpenAL::translate() : " << offset << llendl;
48}
49
50void LLListener_OpenAL::setPosition(LLVector3 pos){
51 LLListener::setPosition(pos);
52 //llinfos << "LLListener_OpenAL::setPosition() : " << pos << llendl;
53}
54
55void LLListener_OpenAL::setVelocity(LLVector3 vel){
56 LLListener::setVelocity(vel);
57}
58
59void LLListener_OpenAL::orient(LLVector3 up, LLVector3 at){
60 LLListener::orient(up, at);
61 //llinfos << "LLListener_OpenAL::orient() up: " << up << " at: " << at << llendl;
62}
63
64void 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
83void 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
91F32 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
41class LLListener_OpenAL : public LLListener 42class 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
37template <class MIXBUFFERFORMAT_T>
38class LLWindGen
39{
40public:
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
123private:
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