aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llaudio
diff options
context:
space:
mode:
authorJacek Antonelli2009-02-12 02:06:41 -0600
committerJacek Antonelli2009-02-12 02:06:45 -0600
commit61f97b33f9850d21965d397b947a298c16ba576d (patch)
treea2edff0a7fbc83e2259eda952511b0fbdbea290b /linden/indra/llaudio
parentSecond Life viewer sources 1.22.7-RC (diff)
downloadmeta-impy-61f97b33f9850d21965d397b947a298c16ba576d.zip
meta-impy-61f97b33f9850d21965d397b947a298c16ba576d.tar.gz
meta-impy-61f97b33f9850d21965d397b947a298c16ba576d.tar.bz2
meta-impy-61f97b33f9850d21965d397b947a298c16ba576d.tar.xz
Second Life viewer sources 1.22.8-RC
Diffstat (limited to '')
-rw-r--r--linden/indra/llaudio/CMakeLists.txt18
-rw-r--r--linden/indra/llaudio/audioengine.cpp329
-rw-r--r--linden/indra/llaudio/audioengine.h134
-rw-r--r--linden/indra/llaudio/audioengine_fmod.cpp288
-rw-r--r--linden/indra/llaudio/audioengine_fmod.h32
-rw-r--r--linden/indra/llaudio/audioengine_openal.cpp547
-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.cpp125
-rw-r--r--linden/indra/llaudio/listener_openal.h18
-rw-r--r--linden/indra/llaudio/windgen.h135
11 files changed, 1380 insertions, 369 deletions
diff --git a/linden/indra/llaudio/CMakeLists.txt b/linden/indra/llaudio/CMakeLists.txt
index ebedcab..235248e 100644
--- a/linden/indra/llaudio/CMakeLists.txt
+++ b/linden/indra/llaudio/CMakeLists.txt
@@ -5,10 +5,12 @@ project(llaudio)
5include(00-Common) 5include(00-Common)
6include(Audio) 6include(Audio)
7include(FMOD) 7include(FMOD)
8include(OPENAL)
8include(LLCommon) 9include(LLCommon)
9include(LLMath) 10include(LLMath)
10include(LLMessage) 11include(LLMessage)
11include(LLVFS) 12include(LLVFS)
13include(LLMedia)
12 14
13include_directories( 15include_directories(
14 ${FMOD_INCLUDE_DIR} 16 ${FMOD_INCLUDE_DIR}
@@ -20,6 +22,9 @@ include_directories(
20 ${VORBISENC_INCLUDE_DIRS} 22 ${VORBISENC_INCLUDE_DIRS}
21 ${VORBISFILE_INCLUDE_DIRS} 23 ${VORBISFILE_INCLUDE_DIRS}
22 ${VORBIS_INCLUDE_DIRS} 24 ${VORBIS_INCLUDE_DIRS}
25 ${OPENAL_LIB_INCLUDE_DIRS}
26 ${FREEAULT_LIB_INCLUDE_DIRS}
27 ${LLMEDIA_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,18 @@ 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 )
78endif (OPENAL)
79
62set_source_files_properties(${llaudio_HEADER_FILES} 80set_source_files_properties(${llaudio_HEADER_FILES}
63 PROPERTIES HEADER_FILE_ONLY TRUE) 81 PROPERTIES HEADER_FILE_ONLY TRUE)
64 82
diff --git a/linden/indra/llaudio/audioengine.cpp b/linden/indra/llaudio/audioengine.cpp
index 81536cf..c5bc367 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,7 +90,7 @@ 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;
@@ -99,10 +98,13 @@ void LLAudioEngine::setDefaults()
99 98
100 for (U32 i = 0; i < LLAudioEngine::AUDIO_TYPE_COUNT; i++) 99 for (U32 i = 0; i < LLAudioEngine::AUDIO_TYPE_COUNT; i++)
101 mSecondaryGain[i] = 1.0f; 100 mSecondaryGain[i] = 1.0f;
101
102 mInternetStreamMedia = NULL;
103 mInternetStreamURL.clear();
102} 104}
103 105
104 106
105BOOL LLAudioEngine::init(const S32 num_channels, void* userdata) 107bool LLAudioEngine::init(const S32 num_channels, void* userdata)
106{ 108{
107 setDefaults(); 109 setDefaults();
108 110
@@ -114,7 +116,9 @@ BOOL LLAudioEngine::init(const S32 num_channels, void* userdata)
114 // Initialize the decode manager 116 // Initialize the decode manager
115 gAudioDecodeMgrp = new LLAudioDecodeMgr; 117 gAudioDecodeMgrp = new LLAudioDecodeMgr;
116 118
117 return TRUE; 119 llinfos << "LLAudioEngine::init() AudioEngine successfully initialized" << llendl;
120
121 return true;
118} 122}
119 123
120 124
@@ -124,6 +128,9 @@ void LLAudioEngine::shutdown()
124 delete gAudioDecodeMgrp; 128 delete gAudioDecodeMgrp;
125 gAudioDecodeMgrp = NULL; 129 gAudioDecodeMgrp = NULL;
126 130
131 // Clean up wind source
132 cleanupWind();
133
127 // Clean up audio sources 134 // Clean up audio sources
128 source_map::iterator iter_src; 135 source_map::iterator iter_src;
129 for (iter_src = mAllSources.begin(); iter_src != mAllSources.end(); iter_src++) 136 for (iter_src = mAllSources.begin(); iter_src != mAllSources.end(); iter_src++)
@@ -144,22 +151,145 @@ void LLAudioEngine::shutdown()
144 S32 i; 151 S32 i;
145 for (i = 0; i < MAX_CHANNELS; i++) 152 for (i = 0; i < MAX_CHANNELS; i++)
146 { 153 {
147 if (mChannels[i]) 154 delete mChannels[i];
148 { 155 mChannels[i] = NULL;
149 delete mChannels[i];
150 mChannels[i] = NULL;
151 }
152 } 156 }
153 157
154 // Clean up buffers 158 // Clean up buffers
155 for (i = 0; i < MAX_BUFFERS; i++) 159 for (i = 0; i < MAX_BUFFERS; i++)
156 { 160 {
157 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)
158 { 180 {
159 delete mBuffers[i]; 181 mInternetStreamMedia = mgr->createSourceFromMimeType(LLURI(url).scheme(), "audio/mpeg"); // assumes that whatever media implementation supports mp3 also supports vorbis.
160 mBuffers[i] = NULL; 182 llinfos << "mInternetStreamMedia is now " << mInternetStreamMedia << llendl;
161 } 183 }
162 } 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}
203
204// virtual
205void LLAudioEngine::stopInternetStream()
206{
207 llinfos << "entered stopInternetStream()" << llendl;
208
209 if(mInternetStreamMedia)
210 {
211 if( ! mInternetStreamMedia->addCommand(LLMediaBase::COMMAND_STOP)){
212 llinfos << "attempting to stop stream failed!" << llendl;
213 }
214 mInternetStreamMedia->updateMedia();
215 }
216
217 mInternetStreamURL.clear();
218}
219
220// virtual
221void LLAudioEngine::pauseInternetStream(int pause)
222{
223 llinfos << "entered pauseInternetStream()" << llendl;
224
225 if(!mInternetStreamMedia)
226 return;
227
228 if(pause)
229 {
230 if(! mInternetStreamMedia->addCommand(LLMediaBase::COMMAND_PAUSE))
231 {
232 llinfos << "attempting to pause stream failed!" << llendl;
233 }
234 } else {
235 if(! mInternetStreamMedia->addCommand(LLMediaBase::COMMAND_START))
236 {
237 llinfos << "attempting to unpause stream failed!" << llendl;
238 }
239 }
240 mInternetStreamMedia->updateMedia();
241}
242
243// virtual
244void LLAudioEngine::updateInternetStream()
245{
246 if (mInternetStreamMedia)
247 mInternetStreamMedia->updateMedia();
248}
249
250// virtual
251int LLAudioEngine::isInternetStreamPlaying()
252{
253 if (!mInternetStreamMedia)
254 return 0;
255
256 if (mInternetStreamMedia->getStatus() == LLMediaBase::STATUS_STARTED)
257 {
258 return 1; // Active and playing
259 }
260
261 if (mInternetStreamMedia->getStatus() == LLMediaBase::STATUS_PAUSED)
262 {
263 return 2; // paused
264 }
265
266 return 0; // Stopped
267}
268
269// virtual
270void LLAudioEngine::getInternetStreamInfo(char* artist, char* title)
271{
272 artist[0] = 0;
273 title[0] = 0;
274}
275
276// virtual
277void LLAudioEngine::setInternetStreamGain(F32 vol)
278{
279 mInternetStreamGain = vol;
280
281 if(!mInternetStreamMedia)
282 return;
283
284 vol = llclamp(vol, 0.f, 1.f);
285 mInternetStreamMedia->setVolume(vol);
286 mInternetStreamMedia->updateMedia();
287}
288
289// virtual
290const std::string& LLAudioEngine::getInternetStreamURL()
291{
292 return mInternetStreamURL;
163} 293}
164 294
165 295
@@ -203,7 +333,7 @@ void LLAudioEngine::idle(F32 max_decode_time)
203 { 333 {
204 if (mBuffers[i]) 334 if (mBuffers[i])
205 { 335 {
206 mBuffers[i]->mInUse = FALSE; 336 mBuffers[i]->mInUse = false;
207 } 337 }
208 } 338 }
209 339
@@ -255,11 +385,11 @@ void LLAudioEngine::idle(F32 max_decode_time)
255 { 385 {
256 // A sync slave, it doesn't start playing until it's synced up with the master. 386 // A sync slave, it doesn't start playing until it's synced up with the master.
257 // Flag this channel as waiting for sync, and return true. 387 // Flag this channel as waiting for sync, and return true.
258 channelp->setWaiting(TRUE); 388 channelp->setWaiting(true);
259 } 389 }
260 else 390 else
261 { 391 {
262 channelp->setWaiting(FALSE); 392 channelp->setWaiting(false);
263 channelp->play(); 393 channelp->play();
264 } 394 }
265 } 395 }
@@ -399,7 +529,7 @@ void LLAudioEngine::idle(F32 max_decode_time)
399 if (sync_masterp->getChannel()) 529 if (sync_masterp->getChannel())
400 { 530 {
401 channelp->playSynced(master_channelp); 531 channelp->playSynced(master_channelp);
402 channelp->setWaiting(FALSE); 532 channelp->setWaiting(false);
403 } 533 }
404 } 534 }
405 } 535 }
@@ -429,7 +559,7 @@ void LLAudioEngine::idle(F32 max_decode_time)
429 { 559 {
430 if (mChannels[i]) 560 if (mChannels[i])
431 { 561 {
432 mChannels[i]->mLoopedThisFrame = FALSE; 562 mChannels[i]->mLoopedThisFrame = false;
433 } 563 }
434 } 564 }
435 565
@@ -440,13 +570,17 @@ void LLAudioEngine::idle(F32 max_decode_time)
440 // missed picking it up in all the places that can add 570 // missed picking it up in all the places that can add
441 // or request new data. 571 // or request new data.
442 startNextTransfer(); 572 startNextTransfer();
573
574 updateInternetStream();
443} 575}
444 576
445BOOL LLAudioEngine::updateBufferForData(LLAudioData *adp, const LLUUID &audio_uuid) 577
578
579bool LLAudioEngine::updateBufferForData(LLAudioData *adp, const LLUUID &audio_uuid)
446{ 580{
447 if (!adp) 581 if (!adp)
448 { 582 {
449 return FALSE; 583 return false;
450 } 584 }
451 585
452 // Update the audio buffer first - load a sound if we have it. 586 // Update the audio buffer first - load a sound if we have it.
@@ -469,14 +603,14 @@ BOOL LLAudioEngine::updateBufferForData(LLAudioData *adp, const LLUUID &audio_uu
469 } 603 }
470 else 604 else
471 { 605 {
472 return FALSE; 606 return false;
473 } 607 }
474 } 608 }
475 return TRUE; 609 return true;
476} 610}
477 611
478 612
479void LLAudioEngine::enableWind(BOOL enable) 613void LLAudioEngine::enableWind(bool enable)
480{ 614{
481 if (enable && (!mEnableWind)) 615 if (enable && (!mEnableWind))
482 { 616 {
@@ -604,7 +738,7 @@ void LLAudioEngine::cleanupBuffer(LLAudioBuffer *bufferp)
604} 738}
605 739
606 740
607BOOL LLAudioEngine::preloadSound(const LLUUID &uuid) 741bool LLAudioEngine::preloadSound(const LLUUID &uuid)
608{ 742{
609 gAudiop->getAudioData(uuid); // We don't care about the return value, this is just to make sure 743 gAudiop->getAudioData(uuid); // We don't care about the return value, this is just to make sure
610 // that we have an entry, which will mean that the audio engine knows about this 744 // that we have an entry, which will mean that the audio engine knows about this
@@ -612,23 +746,23 @@ BOOL LLAudioEngine::preloadSound(const LLUUID &uuid)
612 if (gAudioDecodeMgrp->addDecodeRequest(uuid)) 746 if (gAudioDecodeMgrp->addDecodeRequest(uuid))
613 { 747 {
614 // This means that we do have a local copy, and we're working on decoding it. 748 // This means that we do have a local copy, and we're working on decoding it.
615 return TRUE; 749 return true;
616 } 750 }
617 751
618 // At some point we need to have the audio/asset system check the static VFS 752 // At some point we need to have the audio/asset system check the static VFS
619 // before it goes off and fetches stuff from the server. 753 // before it goes off and fetches stuff from the server.
620 //llwarns << "Used internal preload for non-local sound" << llendl; 754 //llwarns << "Used internal preload for non-local sound" << llendl;
621 return FALSE; 755 return false;
622} 756}
623 757
624 758
625BOOL LLAudioEngine::isWindEnabled() 759bool LLAudioEngine::isWindEnabled()
626{ 760{
627 return mEnableWind; 761 return mEnableWind;
628} 762}
629 763
630 764
631void LLAudioEngine::setMuted(BOOL muted) 765void LLAudioEngine::setMuted(bool muted)
632{ 766{
633 mMuted = muted; 767 mMuted = muted;
634 enableWind(!mMuted); 768 enableWind(!mMuted);
@@ -751,7 +885,7 @@ void LLAudioEngine::triggerSound(const LLUUID &audio_uuid, const LLUUID& owner_i
751 gAudiop->addAudioSource(asp); 885 gAudiop->addAudioSource(asp);
752 if (pos_global.isExactlyZero()) 886 if (pos_global.isExactlyZero())
753 { 887 {
754 asp->setAmbient(TRUE); 888 asp->setAmbient(true);
755 } 889 }
756 else 890 else
757 { 891 {
@@ -930,7 +1064,7 @@ void LLAudioEngine::cleanupAudioSource(LLAudioSource *asp)
930} 1064}
931 1065
932 1066
933BOOL LLAudioEngine::hasDecodedFile(const LLUUID &uuid) 1067bool LLAudioEngine::hasDecodedFile(const LLUUID &uuid)
934{ 1068{
935 std::string uuid_str; 1069 std::string uuid_str;
936 uuid.toString(uuid_str); 1070 uuid.toString(uuid_str);
@@ -941,16 +1075,16 @@ BOOL LLAudioEngine::hasDecodedFile(const LLUUID &uuid)
941 1075
942 if (gDirUtilp->fileExists(wav_path)) 1076 if (gDirUtilp->fileExists(wav_path))
943 { 1077 {
944 return TRUE; 1078 return true;
945 } 1079 }
946 else 1080 else
947 { 1081 {
948 return FALSE; 1082 return false;
949 } 1083 }
950} 1084}
951 1085
952 1086
953BOOL LLAudioEngine::hasLocalFile(const LLUUID &uuid) 1087bool LLAudioEngine::hasLocalFile(const LLUUID &uuid)
954{ 1088{
955 // See if it's in the VFS. 1089 // See if it's in the VFS.
956 return gVFS->getExists(uuid, LLAssetType::AT_SOUND); 1090 return gVFS->getExists(uuid, LLAssetType::AT_SOUND);
@@ -1166,9 +1300,9 @@ void LLAudioEngine::assetCallback(LLVFS *vfs, const LLUUID &uuid, LLAssetType::E
1166 LLAudioData *adp = gAudiop->getAudioData(uuid); 1300 LLAudioData *adp = gAudiop->getAudioData(uuid);
1167 if (adp) 1301 if (adp)
1168 { 1302 {
1169 adp->setHasValidData(FALSE); 1303 adp->setHasValidData(false);
1170 adp->setHasLocalData(FALSE); 1304 adp->setHasLocalData(false);
1171 adp->setHasDecodedData(FALSE); 1305 adp->setHasDecodedData(false);
1172 } 1306 }
1173 } 1307 }
1174 else 1308 else
@@ -1181,8 +1315,8 @@ void LLAudioEngine::assetCallback(LLVFS *vfs, const LLUUID &uuid, LLAssetType::E
1181 } 1315 }
1182 else 1316 else
1183 { 1317 {
1184 adp->setHasValidData(TRUE); 1318 adp->setHasValidData(true);
1185 adp->setHasLocalData(TRUE); 1319 adp->setHasLocalData(true);
1186 gAudioDecodeMgrp->addDecodeRequest(uuid); 1320 gAudioDecodeMgrp->addDecodeRequest(uuid);
1187 } 1321 }
1188 } 1322 }
@@ -1202,12 +1336,12 @@ LLAudioSource::LLAudioSource(const LLUUID& id, const LLUUID& owner_id, const F32
1202 mPriority(0.f), 1336 mPriority(0.f),
1203 mGain(gain), 1337 mGain(gain),
1204 mType(type), 1338 mType(type),
1205 mAmbient(FALSE), 1339 mAmbient(false),
1206 mLoop(FALSE), 1340 mLoop(false),
1207 mSyncMaster(FALSE), 1341 mSyncMaster(false),
1208 mSyncSlave(FALSE), 1342 mSyncSlave(false),
1209 mQueueSounds(FALSE), 1343 mQueueSounds(false),
1210 mPlayedOnce(FALSE), 1344 mPlayedOnce(false),
1211 mChannelp(NULL), 1345 mChannelp(NULL),
1212 mCurrentDatap(NULL), 1346 mCurrentDatap(NULL),
1213 mQueuedDatap(NULL) 1347 mQueuedDatap(NULL)
@@ -1271,7 +1405,7 @@ void LLAudioSource::updatePriority()
1271 } 1405 }
1272} 1406}
1273 1407
1274BOOL LLAudioSource::setupChannel() 1408bool LLAudioSource::setupChannel()
1275{ 1409{
1276 LLAudioData *adp = getCurrentData(); 1410 LLAudioData *adp = getCurrentData();
1277 1411
@@ -1279,7 +1413,7 @@ BOOL LLAudioSource::setupChannel()
1279 { 1413 {
1280 // We're not ready to play back the sound yet, so don't try and allocate a channel for it. 1414 // We're not ready to play back the sound yet, so don't try and allocate a channel for it.
1281 //llwarns << "Aborting, no buffer" << llendl; 1415 //llwarns << "Aborting, no buffer" << llendl;
1282 return FALSE; 1416 return false;
1283 } 1417 }
1284 1418
1285 1419
@@ -1297,15 +1431,15 @@ BOOL LLAudioSource::setupChannel()
1297 // Now we have to reprioritize. 1431 // Now we have to reprioritize.
1298 // For now, just don't play the sound. 1432 // For now, just don't play the sound.
1299 //llwarns << "Aborting, no free channels" << llendl; 1433 //llwarns << "Aborting, no free channels" << llendl;
1300 return FALSE; 1434 return false;
1301 } 1435 }
1302 1436
1303 mChannelp->setSource(this); 1437 mChannelp->setSource(this);
1304 return TRUE; 1438 return true;
1305} 1439}
1306 1440
1307 1441
1308BOOL LLAudioSource::play(const LLUUID &audio_uuid) 1442bool LLAudioSource::play(const LLUUID &audio_uuid)
1309{ 1443{
1310 if (audio_uuid.isNull()) 1444 if (audio_uuid.isNull())
1311 { 1445 {
@@ -1313,7 +1447,7 @@ BOOL LLAudioSource::play(const LLUUID &audio_uuid)
1313 { 1447 {
1314 getChannel()->setSource(NULL); 1448 getChannel()->setSource(NULL);
1315 setChannel(NULL); 1449 setChannel(NULL);
1316 addAudioData(NULL, TRUE); 1450 addAudioData(NULL, true);
1317 } 1451 }
1318 } 1452 }
1319 // Reset our age timeout if someone attempts to play the source. 1453 // Reset our age timeout if someone attempts to play the source.
@@ -1321,7 +1455,7 @@ BOOL LLAudioSource::play(const LLUUID &audio_uuid)
1321 1455
1322 LLAudioData *adp = gAudiop->getAudioData(audio_uuid); 1456 LLAudioData *adp = gAudiop->getAudioData(audio_uuid);
1323 1457
1324 BOOL has_buffer = gAudiop->updateBufferForData(adp, audio_uuid); 1458 bool has_buffer = gAudiop->updateBufferForData(adp, audio_uuid);
1325 1459
1326 1460
1327 addAudioData(adp); 1461 addAudioData(adp);
@@ -1329,47 +1463,48 @@ BOOL LLAudioSource::play(const LLUUID &audio_uuid)
1329 if (!has_buffer) 1463 if (!has_buffer)
1330 { 1464 {
1331 // Don't bother trying to set up a channel or anything, we don't have an audio buffer. 1465 // Don't bother trying to set up a channel or anything, we don't have an audio buffer.
1332 return FALSE; 1466 return false;
1333 } 1467 }
1334 1468
1335 if (!setupChannel()) 1469 if (!setupChannel())
1336 { 1470 {
1337 return FALSE; 1471 return false;
1338 } 1472 }
1339 1473
1340 if (isSyncSlave()) 1474 if (isSyncSlave())
1341 { 1475 {
1342 // A sync slave, it doesn't start playing until it's synced up with the master. 1476 // A sync slave, it doesn't start playing until it's synced up with the master.
1343 // Flag this channel as waiting for sync, and return true. 1477 // Flag this channel as waiting for sync, and return true.
1344 getChannel()->setWaiting(TRUE); 1478 getChannel()->setWaiting(true);
1345 return TRUE; 1479 return true;
1346 } 1480 }
1347 1481
1348 getChannel()->play(); 1482 getChannel()->play();
1349 return TRUE; 1483 return true;
1350} 1484}
1351 1485
1352 1486
1353BOOL LLAudioSource::isDone() 1487bool LLAudioSource::isDone()
1354{ 1488{
1355 const F32 MAX_AGE = 60.f; 1489 const F32 MAX_AGE = 60.f;
1356 const F32 MAX_UNPLAYED_AGE = 15.f; 1490 const F32 MAX_UNPLAYED_AGE = 15.f;
1491
1357 if (isLoop()) 1492 if (isLoop())
1358 { 1493 {
1359 // Looped sources never die on their own. 1494 // Looped sources never die on their own.
1360 return FALSE; 1495 return false;
1361 } 1496 }
1362 1497
1363 1498
1364 if (hasPendingPreloads()) 1499 if (hasPendingPreloads())
1365 { 1500 {
1366 return FALSE; 1501 return false;
1367 } 1502 }
1368 1503
1369 if (mQueuedDatap) 1504 if (mQueuedDatap)
1370 { 1505 {
1371 // Don't kill this sound if we've got something queued up to play. 1506 // Don't kill this sound if we've got something queued up to play.
1372 return FALSE; 1507 return false;
1373 } 1508 }
1374 1509
1375 F32 elapsed = mAgeTimer.getElapsedTimeF32(); 1510 F32 elapsed = mAgeTimer.getElapsedTimeF32();
@@ -1382,11 +1517,11 @@ BOOL LLAudioSource::isDone()
1382 // We don't have a channel assigned, and it's been 1517 // We don't have a channel assigned, and it's been
1383 // over 5 seconds since we tried to play it. Don't bother. 1518 // over 5 seconds since we tried to play it. Don't bother.
1384 //llinfos << "No channel assigned, source is done" << llendl; 1519 //llinfos << "No channel assigned, source is done" << llendl;
1385 return TRUE; 1520 return true;
1386 } 1521 }
1387 else 1522 else
1388 { 1523 {
1389 return FALSE; 1524 return false;
1390 } 1525 }
1391 } 1526 }
1392 1527
@@ -1394,27 +1529,27 @@ BOOL LLAudioSource::isDone()
1394 { 1529 {
1395 if (elapsed > MAX_AGE) 1530 if (elapsed > MAX_AGE)
1396 { 1531 {
1397 // Arbitarily cut off non-looped sounds when they're 20 seconds old. 1532 // Arbitarily cut off non-looped sounds when they're old.
1398 return TRUE; 1533 return true;
1399 } 1534 }
1400 else 1535 else
1401 { 1536 {
1402 // Sound is still playing and we haven't timed out, don't kill it. 1537 // Sound is still playing and we haven't timed out, don't kill it.
1403 return FALSE; 1538 return false;
1404 } 1539 }
1405 } 1540 }
1406 1541
1407 if ((elapsed > MAX_UNPLAYED_AGE) || mPlayedOnce) 1542 if ((elapsed > MAX_UNPLAYED_AGE) || mPlayedOnce)
1408 { 1543 {
1409 // The sound isn't playing back after 5 seconds or we're already done playing it, kill it. 1544 // The sound isn't playing back after 5 seconds or we're already done playing it, kill it.
1410 return TRUE; 1545 return true;
1411 } 1546 }
1412 1547
1413 return FALSE; 1548 return false;
1414} 1549}
1415 1550
1416 1551
1417void LLAudioSource::addAudioData(LLAudioData *adp, const BOOL set_current) 1552void LLAudioSource::addAudioData(LLAudioData *adp, const bool set_current)
1418{ 1553{
1419 // Only handle a single piece of audio data associated with a source right now, 1554 // Only handle a single piece of audio data associated with a source right now,
1420 // until I implement prefetch. 1555 // until I implement prefetch.
@@ -1482,7 +1617,7 @@ void LLAudioSource::addAudioData(LLAudioData *adp, const BOOL set_current)
1482} 1617}
1483 1618
1484 1619
1485BOOL LLAudioSource::hasPendingPreloads() const 1620bool LLAudioSource::hasPendingPreloads() const
1486{ 1621{
1487 // Check to see if we've got any preloads on deck for this source 1622 // Check to see if we've got any preloads on deck for this source
1488 data_map::const_iterator iter; 1623 data_map::const_iterator iter;
@@ -1492,11 +1627,11 @@ BOOL LLAudioSource::hasPendingPreloads() const
1492 if (!adp->hasDecodedData()) 1627 if (!adp->hasDecodedData())
1493 { 1628 {
1494 // This source is still waiting for a preload 1629 // This source is still waiting for a preload
1495 return TRUE; 1630 return true;
1496 } 1631 }
1497 } 1632 }
1498 1633
1499 return FALSE; 1634 return false;
1500} 1635}
1501 1636
1502 1637
@@ -1531,8 +1666,8 @@ LLAudioBuffer *LLAudioSource::getCurrentBuffer()
1531LLAudioChannel::LLAudioChannel() : 1666LLAudioChannel::LLAudioChannel() :
1532 mCurrentSourcep(NULL), 1667 mCurrentSourcep(NULL),
1533 mCurrentBufferp(NULL), 1668 mCurrentBufferp(NULL),
1534 mLoopedThisFrame(FALSE), 1669 mLoopedThisFrame(false),
1535 mWaiting(FALSE), 1670 mWaiting(false),
1536 mSecondaryGain(1.0f) 1671 mSecondaryGain(1.0f)
1537{ 1672{
1538} 1673}
@@ -1560,7 +1695,7 @@ void LLAudioChannel::setSource(LLAudioSource *sourcep)
1560 //llinfos << "Clearing source for channel" << llendl; 1695 //llinfos << "Clearing source for channel" << llendl;
1561 cleanup(); 1696 cleanup();
1562 mCurrentSourcep = NULL; 1697 mCurrentSourcep = NULL;
1563 mWaiting = FALSE; 1698 mWaiting = false;
1564 return; 1699 return;
1565 } 1700 }
1566 1701
@@ -1578,13 +1713,13 @@ void LLAudioChannel::setSource(LLAudioSource *sourcep)
1578} 1713}
1579 1714
1580 1715
1581BOOL LLAudioChannel::updateBuffer() 1716bool LLAudioChannel::updateBuffer()
1582{ 1717{
1583 if (!mCurrentSourcep) 1718 if (!mCurrentSourcep)
1584 { 1719 {
1585 // This channel isn't associated with any source, nothing 1720 // This channel isn't associated with any source, nothing
1586 // to be updated 1721 // to be updated
1587 return FALSE; 1722 return false;
1588 } 1723 }
1589 1724
1590 // Initialize the channel's gain setting for this sound. 1725 // Initialize the channel's gain setting for this sound.
@@ -1600,14 +1735,14 @@ BOOL LLAudioChannel::updateBuffer()
1600 { 1735 {
1601 // The source hasn't changed what buffer it's playing 1736 // The source hasn't changed what buffer it's playing
1602 bufferp->mLastUseTimer.reset(); 1737 bufferp->mLastUseTimer.reset();
1603 bufferp->mInUse = TRUE; 1738 bufferp->mInUse = true;
1604 } 1739 }
1605 return FALSE; 1740 return false;
1606 } 1741 }
1607 1742
1608 // 1743 //
1609 // 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
1610 // existing fmod channel 1745 // the existing channel
1611 // 1746 //
1612 cleanup(); 1747 cleanup();
1613 1748
@@ -1615,16 +1750,16 @@ BOOL LLAudioChannel::updateBuffer()
1615 if (bufferp) 1750 if (bufferp)
1616 { 1751 {
1617 bufferp->mLastUseTimer.reset(); 1752 bufferp->mLastUseTimer.reset();
1618 bufferp->mInUse = TRUE; 1753 bufferp->mInUse = true;
1619 } 1754 }
1620 1755
1621 if (!mCurrentBufferp) 1756 if (!mCurrentBufferp)
1622 { 1757 {
1623 // 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.
1624 return FALSE; 1759 return false;
1625 } 1760 }
1626 1761
1627 return TRUE; 1762 return true;
1628} 1763}
1629 1764
1630 1765
@@ -1638,9 +1773,9 @@ BOOL LLAudioChannel::updateBuffer()
1638LLAudioData::LLAudioData(const LLUUID &uuid) : 1773LLAudioData::LLAudioData(const LLUUID &uuid) :
1639 mID(uuid), 1774 mID(uuid),
1640 mBufferp(NULL), 1775 mBufferp(NULL),
1641 mHasLocalData(FALSE), 1776 mHasLocalData(false),
1642 mHasDecodedData(FALSE), 1777 mHasDecodedData(false),
1643 mHasValidData(TRUE) 1778 mHasValidData(true)
1644{ 1779{
1645 if (uuid.isNull()) 1780 if (uuid.isNull())
1646 { 1781 {
@@ -1651,24 +1786,24 @@ LLAudioData::LLAudioData(const LLUUID &uuid) :
1651 if (gAudiop && gAudiop->hasDecodedFile(uuid)) 1786 if (gAudiop && gAudiop->hasDecodedFile(uuid))
1652 { 1787 {
1653 // Already have a decoded version, don't need to decode it. 1788 // Already have a decoded version, don't need to decode it.
1654 mHasLocalData = TRUE; 1789 mHasLocalData = true;
1655 mHasDecodedData = TRUE; 1790 mHasDecodedData = true;
1656 } 1791 }
1657 else if (gAssetStorage && gAssetStorage->hasLocalAsset(uuid, LLAssetType::AT_SOUND)) 1792 else if (gAssetStorage && gAssetStorage->hasLocalAsset(uuid, LLAssetType::AT_SOUND))
1658 { 1793 {
1659 mHasLocalData = TRUE; 1794 mHasLocalData = true;
1660 } 1795 }
1661} 1796}
1662 1797
1663 1798
1664BOOL LLAudioData::load() 1799bool LLAudioData::load()
1665{ 1800{
1666 // 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.
1667 if (mBufferp) 1802 if (mBufferp)
1668 { 1803 {
1669 // 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.
1670 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;
1671 return TRUE; 1806 return true;
1672 } 1807 }
1673 1808
1674 mBufferp = gAudiop->getFreeBuffer(); 1809 mBufferp = gAudiop->getFreeBuffer();
@@ -1676,7 +1811,7 @@ BOOL LLAudioData::load()
1676 { 1811 {
1677 // No free buffers, abort. 1812 // No free buffers, abort.
1678 llinfos << "Not able to allocate a new audio buffer, aborting." << llendl; 1813 llinfos << "Not able to allocate a new audio buffer, aborting." << llendl;
1679 return FALSE; 1814 return false;
1680 } 1815 }
1681 1816
1682 std::string uuid_str; 1817 std::string uuid_str;
@@ -1690,10 +1825,10 @@ BOOL LLAudioData::load()
1690 gAudiop->cleanupBuffer(mBufferp); 1825 gAudiop->cleanupBuffer(mBufferp);
1691 mBufferp = NULL; 1826 mBufferp = NULL;
1692 1827
1693 return FALSE; 1828 return false;
1694 } 1829 }
1695 mBufferp->mAudioDatap = this; 1830 mBufferp->mAudioDatap = this;
1696 return TRUE; 1831 return true;
1697} 1832}
1698 1833
1699 1834
diff --git a/linden/indra/llaudio/audioengine.h b/linden/indra/llaudio/audioengine.h
index 0bd6327..b582f14 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,6 +80,8 @@ class LLAudioBuffer;
77 80
78class LLAudioEngine 81class LLAudioEngine
79{ 82{
83 friend class LLAudioChannelOpenAL; // bleh. channel needs some listener methods.
84
80public: 85public:
81 enum LLAudioType 86 enum LLAudioType
82 { 87 {
@@ -91,9 +96,8 @@ public:
91 virtual ~LLAudioEngine(); 96 virtual ~LLAudioEngine();
92 97
93 // initialization/startup/shutdown 98 // initialization/startup/shutdown
94 //virtual BOOL init(); 99 virtual bool init(const S32 num_channels, void *userdata);
95 100 virtual std::string getDriverName(bool verbose) = 0;
96 virtual BOOL init(const S32 num_channels, void *userdata);
97 virtual void shutdown(); 101 virtual void shutdown();
98 102
99 // Used by the mechanics of the engine 103 // Used by the mechanics of the engine
@@ -106,14 +110,14 @@ public:
106 // 110 //
107 // "End user" functionality 111 // "End user" functionality
108 // 112 //
109 virtual BOOL isWindEnabled(); 113 virtual bool isWindEnabled();
110 virtual void enableWind(BOOL state_b); 114 virtual void enableWind(bool state_b);
111 115
112 // Use these for temporarily muting the audio system. 116 // Use these for temporarily muting the audio system.
113 // Does not change buffers, initialization, etc. but 117 // Does not change buffers, initialization, etc. but
114 // stops playing new sounds. 118 // stops playing new sounds.
115 virtual void setMuted(BOOL muted); 119 virtual void setMuted(bool muted);
116 virtual BOOL getMuted() const { return mMuted; } 120 virtual bool getMuted() const { return mMuted; }
117 121
118 F32 getMasterGain(); 122 F32 getMasterGain();
119 void setMasterGain(F32 gain); 123 void setMasterGain(F32 gain);
@@ -137,7 +141,7 @@ public:
137 void triggerSound(const LLUUID &sound_id, const LLUUID& owner_id, const F32 gain, 141 void triggerSound(const LLUUID &sound_id, const LLUUID& owner_id, const F32 gain,
138 const S32 type = LLAudioEngine::AUDIO_TYPE_NONE, 142 const S32 type = LLAudioEngine::AUDIO_TYPE_NONE,
139 const LLVector3d &pos_global = LLVector3d::zero); 143 const LLVector3d &pos_global = LLVector3d::zero);
140 BOOL preloadSound(const LLUUID &id); 144 bool preloadSound(const LLUUID &id);
141 145
142 void addAudioSource(LLAudioSource *asp); 146 void addAudioSource(LLAudioSource *asp);
143 void cleanupAudioSource(LLAudioSource *asp); 147 void cleanupAudioSource(LLAudioSource *asp);
@@ -146,14 +150,16 @@ public:
146 LLAudioData *getAudioData(const LLUUID &audio_uuid); 150 LLAudioData *getAudioData(const LLUUID &audio_uuid);
147 151
148 152
149 virtual void startInternetStream(const std::string& url) = 0; 153 // Internet stream methods
150 virtual void stopInternetStream() = 0; 154 virtual void startInternetStream(const std::string& url);
151 virtual void pauseInternetStream(int pause) = 0; 155 virtual void stopInternetStream();
152 virtual int isInternetStreamPlaying() = 0; 156 virtual void pauseInternetStream(int pause);
153 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);
154 // use a value from 0.0 to 1.0, inclusive 160 // use a value from 0.0 to 1.0, inclusive
155 virtual void setInternetStreamGain(F32 vol) { mInternetStreamGain = vol; } 161 virtual void setInternetStreamGain(F32 vol);
156 virtual const std::string& getInternetStreamURL() { return LLStringUtil::null; } 162 virtual const std::string& getInternetStreamURL();
157 163
158 // For debugging usage 164 // For debugging usage
159 virtual LLVector3 getListenerPos(); 165 virtual LLVector3 getListenerPos();
@@ -162,17 +168,16 @@ public:
162 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
163 void cleanupBuffer(LLAudioBuffer *bufferp); 169 void cleanupBuffer(LLAudioBuffer *bufferp);
164 170
165 BOOL hasDecodedFile(const LLUUID &uuid); 171 bool hasDecodedFile(const LLUUID &uuid);
166 BOOL hasLocalFile(const LLUUID &uuid); 172 bool hasLocalFile(const LLUUID &uuid);
167 173
168 BOOL updateBufferForData(LLAudioData *adp, const LLUUID &audio_uuid = LLUUID::null); 174 bool updateBufferForData(LLAudioData *adp, const LLUUID &audio_uuid = LLUUID::null);
169 175
170 176
171 // 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.
172 void startNextTransfer(); 178 void startNextTransfer();
173 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);
174 180
175
176 friend class LLPipeline; // For debugging 181 friend class LLPipeline; // For debugging
177public: 182public:
178 F32 mMaxWindGain; // Hack. Public to set before fade in? 183 F32 mMaxWindGain; // Hack. Public to set before fade in?
@@ -190,11 +195,6 @@ protected:
190 virtual void allocateListener() = 0; 195 virtual void allocateListener() = 0;
191 196
192 197
193 // Internet stream methods
194 virtual void initInternetStream() {}
195 virtual void updateInternetStream() {}
196
197
198 // listener methods 198 // listener methods
199 virtual void setListenerPos(LLVector3 vec); 199 virtual void setListenerPos(LLVector3 vec);
200 virtual void setListenerVelocity(LLVector3 vec); 200 virtual void setListenerVelocity(LLVector3 vec);
@@ -209,13 +209,13 @@ protected:
209protected: 209protected:
210 LLListener *mListenerp; 210 LLListener *mListenerp;
211 211
212 BOOL mMuted; 212 bool mMuted;
213 void* mUserData; 213 void* mUserData;
214 214
215 S32 mLastStatus; 215 S32 mLastStatus;
216 216
217 S32 mNumChannels; 217 S32 mNumChannels;
218 BOOL mEnableWind; 218 bool mEnableWind;
219 219
220 LLUUID mCurrentTransfer; // Audio file currently being transferred by the system 220 LLUUID mCurrentTransfer; // Audio file currently being transferred by the system
221 LLFrameTimer mCurrentTransferTimer; 221 LLFrameTimer mCurrentTransferTimer;
@@ -240,6 +240,7 @@ protected:
240 240
241 // Hack! Internet streams are treated differently from other sources! 241 // Hack! Internet streams are treated differently from other sources!
242 F32 mInternetStreamGain; 242 F32 mInternetStreamGain;
243 std::string mInternetStreamURL;
243 244
244 F32 mNextWindUpdate; 245 F32 mNextWindUpdate;
245 246
@@ -247,6 +248,7 @@ protected:
247 248
248private: 249private:
249 void setDefaults(); 250 void setDefaults();
251 LLMediaBase *mInternetStreamMedia;
250}; 252};
251 253
252 254
@@ -270,24 +272,24 @@ public:
270 272
271 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.
272 274
273 void addAudioData(LLAudioData *adp, BOOL set_current = TRUE); 275 void addAudioData(LLAudioData *adp, bool set_current = TRUE);
274 276
275 void setAmbient(const BOOL ambient) { mAmbient = ambient; } 277 void setAmbient(const bool ambient) { mAmbient = ambient; }
276 BOOL isAmbient() const { return mAmbient; } 278 bool isAmbient() const { return mAmbient; }
277 279
278 void setLoop(const BOOL loop) { mLoop = loop; } 280 void setLoop(const bool loop) { mLoop = loop; }
279 BOOL isLoop() const { return mLoop; } 281 bool isLoop() const { return mLoop; }
280 282
281 void setSyncMaster(const BOOL master) { mSyncMaster = master; } 283 void setSyncMaster(const bool master) { mSyncMaster = master; }
282 BOOL isSyncMaster() const { return mSyncMaster; } 284 bool isSyncMaster() const { return mSyncMaster; }
283 285
284 void setSyncSlave(const BOOL slave) { mSyncSlave = slave; } 286 void setSyncSlave(const bool slave) { mSyncSlave = slave; }
285 BOOL isSyncSlave() const { return mSyncSlave; } 287 bool isSyncSlave() const { return mSyncSlave; }
286 288
287 void setQueueSounds(const BOOL queue) { mQueueSounds = queue; } 289 void setQueueSounds(const bool queue) { mQueueSounds = queue; }
288 BOOL isQueueSounds() const { return mQueueSounds; } 290 bool isQueueSounds() const { return mQueueSounds; }
289 291
290 void setPlayedOnce(const BOOL played_once) { mPlayedOnce = played_once; } 292 void setPlayedOnce(const bool played_once) { mPlayedOnce = played_once; }
291 293
292 void setType(S32 type) { mType = type; } 294 void setType(S32 type) { mType = type; }
293 S32 getType() { return mType; } 295 S32 getType() { return mType; }
@@ -302,16 +304,16 @@ public:
302 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); }
303 305
304 const LLUUID &getID() const { return mID; } 306 const LLUUID &getID() const { return mID; }
305 BOOL isDone(); 307 bool isDone();
306 308
307 LLAudioData *getCurrentData(); 309 LLAudioData *getCurrentData();
308 LLAudioData *getQueuedData(); 310 LLAudioData *getQueuedData();
309 LLAudioBuffer *getCurrentBuffer(); 311 LLAudioBuffer *getCurrentBuffer();
310 312
311 BOOL setupChannel(); 313 bool setupChannel();
312 BOOL play(const LLUUID &audio_id); // Start the audio source playing 314 bool play(const LLUUID &audio_id); // Start the audio source playing
313 315
314 BOOL hasPendingPreloads() const; // Has preloads that haven't been done yet 316 bool hasPendingPreloads() const; // Has preloads that haven't been done yet
315 317
316 friend class LLAudioEngine; 318 friend class LLAudioEngine;
317 friend class LLAudioChannel; 319 friend class LLAudioChannel;
@@ -324,12 +326,12 @@ protected:
324 LLUUID mOwnerID; // owner of the object playing the sound 326 LLUUID mOwnerID; // owner of the object playing the sound
325 F32 mPriority; 327 F32 mPriority;
326 F32 mGain; 328 F32 mGain;
327 BOOL mAmbient; 329 bool mAmbient;
328 BOOL mLoop; 330 bool mLoop;
329 BOOL mSyncMaster; 331 bool mSyncMaster;
330 BOOL mSyncSlave; 332 bool mSyncSlave;
331 BOOL mQueueSounds; 333 bool mQueueSounds;
332 BOOL mPlayedOnce; 334 bool mPlayedOnce;
333 S32 mType; 335 S32 mType;
334 LLVector3d mPositionGlobal; 336 LLVector3d mPositionGlobal;
335 LLVector3 mVelocity; 337 LLVector3 mVelocity;
@@ -359,27 +361,27 @@ class LLAudioData
359{ 361{
360public: 362public:
361 LLAudioData(const LLUUID &uuid); 363 LLAudioData(const LLUUID &uuid);
362 BOOL load(); 364 bool load();
363 365
364 LLUUID getID() const { return mID; } 366 LLUUID getID() const { return mID; }
365 LLAudioBuffer *getBuffer() const { return mBufferp; } 367 LLAudioBuffer *getBuffer() const { return mBufferp; }
366 368
367 BOOL hasLocalData() const { return mHasLocalData; } 369 bool hasLocalData() const { return mHasLocalData; }
368 BOOL hasDecodedData() const { return mHasDecodedData; } 370 bool hasDecodedData() const { return mHasDecodedData; }
369 BOOL hasValidData() const { return mHasValidData; } 371 bool hasValidData() const { return mHasValidData; }
370 372
371 void setHasLocalData(const BOOL hld) { mHasLocalData = hld; } 373 void setHasLocalData(const bool hld) { mHasLocalData = hld; }
372 void setHasDecodedData(const BOOL hdd) { mHasDecodedData = hdd; } 374 void setHasDecodedData(const bool hdd) { mHasDecodedData = hdd; }
373 void setHasValidData(const BOOL hvd) { mHasValidData = hvd; } 375 void setHasValidData(const bool hvd) { mHasValidData = hvd; }
374 376
375 friend class LLAudioEngine; // Severe laziness, bad. 377 friend class LLAudioEngine; // Severe laziness, bad.
376 378
377protected: 379protected:
378 LLUUID mID; 380 LLUUID mID;
379 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.
380 BOOL mHasLocalData; 382 bool mHasLocalData;
381 BOOL mHasDecodedData; 383 bool mHasDecodedData;
382 BOOL mHasValidData; 384 bool mHasValidData;
383}; 385};
384 386
385 387
@@ -408,18 +410,18 @@ protected:
408 virtual void play() = 0; 410 virtual void play() = 0;
409 virtual void playSynced(LLAudioChannel *channelp) = 0; 411 virtual void playSynced(LLAudioChannel *channelp) = 0;
410 virtual void cleanup() = 0; 412 virtual void cleanup() = 0;
411 virtual BOOL isPlaying() = 0; 413 virtual bool isPlaying() = 0;
412 void setWaiting(const BOOL waiting) { mWaiting = waiting; } 414 void setWaiting(const bool waiting) { mWaiting = waiting; }
413 BOOL isWaiting() const { return mWaiting; } 415 bool isWaiting() const { return mWaiting; }
414 416
415 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.
416 virtual void update3DPosition() = 0; 418 virtual void update3DPosition() = 0;
417 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.
418protected: 420protected:
419 LLAudioSource *mCurrentSourcep; 421 LLAudioSource *mCurrentSourcep;
420 LLAudioBuffer *mCurrentBufferp; 422 LLAudioBuffer *mCurrentBufferp;
421 BOOL mLoopedThisFrame; 423 bool mLoopedThisFrame;
422 BOOL mWaiting; // Waiting for sync. 424 bool mWaiting; // Waiting for sync.
423 F32 mSecondaryGain; 425 F32 mSecondaryGain;
424}; 426};
425 427
@@ -435,14 +437,14 @@ class LLAudioBuffer
435{ 437{
436public: 438public:
437 virtual ~LLAudioBuffer() {}; 439 virtual ~LLAudioBuffer() {};
438 virtual BOOL loadWAV(const std::string& filename) = 0; 440 virtual bool loadWAV(const std::string& filename) = 0;
439 virtual U32 getLength() = 0; 441 virtual U32 getLength() = 0;
440 442
441 friend class LLAudioEngine; 443 friend class LLAudioEngine;
442 friend class LLAudioChannel; 444 friend class LLAudioChannel;
443 friend class LLAudioData; 445 friend class LLAudioData;
444protected: 446protected:
445 BOOL mInUse; 447 bool mInUse;
446 LLAudioData *mAudioDatap; 448 LLAudioData *mAudioDatap;
447 LLFrameTimer mLastUseTimer; 449 LLFrameTimer mLastUseTimer;
448}; 450};
diff --git a/linden/indra/llaudio/audioengine_fmod.cpp b/linden/indra/llaudio/audioengine_fmod.cpp
index 666ecce..2197a45 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,10 +152,10 @@ 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_FMOD_ESD")) /*Flawfinder: ignore*/
174 { 159 {
175 LL_DEBUGS("AppInit") << "Trying ESD audio output..." << LL_ENDL; 160 LL_DEBUGS("AppInit") << "Trying ESD audio output..." << LL_ENDL;
176 if(FSOUND_SetOutput(FSOUND_OUTPUT_ESD) && 161 if(FSOUND_SetOutput(FSOUND_OUTPUT_ESD) &&
@@ -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;
@@ -188,14 +173,14 @@ BOOL LLAudioEngine_FMOD::init(const S32 num_channels, void* userdata)
188 } 173 }
189 174
190 if (!audio_ok) 175 if (!audio_ok)
191 if (NULL == getenv("LL_BAD_OSS")) /*Flawfinder: ignore*/ 176 if (NULL == getenv("LL_BAD_FMOD_OSS")) /*Flawfinder: ignore*/
192 { 177 {
193 LL_DEBUGS("AppInit") << "Trying OSS audio output..." << LL_ENDL; 178 LL_DEBUGS("AppInit") << "Trying OSS audio output..." << LL_ENDL;
194 if(FSOUND_SetOutput(FSOUND_OUTPUT_OSS) && 179 if(FSOUND_SetOutput(FSOUND_OUTPUT_OSS) &&
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;
@@ -205,14 +190,14 @@ BOOL LLAudioEngine_FMOD::init(const S32 num_channels, void* userdata)
205 } 190 }
206 191
207 if (!audio_ok) 192 if (!audio_ok)
208 if (NULL == getenv("LL_BAD_ALSA")) /*Flawfinder: ignore*/ 193 if (NULL == getenv("LL_BAD_FMOD_ALSA")) /*Flawfinder: ignore*/
209 { 194 {
210 LL_DEBUGS("AppInit") << "Trying ALSA audio output..." << LL_ENDL; 195 LL_DEBUGS("AppInit") << "Trying ALSA audio output..." << LL_ENDL;
211 if(FSOUND_SetOutput(FSOUND_OUTPUT_ALSA) && 196 if(FSOUND_SetOutput(FSOUND_OUTPUT_ALSA) &&
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,23 @@ 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} 250}
266 251
267 252
268void LLAudioEngine_FMOD::idle(F32 max_decode_time) 253std::string LLAudioEngine_FMOD::getDriverName(bool verbose)
269{ 254{
270 LLAudioEngine::idle(max_decode_time); 255 if (verbose)
271 256 {
272 updateInternetStream(); 257 F32 version = FSOUND_GetVersion();
258 return llformat("FMOD version %f", version);
259 }
260 else
261 {
262 return "FMOD";
263 }
273} 264}
274 265
275 266
@@ -287,7 +278,7 @@ void LLAudioEngine_FMOD::shutdown()
287{ 278{
288 if (gWindDSP) 279 if (gWindDSP)
289 { 280 {
290 FSOUND_DSP_SetActive(gWindDSP,FALSE); 281 FSOUND_DSP_SetActive(gWindDSP,false);
291 FSOUND_DSP_Free(gWindDSP); 282 FSOUND_DSP_Free(gWindDSP);
292 } 283 }
293 284
@@ -318,13 +309,15 @@ LLAudioChannel *LLAudioEngine_FMOD::createChannel()
318 309
319void LLAudioEngine_FMOD::initWind() 310void LLAudioEngine_FMOD::initWind()
320{ 311{
312 mWindGen = new LLWindGen<MIXBUFFERFORMAT>;
313
321 if (!gWindDSP) 314 if (!gWindDSP)
322 { 315 {
323 gWindDSP = FSOUND_DSP_Create(&windCallback, FSOUND_DSP_DEFAULTPRIORITY_CLEARUNIT + 20, NULL); 316 gWindDSP = FSOUND_DSP_Create(&windCallback, FSOUND_DSP_DEFAULTPRIORITY_CLEARUNIT + 20, mWindGen);
324 } 317 }
325 if (gWindDSP) 318 if (gWindDSP)
326 { 319 {
327 FSOUND_DSP_SetActive(gWindDSP, TRUE); 320 FSOUND_DSP_SetActive(gWindDSP, true);
328 } 321 }
329 mNextWindUpdate = 0.0; 322 mNextWindUpdate = 0.0;
330} 323}
@@ -334,10 +327,13 @@ void LLAudioEngine_FMOD::cleanupWind()
334{ 327{
335 if (gWindDSP) 328 if (gWindDSP)
336 { 329 {
337 FSOUND_DSP_SetActive(gWindDSP, FALSE); 330 FSOUND_DSP_SetActive(gWindDSP, false);
338 FSOUND_DSP_Free(gWindDSP); 331 FSOUND_DSP_Free(gWindDSP);
339 gWindDSP = NULL; 332 gWindDSP = NULL;
340 } 333 }
334
335 delete mWindGen;
336 mWindGen = NULL;
341} 337}
342 338
343 339
@@ -367,9 +363,9 @@ void LLAudioEngine_FMOD::updateWind(LLVector3 wind_vec, F32 camera_height_above_
367 pitch = 1.0 + mapWindVecToPitch(wind_vec); 363 pitch = 1.0 + mapWindVecToPitch(wind_vec);
368 center_freq = 80.0 * pow(pitch,2.5*(mapWindVecToGain(wind_vec)+1.0)); 364 center_freq = 80.0 * pow(pitch,2.5*(mapWindVecToGain(wind_vec)+1.0));
369 365
370 gTargetFreq = (F32)center_freq; 366 mWindGen->mTargetFreq = (F32)center_freq;
371 gTargetGain = (F32)mapWindVecToGain(wind_vec) * mMaxWindGain; 367 mWindGen->mTargetGain = (F32)mapWindVecToGain(wind_vec) * mMaxWindGain;
372 gTargetPanGainR = (F32)mapWindVecToPan(wind_vec); 368 mWindGen->mTargetPanGainR = (F32)mapWindVecToPan(wind_vec);
373 } 369 }
374} 370}
375 371
@@ -457,11 +453,11 @@ LLAudioChannelFMOD::~LLAudioChannelFMOD()
457} 453}
458 454
459 455
460BOOL LLAudioChannelFMOD::updateBuffer() 456bool LLAudioChannelFMOD::updateBuffer()
461{ 457{
462 if (LLAudioChannel::updateBuffer()) 458 if (LLAudioChannel::updateBuffer())
463 { 459 {
464 // Base class update returned TRUE, which means that we need to actually 460 // Base class update returned true, which means that we need to actually
465 // set up the channel for a different buffer. 461 // set up the channel for a different buffer.
466 462
467 LLAudioBufferFMOD *bufferp = (LLAudioBufferFMOD *)mCurrentSourcep->getCurrentBuffer(); 463 LLAudioBufferFMOD *bufferp = (LLAudioBufferFMOD *)mCurrentSourcep->getCurrentBuffer();
@@ -473,13 +469,13 @@ BOOL LLAudioChannelFMOD::updateBuffer()
473 // This is bad, there should ALWAYS be a sample associated with a legit 469 // This is bad, there should ALWAYS be a sample associated with a legit
474 // buffer. 470 // buffer.
475 llerrs << "No FMOD sample!" << llendl; 471 llerrs << "No FMOD sample!" << llendl;
476 return FALSE; 472 return false;
477 } 473 }
478 474
479 475
480 // Actually play the sound. Start it off paused so we can do all the necessary 476 // Actually play the sound. Start it off paused so we can do all the necessary
481 // setup. 477 // setup.
482 mChannelID = FSOUND_PlaySoundEx(FSOUND_FREE, samplep, FSOUND_DSP_GetSFXUnit(), TRUE); 478 mChannelID = FSOUND_PlaySoundEx(FSOUND_FREE, samplep, FSOUND_DSP_GetSFXUnit(), true);
483 479
484 //llinfos << "Setting up channel " << std::hex << mChannelID << std::dec << llendl; 480 //llinfos << "Setting up channel " << std::hex << mChannelID << std::dec << llendl;
485 } 481 }
@@ -501,7 +497,7 @@ BOOL LLAudioChannelFMOD::updateBuffer()
501 } 497 }
502 } 498 }
503 499
504 return TRUE; 500 return true;
505} 501}
506 502
507 503
@@ -524,12 +520,12 @@ void LLAudioChannelFMOD::update3DPosition()
524 if (mCurrentSourcep->isAmbient()) 520 if (mCurrentSourcep->isAmbient())
525 { 521 {
526 // Ambient sound, don't need to do any positional updates. 522 // Ambient sound, don't need to do any positional updates.
527 bufferp->set3DMode(FALSE); 523 bufferp->set3DMode(false);
528 } 524 }
529 else 525 else
530 { 526 {
531 // Localized sound. Update the position and velocity of the sound. 527 // Localized sound. Update the position and velocity of the sound.
532 bufferp->set3DMode(TRUE); 528 bufferp->set3DMode(true);
533 529
534 LLVector3 float_pos; 530 LLVector3 float_pos;
535 float_pos.setVec(mCurrentSourcep->getPositionGlobal()); 531 float_pos.setVec(mCurrentSourcep->getPositionGlobal());
@@ -550,13 +546,14 @@ void LLAudioChannelFMOD::updateLoop()
550 } 546 }
551 547
552 // 548 //
553 // Hack: We keep track of whether we looped or not by seeing when the sign of the last sample 549 // Hack: We keep track of whether we looped or not by seeing when the
554 // flips. This is pretty crappy. 550 // sample position looks like it's going backwards. Not reliable; may
551 // yield false negatives.
555 // 552 //
556 U32 cur_pos = FSOUND_GetCurrentPosition(mChannelID); 553 U32 cur_pos = FSOUND_GetCurrentPosition(mChannelID);
557 if (cur_pos < (U32)mLastSamplePos) 554 if (cur_pos < (U32)mLastSamplePos)
558 { 555 {
559 mLoopedThisFrame = TRUE; 556 mLoopedThisFrame = true;
560 } 557 }
561 mLastSamplePos = cur_pos; 558 mLastSamplePos = cur_pos;
562} 559}
@@ -589,11 +586,11 @@ void LLAudioChannelFMOD::play()
589 return; 586 return;
590 } 587 }
591 588
592 if (!FSOUND_SetPaused(mChannelID, FALSE)) 589 if (!FSOUND_SetPaused(mChannelID, false))
593 { 590 {
594 llwarns << "LLAudioChannelFMOD::play error: " << FMOD_ErrorString(FSOUND_GetError()) << llendl; 591 llwarns << "LLAudioChannelFMOD::play error: " << FMOD_ErrorString(FSOUND_GetError()) << llendl;
595 } 592 }
596 getSource()->setPlayedOnce(TRUE); 593 getSource()->setPlayedOnce(true);
597} 594}
598 595
599 596
@@ -618,11 +615,11 @@ void LLAudioChannelFMOD::playSynced(LLAudioChannel *channelp)
618} 615}
619 616
620 617
621BOOL LLAudioChannelFMOD::isPlaying() 618bool LLAudioChannelFMOD::isPlaying()
622{ 619{
623 if (!mChannelID) 620 if (!mChannelID)
624 { 621 {
625 return FALSE; 622 return false;
626 } 623 }
627 624
628 return FSOUND_IsPlaying(mChannelID) && (!FSOUND_GetPaused(mChannelID)); 625 return FSOUND_IsPlaying(mChannelID) && (!FSOUND_GetPaused(mChannelID));
@@ -652,14 +649,14 @@ LLAudioBufferFMOD::~LLAudioBufferFMOD()
652} 649}
653 650
654 651
655BOOL LLAudioBufferFMOD::loadWAV(const std::string& filename) 652bool LLAudioBufferFMOD::loadWAV(const std::string& filename)
656{ 653{
657 // Try to open a wav file from disk. This will eventually go away, as we don't 654 // Try to open a wav file from disk. This will eventually go away, as we don't
658 // really want to block doing this. 655 // really want to block doing this.
659 if (filename.empty()) 656 if (filename.empty())
660 { 657 {
661 // invalid filename, abort. 658 // invalid filename, abort.
662 return FALSE; 659 return false;
663 } 660 }
664 661
665 S32 file_size = 0; 662 S32 file_size = 0;
@@ -667,7 +664,7 @@ BOOL LLAudioBufferFMOD::loadWAV(const std::string& filename)
667 if (!apr_file) 664 if (!apr_file)
668 { 665 {
669 // File not found, abort. 666 // File not found, abort.
670 return FALSE; 667 return false;
671 } 668 }
672 apr_file_close(apr_file); 669 apr_file_close(apr_file);
673 670
@@ -717,11 +714,11 @@ BOOL LLAudioBufferFMOD::loadWAV(const std::string& filename)
717 // 714 //
718 // file is probably corrupt - remove it. 715 // file is probably corrupt - remove it.
719 LLFile::remove(filename); 716 LLFile::remove(filename);
720 return FALSE; 717 return false;
721 } 718 }
722 719
723 // Everything went well, return TRUE 720 // Everything went well, return true
724 return TRUE; 721 return true;
725} 722}
726 723
727 724
@@ -736,7 +733,7 @@ U32 LLAudioBufferFMOD::getLength()
736} 733}
737 734
738 735
739void LLAudioBufferFMOD::set3DMode(BOOL use3d) 736void LLAudioBufferFMOD::set3DMode(bool use3d)
740{ 737{
741 U16 current_mode = FSOUND_Sample_GetMode(mSamplep); 738 U16 current_mode = FSOUND_Sample_GetMode(mSamplep);
742 739
@@ -765,7 +762,7 @@ void LLAudioEngine_FMOD::initInternetStream()
765{ 762{
766 // Number of milliseconds of audio to buffer for the audio card. 763 // Number of milliseconds of audio to buffer for the audio card.
767 // Must be larger than the usual Second Life frame stutter time. 764 // Must be larger than the usual Second Life frame stutter time.
768 FSOUND_Stream_SetBufferSize(200); 765 FSOUND_Stream_SetBufferSize(200);
769 766
770 // Here's where we set the size of the network buffer and some buffering 767 // 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 768 // parameters. In this case we want a network buffer of 16k, we want it
@@ -810,19 +807,19 @@ signed char F_CALLBACKAPI LLAudioEngine_FMOD::callbackMetaData(char *name, char
810 if (!strcmp("ARTIST", name)) 807 if (!strcmp("ARTIST", name))
811 { 808 {
812 strlcpy(self->mInternetStreamArtist, value, 256); 809 strlcpy(self->mInternetStreamArtist, value, 256);
813 self->mInternetStreamNewMetaData = TRUE; 810 self->mInternetStreamNewMetaData = true;
814 return TRUE; 811 return true;
815 } 812 }
816 813
817 if (!strcmp("TITLE", name)) 814 if (!strcmp("TITLE", name))
818 { 815 {
819 strlcpy(self->mInternetStreamTitle, value, 256); 816 strlcpy(self->mInternetStreamTitle, value, 256);
820 self->mInternetStreamNewMetaData = TRUE; 817 self->mInternetStreamNewMetaData = true;
821 return TRUE; 818 return true;
822 } 819 }
823 */ 820 */
824 821
825 return TRUE; 822 return true;
826} 823}
827 824
828 825
@@ -867,7 +864,7 @@ void LLAudioEngine_FMOD::updateInternetStream()
867 { 864 {
868 // Reset volume to previously set volume 865 // Reset volume to previously set volume
869 setInternetStreamGain(mInternetStreamGain); 866 setInternetStreamGain(mInternetStreamGain);
870 FSOUND_SetPaused(mInternetStreamChannel, FALSE); 867 FSOUND_SetPaused(mInternetStreamChannel, false);
871 //FSOUND_Stream_Net_SetMetadataCallback(mInternetStream, callbackMetaData, this); 868 //FSOUND_Stream_Net_SetMetadataCallback(mInternetStream, callbackMetaData, this);
872 } 869 }
873 } 870 }
@@ -909,7 +906,7 @@ void LLAudioEngine_FMOD::stopInternetStream()
909{ 906{
910 if (mInternetStreamChannel != -1) 907 if (mInternetStreamChannel != -1)
911 { 908 {
912 FSOUND_SetPaused(mInternetStreamChannel, TRUE); 909 FSOUND_SetPaused(mInternetStreamChannel, true);
913 FSOUND_SetPriority(mInternetStreamChannel, 0); 910 FSOUND_SetPriority(mInternetStreamChannel, 0);
914 mInternetStreamChannel = -1; 911 mInternetStreamChannel = -1;
915 } 912 }
@@ -971,16 +968,10 @@ int LLAudioEngine_FMOD::isInternetStreamPlaying()
971} 968}
972 969
973 970
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) 971void LLAudioEngine_FMOD::setInternetStreamGain(F32 vol)
982{ 972{
983 LLAudioEngine::setInternetStreamGain(vol); 973 mInternetStreamGain = vol;
974
984 if (mInternetStreamChannel != -1) 975 if (mInternetStreamChannel != -1)
985 { 976 {
986 vol = llclamp(vol, 0.f, 1.f); 977 vol = llclamp(vol, 0.f, 1.f);
@@ -990,15 +981,9 @@ void LLAudioEngine_FMOD::setInternetStreamGain(F32 vol)
990} 981}
991 982
992 983
993const std::string& LLAudioEngine_FMOD::getInternetStreamURL()
994{
995 return mInternetStreamURL;
996}
997
998
999LLAudioStreamFMOD::LLAudioStreamFMOD(const std::string& url) : 984LLAudioStreamFMOD::LLAudioStreamFMOD(const std::string& url) :
1000 mInternetStream(NULL), 985 mInternetStream(NULL),
1001 mReady(FALSE) 986 mReady(false)
1002{ 987{
1003 mInternetStreamURL = url; 988 mInternetStreamURL = url;
1004 mInternetStream = FSOUND_Stream_Open(url.c_str(), FSOUND_NORMAL | FSOUND_NONBLOCKING, 0, 0); 989 mInternetStream = FSOUND_Stream_Open(url.c_str(), FSOUND_NORMAL | FSOUND_NONBLOCKING, 0, 0);
@@ -1007,11 +992,11 @@ LLAudioStreamFMOD::LLAudioStreamFMOD(const std::string& url) :
1007 llwarns << "Couldn't open fmod stream, error " 992 llwarns << "Couldn't open fmod stream, error "
1008 << FMOD_ErrorString(FSOUND_GetError()) 993 << FMOD_ErrorString(FSOUND_GetError())
1009 << llendl; 994 << llendl;
1010 mReady = FALSE; 995 mReady = false;
1011 return; 996 return;
1012 } 997 }
1013 998
1014 mReady = TRUE; 999 mReady = true;
1015} 1000}
1016 1001
1017int LLAudioStreamFMOD::startStream() 1002int LLAudioStreamFMOD::startStream()
@@ -1026,10 +1011,10 @@ int LLAudioStreamFMOD::startStream()
1026 // Make sure the stream is set to 2D mode. 1011 // Make sure the stream is set to 2D mode.
1027 FSOUND_Stream_SetMode(mInternetStream, FSOUND_2D); 1012 FSOUND_Stream_SetMode(mInternetStream, FSOUND_2D);
1028 1013
1029 return FSOUND_Stream_PlayEx(FSOUND_FREE, mInternetStream, NULL, TRUE); 1014 return FSOUND_Stream_PlayEx(FSOUND_FREE, mInternetStream, NULL, true);
1030} 1015}
1031 1016
1032BOOL LLAudioStreamFMOD::stopStream() 1017bool LLAudioStreamFMOD::stopStream()
1033{ 1018{
1034 if (mInternetStream) 1019 if (mInternetStream)
1035 { 1020 {
@@ -1039,34 +1024,34 @@ BOOL LLAudioStreamFMOD::stopStream()
1039 unsigned int flags = 0x0; 1024 unsigned int flags = 0x0;
1040 FSOUND_Stream_Net_GetStatus(mInternetStream, &status, &read_percent, &bitrate, &flags); 1025 FSOUND_Stream_Net_GetStatus(mInternetStream, &status, &read_percent, &bitrate, &flags);
1041 1026
1042 BOOL close = TRUE; 1027 bool close = true;
1043 switch (status) 1028 switch (status)
1044 { 1029 {
1045 case FSOUND_STREAM_NET_CONNECTING: 1030 case FSOUND_STREAM_NET_CONNECTING:
1046 close = FALSE; 1031 close = false;
1047 break; 1032 break;
1048 case FSOUND_STREAM_NET_NOTCONNECTED: 1033 case FSOUND_STREAM_NET_NOTCONNECTED:
1049 case FSOUND_STREAM_NET_BUFFERING: 1034 case FSOUND_STREAM_NET_BUFFERING:
1050 case FSOUND_STREAM_NET_READY: 1035 case FSOUND_STREAM_NET_READY:
1051 case FSOUND_STREAM_NET_ERROR: 1036 case FSOUND_STREAM_NET_ERROR:
1052 default: 1037 default:
1053 close = TRUE; 1038 close = true;
1054 } 1039 }
1055 1040
1056 if (close) 1041 if (close)
1057 { 1042 {
1058 FSOUND_Stream_Close(mInternetStream); 1043 FSOUND_Stream_Close(mInternetStream);
1059 mInternetStream = NULL; 1044 mInternetStream = NULL;
1060 return TRUE; 1045 return true;
1061 } 1046 }
1062 else 1047 else
1063 { 1048 {
1064 return FALSE; 1049 return false;
1065 } 1050 }
1066 } 1051 }
1067 else 1052 else
1068 { 1053 {
1069 return TRUE; 1054 return true;
1070 } 1055 }
1071} 1056}
1072 1057
@@ -1076,94 +1061,35 @@ int LLAudioStreamFMOD::getOpenState()
1076 return open_state; 1061 return open_state;
1077} 1062}
1078 1063
1079/* This determines the format of the mixbuffer being passed in. change if you want to support int32 or float32 */ 1064void * 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{ 1065{
1098// originalbuffer = fsounds original mixbuffer. 1066 // originalbuffer = fmod's original mixbuffer.
1099// newbuffer = the buffer passed from the previous DSP unit. 1067 // newbuffer = the buffer passed from the previous DSP unit.
1100// length = length in samples at this mix time. 1068 // length = length in samples at this mix time.
1101// param = user parameter passed through in FSOUND_DSP_Create. 1069 // param = user parameter passed through in FSOUND_DSP_Create.
1102// 1070 //
1103// modify the buffer in some fashion 1071 // modify the buffer in some fashion
1104 1072
1105 U8 *cursamplep = (U8*)newbuffer; 1073 LLWindGen<LLAudioEngine_FMOD::MIXBUFFERFORMAT> *windgen =
1106 U8 wordsize = 2; 1074 (LLWindGen<LLAudioEngine_FMOD::MIXBUFFERFORMAT> *)userdata;
1075 U8 stride;
1107 1076
1108#if LL_DARWIN 1077#if LL_DARWIN
1109 wordsize = sizeof(MIXBUFFERFORMAT); 1078 stride = sizeof(LLAudioEngine_FMOD::MIXBUFFERFORMAT);
1110#else 1079#else
1111 int mixertype = FSOUND_GetMixer(); 1080 int mixertype = FSOUND_GetMixer();
1112 if (mixertype == FSOUND_MIXER_BLENDMODE || mixertype == FSOUND_MIXER_QUALITY_FPU) 1081 if (mixertype == FSOUND_MIXER_BLENDMODE ||
1113 { 1082 mixertype == FSOUND_MIXER_QUALITY_FPU)
1114 wordsize = 4; 1083 {
1115 } 1084 stride = 4;
1116#endif 1085 }
1117 1086 else
1118 double bandwidth = 50; 1087 {
1119 double inputSamplingRate = 44100; 1088 stride = 2;
1120 double a0,b1,b2; 1089 }
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 1090#endif
1154 1091
1155 nextSample *= gCurrentGain; 1092 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 1093
1168 return newbuffer; 1094 return newbuffer;
1169} 1095}
diff --git a/linden/indra/llaudio/audioengine_fmod.h b/linden/indra/llaudio/audioengine_fmod.h
index 444d754..4d2cbce 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,12 @@ 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);
52 virtual std::string getDriverName(bool verbose);
51 virtual void allocateListener(); 53 virtual void allocateListener();
52 54
53 virtual void shutdown(); 55 virtual void shutdown();
54 56
55 virtual void idle(F32 max_decode_time = 0.f);
56
57 // Internet stream methods 57 // Internet stream methods
58 virtual void initInternetStream(); 58 virtual void initInternetStream();
59 virtual void startInternetStream(const std::string& url); 59 virtual void startInternetStream(const std::string& url);
@@ -61,15 +61,19 @@ public:
61 virtual void stopInternetStream(); 61 virtual void stopInternetStream();
62 virtual void pauseInternetStream(int pause); 62 virtual void pauseInternetStream(int pause);
63 virtual int isInternetStreamPlaying(); 63 virtual int isInternetStreamPlaying();
64 virtual void getInternetStreamInfo(char* artist, char* title);
65 virtual void setInternetStreamGain(F32 vol); 64 virtual void setInternetStreamGain(F32 vol);
66 virtual const std::string& getInternetStreamURL();
67 65
68 /*virtual*/ void initWind(); 66 /*virtual*/ void initWind();
69 /*virtual*/ void cleanupWind(); 67 /*virtual*/ void cleanupWind();
70 68
71 /*virtual*/void updateWind(LLVector3 direction, F32 camera_height_above_water); 69 /*virtual*/void updateWind(LLVector3 direction, F32 camera_height_above_water);
72 70
71#if LL_DARWIN
72 typedef S32 MIXBUFFERFORMAT;
73#else
74 typedef S16 MIXBUFFERFORMAT;
75#endif
76
73protected: 77protected:
74 /*virtual*/ LLAudioBuffer *createBuffer(); // Get a free buffer, or flush an existing one if you have to. 78 /*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. 79 /*virtual*/ LLAudioChannel *createChannel(); // Create a new audio channel.
@@ -79,7 +83,6 @@ protected:
79 static signed char F_CALLBACKAPI callbackMetaData(char* name, char* value, void* userdata); 83 static signed char F_CALLBACKAPI callbackMetaData(char* name, char* value, void* userdata);
80 84
81 LLAudioStreamFMOD *mCurrentInternetStreamp; 85 LLAudioStreamFMOD *mCurrentInternetStreamp;
82 std::string mInternetStreamURL;
83 int mInternetStreamChannel; 86 int mInternetStreamChannel;
84 87
85 std::list<LLAudioStreamFMOD *> mDeadStreams; 88 std::list<LLAudioStreamFMOD *> mDeadStreams;
@@ -88,11 +91,12 @@ protected:
88 //F32 mMaxDistance[MAX_BUFFERS]; 91 //F32 mMaxDistance[MAX_BUFFERS];
89 92
90 S32 mFadeIn; 93 S32 mFadeIn;
91 BOOL mInited; 94 bool mInited;
92 95
93 // On Windows, userdata is the HWND of the application window. 96 // On Windows, userdata is the HWND of the application window.
94 void* mUserData; 97 void* mUserData;
95 98
99 LLWindGen<MIXBUFFERFORMAT> *mWindGen;
96}; 100};
97 101
98 102
@@ -106,9 +110,9 @@ protected:
106 /*virtual*/ void play(); 110 /*virtual*/ void play();
107 /*virtual*/ void playSynced(LLAudioChannel *channelp); 111 /*virtual*/ void playSynced(LLAudioChannel *channelp);
108 /*virtual*/ void cleanup(); 112 /*virtual*/ void cleanup();
109 /*virtual*/ BOOL isPlaying(); 113 /*virtual*/ bool isPlaying();
110 114
111 /*virtual*/ BOOL updateBuffer(); 115 /*virtual*/ bool updateBuffer();
112 /*virtual*/ void update3DPosition(); 116 /*virtual*/ void update3DPosition();
113 /*virtual*/ void updateLoop(); 117 /*virtual*/ void updateLoop();
114 118
@@ -124,11 +128,11 @@ public:
124 LLAudioBufferFMOD(); 128 LLAudioBufferFMOD();
125 virtual ~LLAudioBufferFMOD(); 129 virtual ~LLAudioBufferFMOD();
126 130
127 /*virtual*/ BOOL loadWAV(const std::string& filename); 131 /*virtual*/ bool loadWAV(const std::string& filename);
128 /*virtual*/ U32 getLength(); 132 /*virtual*/ U32 getLength();
129 friend class LLAudioChannelFMOD; 133 friend class LLAudioChannelFMOD;
130 134
131 void set3DMode(BOOL use3d); 135 void set3DMode(bool use3d);
132protected: 136protected:
133 FSOUND_SAMPLE *getSample() { return mSamplep; } 137 FSOUND_SAMPLE *getSample() { return mSamplep; }
134protected: 138protected:
@@ -140,15 +144,15 @@ class LLAudioStreamFMOD
140public: 144public:
141 LLAudioStreamFMOD(const std::string& url); 145 LLAudioStreamFMOD(const std::string& url);
142 int startStream(); 146 int startStream();
143 BOOL stopStream(); // Returns true if the stream was successfully stopped. 147 bool stopStream(); // Returns true if the stream was successfully stopped.
144 BOOL ready(); 148 bool ready();
145 149
146 const std::string& getURL() { return mInternetStreamURL; } 150 const std::string& getURL() { return mInternetStreamURL; }
147 151
148 int getOpenState(); 152 int getOpenState();
149protected: 153protected:
150 FSOUND_STREAM* mInternetStream; 154 FSOUND_STREAM* mInternetStream;
151 BOOL mReady; 155 bool mReady;
152 156
153 std::string mInternetStreamURL; 157 std::string mInternetStreamURL;
154}; 158};
diff --git a/linden/indra/llaudio/audioengine_openal.cpp b/linden/indra/llaudio/audioengine_openal.cpp
new file mode 100644
index 0000000..b33e0b0
--- /dev/null
+++ b/linden/indra/llaudio/audioengine_openal.cpp
@@ -0,0 +1,547 @@
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-2009, 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 alSourcei (mALSource, AL_SOURCE_RELATIVE, AL_TRUE);
303 } else {
304 LLVector3 float_pos;
305 float_pos.setVec(mCurrentSourcep->getPositionGlobal());
306 alSourcefv(mALSource, AL_POSITION, float_pos.mV);
307 alSourcefv(mALSource, AL_VELOCITY, mCurrentSourcep->getVelocity().mV);
308 alSourcei (mALSource, AL_SOURCE_RELATIVE, AL_FALSE);
309 }
310
311 alSourcef(mALSource, AL_GAIN, mCurrentSourcep->getGain() * getSecondaryGain());
312}
313
314LLAudioBufferOpenAL::LLAudioBufferOpenAL()
315{
316 mALBuffer = AL_NONE;
317}
318
319LLAudioBufferOpenAL::~LLAudioBufferOpenAL()
320{
321 cleanup();
322}
323
324void LLAudioBufferOpenAL::cleanup()
325{
326 if(mALBuffer != AL_NONE)
327 {
328 alDeleteBuffers(1, &mALBuffer);
329 mALBuffer = AL_NONE;
330 }
331}
332
333bool LLAudioBufferOpenAL::loadWAV(const std::string& filename)
334{
335 cleanup();
336 mALBuffer = alutCreateBufferFromFile(filename.c_str());
337 if(mALBuffer == AL_NONE)
338 {
339 ALenum error = alutGetError();
340 if (gDirUtilp->fileExists(filename))
341 {
342 llwarns <<
343 "LLAudioBufferOpenAL::loadWAV() Error loading "
344 << filename
345 << " " << alutGetErrorString(error) << llendl;
346 }
347 else
348 {
349 // It's common for the file to not actually exist.
350 lldebugs <<
351 "LLAudioBufferOpenAL::loadWAV() Error loading "
352 << filename
353 << " " << alutGetErrorString(error) << llendl;
354 }
355 return false;
356 }
357
358 return true;
359}
360
361U32 LLAudioBufferOpenAL::getLength()
362{
363 if(mALBuffer == AL_NONE)
364 {
365 return 0;
366 }
367 ALint length;
368 alGetBufferi(mALBuffer, AL_SIZE, &length);
369 return length / 2; // convert size in bytes to size in (16-bit) samples
370}
371
372// ------------
373
374void LLAudioEngine_OpenAL::initWind()
375{
376 ALenum error;
377 llinfos << "LLAudioEngine_OpenAL::initWind() start" << llendl;
378
379 mNumEmptyWindALBuffers = MAX_NUM_WIND_BUFFERS;
380
381 alGetError(); /* clear error */
382
383 alGenSources(1,&mWindSource);
384
385 if((error=alGetError()) != AL_NO_ERROR)
386 {
387 llwarns << "LLAudioEngine_OpenAL::initWind() Error creating wind sources: "<<error<<llendl;
388 }
389
390 mWindGen = new LLWindGen<WIND_SAMPLE_T>;
391
392 mWindBufFreq = mWindGen->getInputSamplingRate();
393 mWindBufSamples = llceil(mWindBufFreq * WIND_BUFFER_SIZE_SEC);
394 mWindBufBytes = mWindBufSamples * 2 /*stereo*/ * sizeof(WIND_SAMPLE_T);
395
396 mWindBuf = new WIND_SAMPLE_T [mWindBufSamples * 2 /*stereo*/];
397
398 if(mWindBuf==NULL)
399 {
400 llerrs << "LLAudioEngine_OpenAL::initWind() Error creating wind memory buffer" << llendl;
401 mEnableWind=false;
402 }
403
404 llinfos << "LLAudioEngine_OpenAL::initWind() done" << llendl;
405}
406
407void LLAudioEngine_OpenAL::cleanupWind()
408{
409 llinfos << "LLAudioEngine_OpenAL::cleanupWind()" << llendl;
410
411 if (mWindSource != AL_NONE)
412 {
413 // detach and delete all outstanding buffers on the wind source
414 alSourceStop(mWindSource);
415 ALint processed;
416 alGetSourcei(mWindSource, AL_BUFFERS_PROCESSED, &processed);
417 while (processed--)
418 {
419 ALuint buffer = AL_NONE;
420 alSourceUnqueueBuffers(mWindSource, 1, &buffer);
421 alDeleteBuffers(1, &buffer);
422 }
423
424 // delete the wind source itself
425 alDeleteSources(1, &mWindSource);
426
427 mWindSource = AL_NONE;
428 }
429
430 delete[] mWindBuf;
431 mWindBuf = NULL;
432
433 delete mWindGen;
434 mWindGen = NULL;
435}
436
437void LLAudioEngine_OpenAL::updateWind(LLVector3 wind_vec, F32 camera_altitude)
438{
439 LLVector3 wind_pos;
440 F64 pitch;
441 F64 center_freq;
442 ALenum error;
443
444 if (!mEnableWind)
445 return;
446
447 if(!mWindBuf)
448 return;
449
450 if (mWindUpdateTimer.checkExpirationAndReset(LL_WIND_UPDATE_INTERVAL))
451 {
452
453 // wind comes in as Linden coordinate (+X = forward, +Y = left, +Z = up)
454 // need to convert this to the conventional orientation DS3D and OpenAL use
455 // where +X = right, +Y = up, +Z = backwards
456
457 wind_vec.setVec(-wind_vec.mV[1], wind_vec.mV[2], -wind_vec.mV[0]);
458
459 pitch = 1.0 + mapWindVecToPitch(wind_vec);
460 center_freq = 80.0 * pow(pitch,2.5*(mapWindVecToGain(wind_vec)+1.0));
461
462 mWindGen->mTargetFreq = (F32)center_freq;
463 mWindGen->mTargetGain = (F32)mapWindVecToGain(wind_vec) * mMaxWindGain;
464 mWindGen->mTargetPanGainR = (F32)mapWindVecToPan(wind_vec);
465
466 alSourcei(mWindSource, AL_LOOPING, AL_FALSE);
467 alSource3f(mWindSource, AL_POSITION, 0.0, 0.0, 0.0);
468 alSource3f(mWindSource, AL_VELOCITY, 0.0, 0.0, 0.0);
469 alSourcef(mWindSource, AL_ROLLOFF_FACTOR, 0.0);
470 alSourcei(mWindSource, AL_SOURCE_RELATIVE, AL_TRUE);
471 }
472
473 // ok lets make a wind buffer now
474
475 ALint processed, queued, unprocessed;
476 alGetSourcei(mWindSource, AL_BUFFERS_PROCESSED, &processed);
477 alGetSourcei(mWindSource, AL_BUFFERS_QUEUED, &queued);
478 unprocessed = queued - processed;
479
480 // ensure that there are always at least 3x as many filled buffers
481 // queued as we managed to empty since last time.
482 mNumEmptyWindALBuffers = llmin(mNumEmptyWindALBuffers + processed * 3 - unprocessed, MAX_NUM_WIND_BUFFERS-unprocessed);
483 mNumEmptyWindALBuffers = llmax(mNumEmptyWindALBuffers, 0);
484
485 //llinfos << "mNumEmptyWindALBuffers: " << mNumEmptyWindALBuffers <<" (" << unprocessed << ":" << processed << ")" << llendl;
486
487 while(processed--) // unqueue old buffers
488 {
489 ALuint buffer;
490 ALenum error;
491 alGetError(); /* clear error */
492 alSourceUnqueueBuffers(mWindSource, 1, &buffer);
493 error = alGetError();
494 if(error != AL_NO_ERROR)
495 {
496 llwarns << "LLAudioEngine_OpenAL::updateWind() error swapping (unqueuing) buffers" << llendl;
497 }
498 else
499 {
500 alDeleteBuffers(1, &buffer);
501 }
502 }
503
504 unprocessed += mNumEmptyWindALBuffers;
505 while (mNumEmptyWindALBuffers > 0) // fill+queue new buffers
506 {
507 ALuint buffer;
508 alGetError(); /* clear error */
509 alGenBuffers(1,&buffer);
510 if((error=alGetError()) != AL_NO_ERROR)
511 {
512 llwarns << "LLAudioEngine_OpenAL::initWind() Error creating wind buffer: " << error << llendl;
513 break;
514 }
515
516 alBufferData(buffer,
517 AL_FORMAT_STEREO16,
518 mWindGen->windGenerate(mWindBuf,
519 mWindBufSamples, 2),
520 mWindBufBytes,
521 mWindBufFreq);
522 error = alGetError();
523 if(error != AL_NO_ERROR)
524 {
525 llwarns << "LLAudioEngine_OpenAL::updateWind() error swapping (bufferdata) buffers" << llendl;
526 }
527
528 alSourceQueueBuffers(mWindSource, 1, &buffer);
529 error = alGetError();
530 if(error != AL_NO_ERROR)
531 {
532 llwarns << "LLAudioEngine_OpenAL::updateWind() error swapping (queuing) buffers" << llendl;
533 }
534
535 --mNumEmptyWindALBuffers;
536 }
537
538 ALint playing;
539 alGetSourcei(mWindSource, AL_SOURCE_STATE, &playing);
540 if(playing != AL_PLAYING)
541 {
542 alSourcePlay(mWindSource);
543
544 lldebugs << "Wind had stopped - probably ran out of buffers - restarting: " << (unprocessed+mNumEmptyWindALBuffers) << " now queued." << llendl;
545 }
546}
547
diff --git a/linden/indra/llaudio/audioengine_openal.h b/linden/indra/llaudio/audioengine_openal.h
new file mode 100644
index 0000000..54b60e6
--- /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-2009, 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 2c773ef..6ac8f20 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..718de63
--- /dev/null
+++ b/linden/indra/llaudio/listener_openal.cpp
@@ -0,0 +1,125 @@
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-2009, 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 "audioengine.h"
35
36#include "listener_openal.h"
37
38LLListener_OpenAL::LLListener_OpenAL()
39{
40 init();
41}
42
43LLListener_OpenAL::~LLListener_OpenAL()
44{
45}
46
47void LLListener_OpenAL::translate(LLVector3 offset)
48{
49 //llinfos << "LLListener_OpenAL::translate() : " << offset << llendl;
50 LLListener::translate(offset);
51}
52
53void LLListener_OpenAL::setPosition(LLVector3 pos)
54{
55 //llinfos << "LLListener_OpenAL::setPosition() : " << pos << llendl;
56 LLListener::setPosition(pos);
57}
58
59void LLListener_OpenAL::setVelocity(LLVector3 vel)
60{
61 LLListener::setVelocity(vel);
62}
63
64void LLListener_OpenAL::orient(LLVector3 up, LLVector3 at)
65{
66 //llinfos << "LLListener_OpenAL::orient() up: " << up << " at: " << at << llendl;
67 LLListener::orient(up, at);
68}
69
70void LLListener_OpenAL::commitDeferredChanges()
71{
72 ALfloat orientation[6];
73 orientation[0] = mListenAt.mV[0];
74 orientation[1] = mListenAt.mV[1];
75 orientation[2] = mListenAt.mV[2];
76 orientation[3] = mListenUp.mV[0];
77 orientation[4] = mListenUp.mV[1];
78 orientation[5] = mListenUp.mV[2];
79
80 ALfloat velocity[3];
81 velocity[0] = mVelocity.mV[0];
82 velocity[1] = mVelocity.mV[1];
83 velocity[2] = mVelocity.mV[2];
84
85 alListenerfv(AL_ORIENTATION, orientation);
86 alListenerfv(AL_POSITION, mPosition.mV);
87 alListenerfv(AL_VELOCITY, velocity);
88}
89
90void LLListener_OpenAL::setDopplerFactor(F32 factor)
91{
92 //llinfos << "LLListener_OpenAL::setDopplerFactor() : " << factor << llendl;
93 alDopplerFactor(factor);
94}
95
96F32 LLListener_OpenAL::getDopplerFactor()
97{
98 ALfloat factor;
99 factor = alGetFloat(AL_DOPPLER_FACTOR);
100 //llinfos << "LLListener_OpenAL::getDopplerFactor() : " << factor << llendl;
101 return factor;
102}
103
104
105void LLListener_OpenAL::setRolloffFactor(F32 factor)
106{
107 mRolloffFactor = factor;
108}
109
110F32 LLListener_OpenAL::getRolloffFactor()
111{
112 return mRolloffFactor;
113}
114
115
116void LLListener_OpenAL::setDistanceFactor(F32 factor)
117{
118 mDistanceFactor = factor;
119}
120
121F32 LLListener_OpenAL::getDistanceFactor()
122{
123 return mDistanceFactor;
124}
125
diff --git a/linden/indra/llaudio/listener_openal.h b/linden/indra/llaudio/listener_openal.h
index e6c9324..3e4353f 100644
--- a/linden/indra/llaudio/listener_openal.h
+++ b/linden/indra/llaudio/listener_openal.h
@@ -40,12 +40,6 @@
40 40
41class LLListener_OpenAL : public LLListener 41class LLListener_OpenAL : public LLListener
42{ 42{
43 private:
44 protected:
45 public:
46
47 private:
48 protected:
49 public: 43 public:
50 LLListener_OpenAL(); 44 LLListener_OpenAL();
51 virtual ~LLListener_OpenAL(); 45 virtual ~LLListener_OpenAL();
@@ -54,6 +48,18 @@ class LLListener_OpenAL : public LLListener
54 virtual void setPosition(LLVector3 pos); 48 virtual void setPosition(LLVector3 pos);
55 virtual void setVelocity(LLVector3 vel); 49 virtual void setVelocity(LLVector3 vel);
56 virtual void orient(LLVector3 up, LLVector3 at); 50 virtual void orient(LLVector3 up, LLVector3 at);
51 virtual void commitDeferredChanges();
52
53 virtual void setDopplerFactor(F32 factor);
54 virtual F32 getDopplerFactor();
55 virtual void setDistanceFactor(F32 factor);
56 virtual F32 getDistanceFactor();
57 virtual void setRolloffFactor(F32 factor);
58 virtual F32 getRolloffFactor();
59
60 protected:
61 F32 mDistanceFactor;
62 F32 mRolloffFactor;
57}; 63};
58 64
59#endif 65#endif
diff --git a/linden/indra/llaudio/windgen.h b/linden/indra/llaudio/windgen.h
new file mode 100644
index 0000000..faffd3c
--- /dev/null
+++ b/linden/indra/llaudio/windgen.h
@@ -0,0 +1,135 @@
1/**
2 * @file windgen.h
3 * @brief Templated wind noise generation
4 *
5 * $LicenseInfo:firstyear=2002&license=viewergpl$
6 *
7 * Copyright (c) 2002-2009, 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://secondlifegrid.net/programs/open_source/licensing/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://secondlifegrid.net/programs/open_source/licensing/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 // 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
95 // do a resonant filter on the noise
96 nextSample = (double)( a0 * nextSample - b1 * mY0 - b2 * mY1 );
97 mY1 = mY0;
98 mY0 = nextSample;
99
100 nextSample *= mCurrentGain;
101
102 MIXBUFFERFORMAT_T sample;
103
104 sample = llfloor(((F32)nextSample*32768.f*(1.0f - mCurrentPanGainR))+0.5f);
105 *(MIXBUFFERFORMAT_T*)cursamplep = llclamp(sample, (MIXBUFFERFORMAT_T)-32768, (MIXBUFFERFORMAT_T)32767);
106 cursamplep += stride;
107
108 sample = llfloor(((F32)nextSample*32768.f*mCurrentPanGainR)+0.5f);
109 *(MIXBUFFERFORMAT_T*)cursamplep = llclamp(sample, (MIXBUFFERFORMAT_T)-32768, (MIXBUFFERFORMAT_T)32767);
110 cursamplep += stride;
111 }
112
113 return newbuffer;
114 }
115
116 F32 mTargetGain;
117 F32 mTargetFreq;
118 F32 mTargetPanGainR;
119
120private:
121 static const U32 mInputSamplingRate = 44100;
122 F64 mbuf0;
123 F64 mbuf1;
124 F64 mbuf2;
125 F64 mbuf3;
126 F64 mbuf4;
127 F64 mbuf5;
128 F64 mY0;
129 F64 mY1;
130 F32 mCurrentGain;
131 F32 mCurrentFreq;
132 F32 mCurrentPanGainR;
133};
134
135#endif