aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llaudio
diff options
context:
space:
mode:
Diffstat (limited to 'linden/indra/llaudio')
-rw-r--r--linden/indra/llaudio/audioengine.cpp198
-rw-r--r--linden/indra/llaudio/audioengine.h75
-rw-r--r--linden/indra/llaudio/audioengine_openal.cpp689
-rw-r--r--linden/indra/llaudio/audioengine_openal.h62
-rw-r--r--linden/indra/llaudio/listener_openal.cpp8
-rw-r--r--linden/indra/llaudio/listener_openal.h13
-rw-r--r--linden/indra/llaudio/llaudiodecodemgr.cpp23
7 files changed, 689 insertions, 379 deletions
diff --git a/linden/indra/llaudio/audioengine.cpp b/linden/indra/llaudio/audioengine.cpp
index 0a450e9..5fb38c0 100644
--- a/linden/indra/llaudio/audioengine.cpp
+++ b/linden/indra/llaudio/audioengine.cpp
@@ -51,6 +51,9 @@ extern void request_sound(const LLUUID &sound_guid);
51 51
52LLAudioEngine* gAudiop = NULL; 52LLAudioEngine* gAudiop = NULL;
53 53
54// Maximum amount of time we wait for a transfer to complete before starting
55// off another one.
56const F32 MAX_CURRENT_TRANSFER_TIME = 60.f;
54 57
55// 58//
56// LLAudioEngine implementation 59// LLAudioEngine implementation
@@ -74,8 +77,7 @@ void LLAudioEngine::setDefaults()
74 77
75 mListenerp = NULL; 78 mListenerp = NULL;
76 79
77 mMuted = false; 80 mMuted = FALSE;
78 mUserData = NULL;
79 81
80 mLastStatus = 0; 82 mLastStatus = 0;
81 83
@@ -96,17 +98,16 @@ void LLAudioEngine::setDefaults()
96 mInternetStreamGain = 0.125f; 98 mInternetStreamGain = 0.125f;
97 mNextWindUpdate = 0.f; 99 mNextWindUpdate = 0.f;
98 100
99 mInternetStreamMedia = NULL; 101 for (U32 i = 0; i < LLAudioEngine::AUDIO_TYPE_COUNT; i++)
100 mInternetStreamURL.clear(); 102 mSecondaryGain[i] = 1.0f;
101} 103}
102 104
103 105
104bool LLAudioEngine::init(const S32 num_channels, void* userdata) 106BOOL LLAudioEngine::init(const S32 num_channels)
105{ 107{
106 setDefaults(); 108 setDefaults();
107 109
108 mNumChannels = num_channels; 110 mNumChannels = num_channels;
109 mUserData = userdata;
110 111
111 allocateListener(); 112 allocateListener();
112 113
@@ -145,146 +146,22 @@ void LLAudioEngine::shutdown()
145 S32 i; 146 S32 i;
146 for (i = 0; i < MAX_CHANNELS; i++) 147 for (i = 0; i < MAX_CHANNELS; i++)
147 { 148 {
148 delete mChannels[i]; 149 if (mChannels[i])
149 mChannels[i] = NULL; 150 {
151 delete mChannels[i];
152 mChannels[i] = NULL;
153 }
150 } 154 }
151 155
152 // Clean up buffers 156 // Clean up buffers
153 for (i = 0; i < MAX_BUFFERS; i++) 157 for (i = 0; i < MAX_BUFFERS; i++)
154 { 158 {
155 delete mBuffers[i]; 159 if (mBuffers[i])
156 mBuffers[i] = NULL;
157 }
158
159 delete mInternetStreamMedia;
160 mInternetStreamMedia = NULL;
161 mInternetStreamURL.clear();
162}
163
164
165// virtual
166void LLAudioEngine::startInternetStream(const std::string& url)
167{
168 llinfos << "entered startInternetStream()" << llendl;
169
170 if (!mInternetStreamMedia)
171 {
172 LLMediaManager* mgr = LLMediaManager::getInstance();
173 if (mgr)
174 { 160 {
175 mInternetStreamMedia = mgr->createSourceFromMimeType(LLURI(url).scheme(), "audio/mpeg"); // assumes that whatever media implementation supports mp3 also supports vorbis. 161 delete mBuffers[i];
176 llinfos << "mInternetStreamMedia is now " << mInternetStreamMedia << llendl; 162 mBuffers[i] = NULL;
177 }
178 }
179
180 if(!mInternetStreamMedia)
181 return;
182
183 if (!url.empty()) {
184 llinfos << "Starting internet stream: " << url << llendl;
185 mInternetStreamURL = url;
186 mInternetStreamMedia->navigateTo ( url );
187 llinfos << "Playing....." << llendl;
188 mInternetStreamMedia->addCommand(LLMediaBase::COMMAND_START);
189 mInternetStreamMedia->updateMedia();
190 } else {
191 llinfos << "setting stream to NULL"<< llendl;
192 mInternetStreamURL.clear();
193 mInternetStreamMedia->addCommand(LLMediaBase::COMMAND_STOP);
194 mInternetStreamMedia->updateMedia();
195 }
196 //#endif
197}
198
199// virtual
200void LLAudioEngine::stopInternetStream()
201{
202 llinfos << "entered stopInternetStream()" << llendl;
203
204 if(mInternetStreamMedia)
205 {
206 if( ! mInternetStreamMedia->addCommand(LLMediaBase::COMMAND_STOP)){
207 llinfos << "attempting to stop stream failed!" << llendl;
208 } 163 }
209 mInternetStreamMedia->updateMedia();
210 } 164 }
211
212 mInternetStreamURL.clear();
213}
214
215// virtual
216void LLAudioEngine::pauseInternetStream(int pause)
217{
218 llinfos << "entered pauseInternetStream()" << llendl;
219
220 if(!mInternetStreamMedia)
221 return;
222
223 if(pause)
224 {
225 if(! mInternetStreamMedia->addCommand(LLMediaBase::COMMAND_PAUSE))
226 {
227 llinfos << "attempting to pause stream failed!" << llendl;
228 }
229 } else {
230 if(! mInternetStreamMedia->addCommand(LLMediaBase::COMMAND_START))
231 {
232 llinfos << "attempting to unpause stream failed!" << llendl;
233 }
234 }
235 mInternetStreamMedia->updateMedia();
236}
237
238// virtual
239void LLAudioEngine::updateInternetStream()
240{
241 if (mInternetStreamMedia)
242 mInternetStreamMedia->updateMedia();
243}
244
245// virtual
246int LLAudioEngine::isInternetStreamPlaying()
247{
248 if (!mInternetStreamMedia)
249 return 0;
250
251 if (mInternetStreamMedia->getStatus() == LLMediaBase::STATUS_STARTED)
252 {
253 return 1; // Active and playing
254 }
255
256 if (mInternetStreamMedia->getStatus() == LLMediaBase::STATUS_PAUSED)
257 {
258 return 2; // paused
259 }
260
261 return 0; // Stopped
262}
263
264// virtual
265void LLAudioEngine::getInternetStreamInfo(char* artist, char* title)
266{
267 artist[0] = 0;
268 title[0] = 0;
269}
270
271// virtual
272void LLAudioEngine::setInternetStreamGain(F32 vol)
273{
274 mInternetStreamGain = vol;
275
276 if(!mInternetStreamMedia)
277 return;
278
279 vol = llclamp(vol, 0.f, 1.f);
280 mInternetStreamMedia->setVolume(vol);
281 mInternetStreamMedia->updateMedia();
282}
283
284// virtual
285const std::string& LLAudioEngine::getInternetStreamURL()
286{
287 return mInternetStreamURL;
288} 165}
289 166
290 167
@@ -295,6 +172,13 @@ void LLAudioEngine::updateChannels()
295 { 172 {
296 if (mChannels[i]) 173 if (mChannels[i])
297 { 174 {
175 // set secondary gain if type is available
176 LLAudioSource* source = mChannels[i]->getSource();
177 if (source)
178 {
179 mChannels[i]->setSecondaryGain(mSecondaryGain[source->getType()]);
180 }
181
298 mChannels[i]->updateBuffer(); 182 mChannels[i]->updateBuffer();
299 mChannels[i]->update3DPosition(); 183 mChannels[i]->update3DPosition();
300 mChannels[i]->updateLoop(); 184 mChannels[i]->updateLoop();
@@ -565,8 +449,6 @@ void LLAudioEngine::idle(F32 max_decode_time)
565 // missed picking it up in all the places that can add 449 // missed picking it up in all the places that can add
566 // or request new data. 450 // or request new data.
567 startNextTransfer(); 451 startNextTransfer();
568
569 updateInternetStream();
570} 452}
571 453
572 454
@@ -775,6 +657,18 @@ F32 LLAudioEngine::getMasterGain()
775 return mMasterGain; 657 return mMasterGain;
776} 658}
777 659
660void LLAudioEngine::setSecondaryGain(S32 type, F32 gain)
661{
662 llassert(type < LLAudioEngine::AUDIO_TYPE_COUNT);
663
664 mSecondaryGain[type] = gain;
665}
666
667F32 LLAudioEngine::getSecondaryGain(S32 type)
668{
669 return mSecondaryGain[type];
670}
671
778F32 LLAudioEngine::getInternetStreamGain() 672F32 LLAudioEngine::getInternetStreamGain()
779{ 673{
780 return mInternetStreamGain; 674 return mInternetStreamGain;
@@ -850,7 +744,8 @@ F64 LLAudioEngine::mapWindVecToPan(LLVector3 wind_vec)
850} 744}
851 745
852 746
853void LLAudioEngine::triggerSound(const LLUUID &audio_uuid, const LLUUID& owner_id, const F32 gain, const LLVector3d &pos_global) 747void LLAudioEngine::triggerSound(const LLUUID &audio_uuid, const LLUUID& owner_id, const F32 gain,
748 const S32 type, const LLVector3d &pos_global)
854{ 749{
855 // Create a new source (since this can't be associated with an existing source. 750 // Create a new source (since this can't be associated with an existing source.
856 //llinfos << "Localized: " << audio_uuid << llendl; 751 //llinfos << "Localized: " << audio_uuid << llendl;
@@ -1317,12 +1212,13 @@ LLAudioSource::LLAudioSource(const LLUUID& id, const LLUUID& owner_id, const F32
1317 mOwnerID(owner_id), 1212 mOwnerID(owner_id),
1318 mPriority(0.f), 1213 mPriority(0.f),
1319 mGain(gain), 1214 mGain(gain),
1320 mAmbient(false), 1215 mType(type),
1321 mLoop(false), 1216 mAmbient(FALSE),
1322 mSyncMaster(false), 1217 mLoop(FALSE),
1323 mSyncSlave(false), 1218 mSyncMaster(FALSE),
1324 mQueueSounds(false), 1219 mSyncSlave(FALSE),
1325 mPlayedOnce(false), 1220 mQueueSounds(FALSE),
1221 mPlayedOnce(FALSE),
1326 mChannelp(NULL), 1222 mChannelp(NULL),
1327 mCurrentDatap(NULL), 1223 mCurrentDatap(NULL),
1328 mQueuedDatap(NULL) 1224 mQueuedDatap(NULL)
@@ -1468,8 +1364,7 @@ bool LLAudioSource::play(const LLUUID &audio_uuid)
1468bool LLAudioSource::isDone() 1364bool LLAudioSource::isDone()
1469{ 1365{
1470 const F32 MAX_AGE = 60.f; 1366 const F32 MAX_AGE = 60.f;
1471 const F32 MAX_UNPLAYED_AGE = 15.f; 1367 const F32 MAX_UNPLAYED_AGE = 30.f;
1472
1473 if (isLoop()) 1368 if (isLoop())
1474 { 1369 {
1475 // Looped sources never die on their own. 1370 // Looped sources never die on their own.
@@ -1647,8 +1542,9 @@ LLAudioBuffer *LLAudioSource::getCurrentBuffer()
1647LLAudioChannel::LLAudioChannel() : 1542LLAudioChannel::LLAudioChannel() :
1648 mCurrentSourcep(NULL), 1543 mCurrentSourcep(NULL),
1649 mCurrentBufferp(NULL), 1544 mCurrentBufferp(NULL),
1650 mLoopedThisFrame(false), 1545 mLoopedThisFrame(FALSE),
1651 mWaiting(false) 1546 mWaiting(FALSE),
1547 mSecondaryGain(1.0f)
1652{ 1548{
1653} 1549}
1654 1550
diff --git a/linden/indra/llaudio/audioengine.h b/linden/indra/llaudio/audioengine.h
index 94134f5..937a8e1 100644
--- a/linden/indra/llaudio/audioengine.h
+++ b/linden/indra/llaudio/audioengine.h
@@ -80,11 +80,23 @@ class LLAudioBuffer;
80class LLAudioEngine 80class LLAudioEngine
81{ 81{
82public: 82public:
83 enum LLAudioType
84 {
85 AUDIO_TYPE_NONE = 0,
86 AUDIO_TYPE_SFX = 1,
87 AUDIO_TYPE_UI = 2,
88 AUDIO_TYPE_AMBIENT = 3,
89 AUDIO_TYPE_COUNT = 4 // last
90 };
91
83 LLAudioEngine(); 92 LLAudioEngine();
84 virtual ~LLAudioEngine(); 93 virtual ~LLAudioEngine();
85 94
86 // initialization/startup/shutdown 95 // initialization/startup/shutdown
87 virtual bool init(const S32 num_channels, void *userdata); 96 //virtual BOOL init();
97
98 virtual BOOL init(const S32 num_channels);
99 virtual std::string getDriverName(bool verbose) = 0;
88 virtual void shutdown(); 100 virtual void shutdown();
89 101
90 // Used by the mechanics of the engine 102 // Used by the mechanics of the engine
@@ -109,6 +121,9 @@ public:
109 F32 getMasterGain(); 121 F32 getMasterGain();
110 void setMasterGain(F32 gain); 122 void setMasterGain(F32 gain);
111 123
124 F32 getSecondaryGain(S32 type);
125 void setSecondaryGain(S32 type, F32 gain);
126
112 F32 getInternetStreamGain(); 127 F32 getInternetStreamGain();
113 128
114 virtual void setDopplerFactor(F32 factor); 129 virtual void setDopplerFactor(F32 factor);
@@ -122,8 +137,10 @@ public:
122 137
123 // Methods actually related to setting up and removing sounds 138 // Methods actually related to setting up and removing sounds
124 // Owner ID is the owner of the object making the request 139 // Owner ID is the owner of the object making the request
125 void triggerSound(const LLUUID &sound_id, const LLUUID& owner_id, const F32 gain, const LLVector3d &pos_global = LLVector3d::zero); 140 void triggerSound(const LLUUID &sound_id, const LLUUID& owner_id, const F32 gain,
126 bool preloadSound(const LLUUID &id); 141 const S32 type = LLAudioEngine::AUDIO_TYPE_NONE,
142 const LLVector3d &pos_global = LLVector3d::zero);
143 BOOL preloadSound(const LLUUID &id);
127 144
128 void addAudioSource(LLAudioSource *asp); 145 void addAudioSource(LLAudioSource *asp);
129 void cleanupAudioSource(LLAudioSource *asp); 146 void cleanupAudioSource(LLAudioSource *asp);
@@ -132,16 +149,15 @@ public:
132 LLAudioData *getAudioData(const LLUUID &audio_uuid); 149 LLAudioData *getAudioData(const LLUUID &audio_uuid);
133 150
134 151
135 // Internet stream methods 152 virtual void startInternetStream(const std::string& url) = 0;
136 virtual void startInternetStream(const std::string& url); 153 virtual void stopInternetStream() = 0;
137 virtual void stopInternetStream(); 154 virtual void pauseInternetStream(int pause) = 0;
138 virtual void pauseInternetStream(int pause); 155 virtual int isInternetStreamPlaying() = 0;
139 virtual void updateInternetStream(); 156 virtual void getInternetStreamInfo(char* artist, char* title) { artist[0] = 0; title[0] = 0; }
140 virtual int isInternetStreamPlaying();
141 virtual void getInternetStreamInfo(char* artist, char* title);
142 // use a value from 0.0 to 1.0, inclusive 157 // use a value from 0.0 to 1.0, inclusive
143 virtual void setInternetStreamGain(F32 vol); 158 virtual void setInternetStreamGain(F32 vol) { mInternetStreamGain = vol; }
144 virtual const std::string& getInternetStreamURL(); 159 virtual const std::string& getInternetStreamURL() { return LLStringUtil::null; }
160 virtual void InitStreamer() = 0;
145 161
146 // For debugging usage 162 // For debugging usage
147 virtual LLVector3 getListenerPos(); 163 virtual LLVector3 getListenerPos();
@@ -177,6 +193,11 @@ protected:
177 virtual void allocateListener() = 0; 193 virtual void allocateListener() = 0;
178 194
179 195
196 // Internet stream methods
197 virtual void initInternetStream() {}
198 virtual void updateInternetStream() {}
199
200
180 // listener methods 201 // listener methods
181 virtual void setListenerPos(LLVector3 vec); 202 virtual void setListenerPos(LLVector3 vec);
182 virtual void setListenerVelocity(LLVector3 vec); 203 virtual void setListenerVelocity(LLVector3 vec);
@@ -191,8 +212,7 @@ protected:
191protected: 212protected:
192 LLListener *mListenerp; 213 LLListener *mListenerp;
193 214
194 bool mMuted; 215 BOOL mMuted;
195 void* mUserData;
196 216
197 S32 mLastStatus; 217 S32 mLastStatus;
198 218
@@ -218,10 +238,10 @@ protected:
218 LLAudioBuffer *mBuffers[MAX_BUFFERS]; 238 LLAudioBuffer *mBuffers[MAX_BUFFERS];
219 239
220 F32 mMasterGain; 240 F32 mMasterGain;
241 F32 mSecondaryGain[AUDIO_TYPE_COUNT];
221 242
222 // Hack! Internet streams are treated differently from other sources! 243 // Hack! Internet streams are treated differently from other sources!
223 F32 mInternetStreamGain; 244 F32 mInternetStreamGain;
224 std::string mInternetStreamURL;
225 245
226 F32 mNextWindUpdate; 246 F32 mNextWindUpdate;
227 247
@@ -229,7 +249,6 @@ protected:
229 249
230private: 250private:
231 void setDefaults(); 251 void setDefaults();
232 LLMediaBase *mInternetStreamMedia;
233}; 252};
234 253
235 254
@@ -272,6 +291,9 @@ public:
272 291
273 void setPlayedOnce(const bool played_once) { mPlayedOnce = played_once; } 292 void setPlayedOnce(const bool played_once) { mPlayedOnce = played_once; }
274 293
294 void setType(S32 type) { mType = type; }
295 S32 getType() { return mType; }
296
275 void setPositionGlobal(const LLVector3d &position_global) { mPositionGlobal = position_global; } 297 void setPositionGlobal(const LLVector3d &position_global) { mPositionGlobal = position_global; }
276 LLVector3d getPositionGlobal() const { return mPositionGlobal; } 298 LLVector3d getPositionGlobal() const { return mPositionGlobal; }
277 LLVector3 getVelocity() const { return mVelocity; } 299 LLVector3 getVelocity() const { return mVelocity; }
@@ -304,12 +326,13 @@ protected:
304 LLUUID mOwnerID; // owner of the object playing the sound 326 LLUUID mOwnerID; // owner of the object playing the sound
305 F32 mPriority; 327 F32 mPriority;
306 F32 mGain; 328 F32 mGain;
307 bool mAmbient; 329 BOOL mAmbient;
308 bool mLoop; 330 BOOL mLoop;
309 bool mSyncMaster; 331 BOOL mSyncMaster;
310 bool mSyncSlave; 332 BOOL mSyncSlave;
311 bool mQueueSounds; 333 BOOL mQueueSounds;
312 bool mPlayedOnce; 334 BOOL mPlayedOnce;
335 S32 mType;
313 LLVector3d mPositionGlobal; 336 LLVector3d mPositionGlobal;
314 LLVector3 mVelocity; 337 LLVector3 mVelocity;
315 338
@@ -378,6 +401,9 @@ public:
378 virtual void setSource(LLAudioSource *sourcep); 401 virtual void setSource(LLAudioSource *sourcep);
379 LLAudioSource *getSource() const { return mCurrentSourcep; } 402 LLAudioSource *getSource() const { return mCurrentSourcep; }
380 403
404 void setSecondaryGain(F32 gain) { mSecondaryGain = gain; }
405 F32 getSecondaryGain() { return mSecondaryGain; }
406
381 friend class LLAudioEngine; 407 friend class LLAudioEngine;
382 friend class LLAudioSource; 408 friend class LLAudioSource;
383protected: 409protected:
@@ -394,8 +420,9 @@ protected:
394protected: 420protected:
395 LLAudioSource *mCurrentSourcep; 421 LLAudioSource *mCurrentSourcep;
396 LLAudioBuffer *mCurrentBufferp; 422 LLAudioBuffer *mCurrentBufferp;
397 bool mLoopedThisFrame; 423 BOOL mLoopedThisFrame;
398 bool mWaiting; // Waiting for sync. 424 BOOL mWaiting; // Waiting for sync.
425 F32 mSecondaryGain;
399}; 426};
400 427
401 428
diff --git a/linden/indra/llaudio/audioengine_openal.cpp b/linden/indra/llaudio/audioengine_openal.cpp
index 85d2080..65203dd 100644
--- a/linden/indra/llaudio/audioengine_openal.cpp
+++ b/linden/indra/llaudio/audioengine_openal.cpp
@@ -36,29 +36,31 @@
36#include "audioengine_openal.h" 36#include "audioengine_openal.h"
37#include "listener_openal.h" 37#include "listener_openal.h"
38 38
39LLAudioEngine_OpenAL::LLAudioEngine_OpenAL()
40{
39 41
40// Variables and definitions for Wind 42 #if LL_GSTREAMER_ENABLED
41#define MAX_NUM_WIND_BUFFERS 40 43 mMedia_data = new LLMediaManagerData;
42static int empty_num_wind_buffers = MAX_NUM_WIND_BUFFERS; 44 // initialize GStreamer
43static const float wind_buffer_size_sec = 0.05f; // 1/20th sec 45 LLMediaImplGStreamer::startup( mMedia_data );
44static const U32 wind_gen_freq = LLWindGen<S16>::getInputSamplingRate();
45static ALuint wind_source;
46static S16 *winddata=NULL;
47 46
47 m_streamer=new LLMediaImplGStreamer ();
48 48
49LLAudioEngine_OpenAL::LLAudioEngine_OpenAL() 49 if(!m_streamer)
50{ 50 {
51 mWindGen = NULL; 51 llwarns << "LLAudioEngine_OpenAL::LLAudioEngine_OpenAL() Failed to create our private gstreamer audio instance" << llendl;
52 }
53 #endif
52} 54}
53 55
54LLAudioEngine_OpenAL::~LLAudioEngine_OpenAL() 56LLAudioEngine_OpenAL::~LLAudioEngine_OpenAL()
55{ 57{
56} 58}
57 59
58bool LLAudioEngine_OpenAL::init(const S32 num_channels, void* userdata) 60
61BOOL LLAudioEngine_OpenAL::init(const S32 num_channels)
59{ 62{
60 mWindGen = NULL; 63 LLAudioEngine::init(num_channels);
61 LLAudioEngine::init(num_channels, userdata);
62 64
63 if(!alutInit(NULL, NULL)) 65 if(!alutInit(NULL, NULL))
64 { 66 {
@@ -66,35 +68,61 @@ bool LLAudioEngine_OpenAL::init(const S32 num_channels, void* userdata)
66 return false; 68 return false;
67 } 69 }
68 70
71 initInternetStream();
72
69 llinfos << "LLAudioEngine_OpenAL::init() OpenAL successfully initialized" << llendl; 73 llinfos << "LLAudioEngine_OpenAL::init() OpenAL successfully initialized" << llendl;
70 74
71 llinfos << "OpenAL version: " 75 llinfos << "LLAudioEngine_OpenAL::init() Speed of sound is: " << alGetFloat(AL_SPEED_OF_SOUND) << llendl;
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 76
78 ALint major = alutGetMajorVersion (); 77 return TRUE;
79 ALint minor = alutGetMinorVersion (); 78}
80 llinfos << "ALUT version: " << major << "." << minor << llendl;
81 79
80std::string LLAudioEngine_OpenAL::getDriverName(bool verbose)
81{
82 ALCdevice *device = alcGetContextsDevice(alcGetCurrentContext()); 82 ALCdevice *device = alcGetContextsDevice(alcGetCurrentContext());
83
84 std::ostringstream version;
85
86 ALint major = alutGetMajorVersion ();
87 ALint minor = alutGetMinorVersion ();
83 88
84 alcGetIntegerv(device, ALC_MAJOR_VERSION, 1, &major); 89 alcGetIntegerv(device, ALC_MAJOR_VERSION, 1, &major);
85 alcGetIntegerv(device, ALC_MAJOR_VERSION, 1, &minor); 90 alcGetIntegerv(device, ALC_MAJOR_VERSION, 1, &minor);
86 llinfos << "ALC version: " << major << "." << minor << llendl;
87 91
88 llinfos << "ALC default device: " 92 version <<
89 << ll_safe_string(alcGetString(device, 93 "OpenAL";
90 ALC_DEFAULT_DEVICE_SPECIFIER))
91 << llendl;
92 94
93 llinfos << "LLAudioEngine_OpenAL::init() Speed of sound is: " << alGetFloat(AL_SPEED_OF_SOUND) << llendl; 95 if (verbose)
96 {
97 version <<
98 ", version " <<
99 ll_safe_string(alGetString(AL_VERSION)) <<
100 " / " <<
101 ll_safe_string(alGetString(AL_VENDOR)) <<
102 " / " <<
103 ll_safe_string(alGetString(AL_RENDERER));
104
105 if (device)
106 version <<
107 ": " <<
108 ll_safe_string(alcGetString(device,
109 ALC_DEFAULT_DEVICE_SPECIFIER));
110 }
94 111
95 return true; 112 return version.str();
113}
114
115
116void LLAudioEngine_OpenAL::idle(F32 max_decode_time)
117{
118 LLAudioEngine::idle(max_decode_time);
119 #if LL_GSTREAMER_ENABLED
120 if(m_streamer != NULL)
121 m_streamer->updateMedia();
122 #endif
96} 123}
97 124
125
98void LLAudioEngine_OpenAL::allocateListener() 126void LLAudioEngine_OpenAL::allocateListener()
99{ 127{
100 mListenerp = (LLListener *) new LLListener_OpenAL(); 128 mListenerp = (LLListener *) new LLListener_OpenAL();
@@ -115,11 +143,21 @@ void LLAudioEngine_OpenAL::shutdown()
115 llwarns << "Nuts." << llendl; 143 llwarns << "Nuts." << llendl;
116 llwarns << "LLAudioEngine_OpenAL::shutdown() ALUT shutdown failed: " << alutGetErrorString (alutGetError ()) << llendl; 144 llwarns << "LLAudioEngine_OpenAL::shutdown() ALUT shutdown failed: " << alutGetErrorString (alutGetError ()) << llendl;
117 } 145 }
118 146 else
119 llinfos << "LLAudioEngine_OpenAL::shutdown() OpenAL successfully shut down" << llendl; 147 {
120 148 llinfos << "LLAudioEngine_OpenAL::shutdown() OpenAL successfully shut down" << llendl;
149 }
150
121 delete mListenerp; 151 delete mListenerp;
122 mListenerp = NULL; 152 mListenerp = NULL;
153
154 #if LL_GSTREAMER_ENABLED
155 if(m_streamer)
156 {
157 delete m_streamer;
158 m_streamer = NULL;
159 }
160 #endif
123} 161}
124 162
125LLAudioBuffer *LLAudioEngine_OpenAL::createBuffer() 163LLAudioBuffer *LLAudioEngine_OpenAL::createBuffer()
@@ -140,26 +178,27 @@ void LLAudioEngine_OpenAL::setInternalGain(F32 gain)
140 178
141LLAudioChannelOpenAL::LLAudioChannelOpenAL() 179LLAudioChannelOpenAL::LLAudioChannelOpenAL()
142{ 180{
143 alGenSources(1, &mALSource); 181 alGenSources(1, &ALSource);
144} 182}
145 183
146LLAudioChannelOpenAL::~LLAudioChannelOpenAL() 184LLAudioChannelOpenAL::~LLAudioChannelOpenAL()
147{ 185{
148 cleanup(); 186 cleanup();
149 alDeleteSources(1, &mALSource); 187 alDeleteSources(1, &ALSource);
150} 188}
151 189
152void LLAudioChannelOpenAL::cleanup() 190void LLAudioChannelOpenAL::cleanup()
153{ 191{
154 alSourceStop(mALSource); 192 alSourceStop(ALSource);
155 mCurrentBufferp = NULL; 193 mCurrentBufferp = NULL;
156} 194}
157 195
158void LLAudioChannelOpenAL::play() 196void LLAudioChannelOpenAL::play()
159{ 197{
160 if(!isPlaying()){ 198 if(!isPlaying())
161 alSourcePlay(mALSource); 199 {
162 getSource()->setPlayedOnce(true); 200 alSourcePlay(ALSource);
201 getSource()->setPlayedOnce(TRUE);
163 } 202 }
164} 203}
165 204
@@ -171,9 +210,10 @@ void LLAudioChannelOpenAL::playSynced(LLAudioChannel *channelp)
171bool LLAudioChannelOpenAL::isPlaying() 210bool LLAudioChannelOpenAL::isPlaying()
172{ 211{
173 ALint state; 212 ALint state;
174 alGetSourcei(mALSource, AL_SOURCE_STATE, &state); 213 alGetSourcei(ALSource, AL_SOURCE_STATE, &state);
175 if(state == AL_PLAYING){ 214 if(state == AL_PLAYING)
176 return true; 215 {
216 return TRUE;
177 } 217 }
178 return false; 218 return false;
179} 219}
@@ -185,9 +225,9 @@ bool LLAudioChannelOpenAL::updateBuffer()
185 // Base class update returned true, which means that we need to actually 225 // Base class update returned true, which means that we need to actually
186 // set up the source for a different buffer. 226 // set up the source for a different buffer.
187 LLAudioBufferOpenAL *bufferp = (LLAudioBufferOpenAL *)mCurrentSourcep->getCurrentBuffer(); 227 LLAudioBufferOpenAL *bufferp = (LLAudioBufferOpenAL *)mCurrentSourcep->getCurrentBuffer();
188 alSourcei(mALSource, AL_BUFFER, bufferp->getBuffer()); 228 alSourcei(ALSource, AL_BUFFER, bufferp->getBuffer());
189 alSourcef(mALSource, AL_GAIN, mCurrentSourcep->getGain()); 229 alSourcef(ALSource, AL_GAIN, mCurrentSourcep->getGain());
190 alSourcei(mALSource, AL_LOOPING, mCurrentSourcep->isLoop() ? AL_TRUE : AL_FALSE); 230 alSourcei(ALSource, AL_LOOPING, mCurrentSourcep->isLoop() ? AL_TRUE : AL_FALSE);
191 } 231 }
192 232
193 return true; 233 return true;
@@ -201,28 +241,30 @@ void LLAudioChannelOpenAL::update3DPosition()
201 } 241 }
202 if (mCurrentSourcep->isAmbient()) 242 if (mCurrentSourcep->isAmbient())
203 { 243 {
204 alSource3f(mALSource, AL_POSITION, 0.0, 0.0, 0.0); 244 alSource3f(ALSource, AL_POSITION, 0.0, 0.0, 0.0);
205 alSource3f(mALSource, AL_VELOCITY, 0.0, 0.0, 0.0); 245 alSource3f(ALSource, AL_VELOCITY, 0.0, 0.0, 0.0);
206 //alSource3f(mALSource, AL_DIRECTION, 0.0, 0.0, 0.0); 246 //alSource3f(ALSource, AL_DIRECTION, 0.0, 0.0, 0.0);
207 alSourcef (mALSource, AL_ROLLOFF_FACTOR, 0.0); 247 alSourcef (ALSource, AL_ROLLOFF_FACTOR, 0.0);
208 alSourcei (mALSource, AL_SOURCE_RELATIVE, AL_TRUE); 248 alSourcei (ALSource, AL_SOURCE_RELATIVE, AL_TRUE);
209 } else { 249 }
250 else
251 {
210 LLVector3 float_pos; 252 LLVector3 float_pos;
211 float_pos.setVec(mCurrentSourcep->getPositionGlobal()); 253 float_pos.setVec(mCurrentSourcep->getPositionGlobal());
212 alSourcefv(mALSource, AL_POSITION, float_pos.mV); 254 alSourcefv(ALSource, AL_POSITION, float_pos.mV);
213 //llinfos << "LLAudioChannelOpenAL::update3DPosition() Velocity: " << mCurrentSourcep->getVelocity() << llendl; 255 //llinfos << "LLAudioChannelOpenAL::update3DPosition() Velocity: " << mCurrentSourcep->getVelocity() << llendl;
214 alSourcefv(mALSource, AL_VELOCITY, mCurrentSourcep->getVelocity().mV); 256 alSourcefv(ALSource, AL_VELOCITY, mCurrentSourcep->getVelocity().mV);
215 //alSource3f(mALSource, AL_DIRECTION, 0.0, 0.0, 0.0); 257 //alSource3f(ALSource, AL_DIRECTION, 0.0, 0.0, 0.0);
216 alSourcef (mALSource, AL_ROLLOFF_FACTOR, 1.0); 258 alSourcef (ALSource, AL_ROLLOFF_FACTOR, 1.0);
217 alSourcei (mALSource, AL_SOURCE_RELATIVE, AL_FALSE); 259 alSourcei (ALSource, AL_SOURCE_RELATIVE, AL_FALSE);
218 } 260 }
219 //llinfos << "LLAudioChannelOpenAL::update3DPosition() Gain: " << mCurrentSourcep->getGain() << llendl; 261 //llinfos << "LLAudioChannelOpenAL::update3DPosition() Gain: " << mCurrentSourcep->getGain() << llendl;
220 alSourcef(mALSource, AL_GAIN, mCurrentSourcep->getGain()); 262 alSourcef(ALSource, AL_GAIN, mCurrentSourcep->getGain());
221} 263}
222 264
223LLAudioBufferOpenAL::LLAudioBufferOpenAL() 265LLAudioBufferOpenAL::LLAudioBufferOpenAL()
224{ 266{
225 mALBuffer = AL_NONE; 267 ALBuffer = AL_NONE;
226} 268}
227 269
228LLAudioBufferOpenAL::~LLAudioBufferOpenAL() 270LLAudioBufferOpenAL::~LLAudioBufferOpenAL()
@@ -232,99 +274,99 @@ LLAudioBufferOpenAL::~LLAudioBufferOpenAL()
232 274
233void LLAudioBufferOpenAL::cleanup() 275void LLAudioBufferOpenAL::cleanup()
234{ 276{
235 if(mALBuffer != AL_NONE) 277 if(ALBuffer != AL_NONE)
236 { 278 {
237 alDeleteBuffers(1, &mALBuffer); 279 alDeleteBuffers(1, &ALBuffer);
238 mALBuffer = AL_NONE;
239 } 280 }
240} 281}
241 282
242bool LLAudioBufferOpenAL::loadWAV(const std::string& filename) 283bool LLAudioBufferOpenAL::loadWAV(const std::string& filename)
243{ 284{
244 cleanup(); 285 cleanup();
245 mALBuffer = alutCreateBufferFromFile(filename.c_str()); 286 ALBuffer = alutCreateBufferFromFile(filename.c_str());
246 if(mALBuffer == AL_NONE){ 287 if(ALBuffer == AL_NONE)
247 ALenum error = alutGetError(); 288 {
248 if (gDirUtilp->fileExists(filename)) { 289 return FALSE;
249 llwarns <<
250 "LLAudioBufferOpenAL::loadWAV() Error loading "
251 << filename
252 << " " << alutGetErrorString(error) << llendl;
253 } else {
254 // It's common for the file to not actually exist.
255 lldebugs <<
256 "LLAudioBufferOpenAL::loadWAV() Error loading "
257 << filename
258 << " " << alutGetErrorString(error) << llendl;
259 }
260 return false;
261 } 290 }
262 291
263 return true; 292 return true;
264} 293}
265 294
266U32 LLAudioBufferOpenAL::getLength(){ 295
267 if(mALBuffer == AL_NONE){ 296U32 LLAudioBufferOpenAL::getLength()
297{
298 if(ALBuffer == AL_NONE)
299 {
268 return 0; 300 return 0;
269 } 301 }
270 ALint length; 302 ALint length;
271 alGetBufferi(mALBuffer, AL_SIZE, &length); 303 alGetBufferi(ALBuffer, AL_SIZE, &length);
272 return length >> 2; 304 return length >> 2;
273} 305}
274 306
275// ------------ 307// ------------
276 308
277void LLAudioEngine_OpenAL::initWind(){ 309void LLAudioEngine_OpenAL::initWind()
278 ALenum error; 310{
279 llinfos << "LLAudioEngine_OpenAL::initWind() start" << llendl;
280 311
281 alGetError(); /* clear error */ 312 if (true)
282 313 return;
283 alGenSources(1,&wind_source);
284
285 if((error=alGetError()) != AL_NO_ERROR)
286 {
287 llwarns << "LLAudioEngine_OpenAL::initWind() Error creating wind sources: "<<error<<llendl;
288 }
289
290 winddata=(S16*)malloc(sizeof(S16)*llceil(wind_gen_freq*wind_buffer_size_sec*2*2)); //200ms @wind_gen_freqHz Stereo
291 314
292 if(winddata==NULL) 315 llinfos << "initWind() start" << llendl;
316
317 alGenBuffers(mNumWindBuffers,mWindBuffers);
318 alGenSources(1,&mWindSource);
319 checkALError();
320
321 // ok lets make a wind buffer now
322 for(int counter=0;counter<mNumWindBuffers;counter++)
293 { 323 {
294 llerrs << "LLAudioEngine_OpenAL::initWind() Error creating wind memory buffer" << llendl; 324
295 mEnableWind=false; 325 alBufferData(mWindBuffers[counter],AL_FORMAT_STEREO16,windDSP((void*)mWindData,mWindDataSize/mBytesPerSample),mWindDataSize,mSampleRate);
326 checkALError();
296 } 327 }
297 328
298 mWindGen = new LLWindGen<S16>; 329 alSourceQueueBuffers(mWindSource, mNumWindBuffers, mWindBuffers);
330 checkALError();
331
332 alSourcePlay(mWindSource);
333 checkALError();
299 334
300 llinfos << "LLAudioEngine_OpenAL::initWind() done" << llendl; 335 llinfos << "LLAudioEngine_OpenAL::initWind() done" << llendl;
336
301} 337}
302 338
303void LLAudioEngine_OpenAL::cleanupWind(){ 339void LLAudioEngine_OpenAL::cleanupWind(){
304 llinfos << "LLAudioEngine_OpenAL::cleanupWind()" << llendl; 340 llinfos << "LLAudioEngine_OpenAL::cleanupWind()" << llendl;
305 341
306 alDeleteSources(1, &wind_source); 342 alDeleteBuffers(mNumWindBuffers,mWindBuffers);
307 343 alDeleteSources(1, &mWindSource);
308 if(winddata) 344
309 free(winddata); 345 checkALError();
346}
347
348void LLAudioEngine_OpenAL::checkALError()
349{
350 ALenum error;
351 if((error=alGetError()) != AL_NO_ERROR)
352 llwarns << "LLAudioEngine_OpenAL Error: "<<error<<llendl;
310 353
311 delete mWindGen;
312 mWindGen = NULL;
313} 354}
314 355
315void LLAudioEngine_OpenAL::updateWind(LLVector3 wind_vec, F32 camera_altitude) 356void LLAudioEngine_OpenAL::updateWind(LLVector3 wind_vec, F32 camera_altitude)
316{ 357{
358
359 if (true)
360 return;
361
317 LLVector3 wind_pos; 362 LLVector3 wind_pos;
318 F64 pitch; 363 F32 pitch;
319 F64 center_freq; 364 F32 center_freq;
320 ALenum error; 365
321 366 if (!mEnableWind)
322 mMaxWindGain=1.0;
323
324 if (mEnableWind)
325 return; 367 return;
326 368
327 if(winddata) 369 if(!mWindData)
328 return; 370 return;
329 371
330 if (mWindUpdateTimer.checkExpirationAndReset(LL_WIND_UPDATE_INTERVAL)) 372 if (mWindUpdateTimer.checkExpirationAndReset(LL_WIND_UPDATE_INTERVAL))
@@ -335,88 +377,385 @@ void LLAudioEngine_OpenAL::updateWind(LLVector3 wind_vec, F32 camera_altitude)
335 // where +X = right, +Y = up, +Z = backwards 377 // where +X = right, +Y = up, +Z = backwards
336 378
337 wind_vec.setVec(-wind_vec.mV[1], wind_vec.mV[2], -wind_vec.mV[0]); 379 wind_vec.setVec(-wind_vec.mV[1], wind_vec.mV[2], -wind_vec.mV[0]);
338
339 pitch = 1.0 + mapWindVecToPitch(wind_vec);
340 center_freq = 80.0 * pow(pitch,2.5*(mapWindVecToGain(wind_vec)+1.0));
341
342 mWindGen->mTargetFreq = (F32)center_freq;
343 mWindGen->mTargetGain = (F32)mapWindVecToGain(wind_vec) * mMaxWindGain;
344 mWindGen->mTargetPanGainR = (F32)mapWindVecToPan(wind_vec);
345
346 alSourcei(wind_source, AL_LOOPING, AL_FALSE);
347 alSource3f(wind_source, AL_POSITION, 0.0, 0.0, 0.0);
348 alSource3f(wind_source, AL_VELOCITY, 0.0, 0.0, 0.0);
349 alSourcef(wind_source, AL_ROLLOFF_FACTOR, 0.0);
350 alSourcei(wind_source, AL_SOURCE_RELATIVE, AL_TRUE);
351 }
352 380
353 // ok lets make a wind buffer now
354 381
355 int processed, queued, unprocessed; 382 pitch = 1.0f + mapWindVecToPitch(wind_vec);
356 alGetSourcei(wind_source, AL_BUFFERS_PROCESSED, &processed); 383 center_freq = 80.0f * powf(pitch,2.5f*(mapWindVecToGain(wind_vec)+1.0f));
357 alGetSourcei(wind_source, AL_BUFFERS_QUEUED, &queued);
358 unprocessed = queued - processed;
359 384
360 // ensure that there are always at least 3x as many filled buffers 385 //TESTING
361 // queued as we managed to empty since last time. 386 mMaxWindGain=1.0;
362 empty_num_wind_buffers = llmin(empty_num_wind_buffers + processed * 3 - unprocessed, MAX_NUM_WIND_BUFFERS-unprocessed);
363 empty_num_wind_buffers = llmax(empty_num_wind_buffers, 0);
364 387
365 //llinfos << "empty_num_wind_buffers: " << empty_num_wind_buffers <<" (" << unprocessed << ":" << processed << ")" << llendl; 388 mTargetFreq = center_freq;
389 mTargetGain = (F32)mapWindVecToGain(wind_vec) * mMaxWindGain;
390 mTargetPanGainR = (F32)mapWindVecToPan(wind_vec);
366 391
367 while(processed--) // unqueue old buffers 392 ALfloat source0Pos[]={mListenerp->getPosition().mV[0],mListenerp->getPosition().mV[1],mListenerp->getPosition().mV[2]};
393 ALfloat source0Vel[]={ 0.0, 0.0, 0.0};
394
395 alSourcef(mWindSource, AL_GAIN, mTargetGain);
396 alSourcef(mWindSource, AL_PITCH, pitch);
397 alSourcefv(mWindSource, AL_POSITION, source0Pos);
398 alSourcefv(mWindSource, AL_VELOCITY, source0Vel);
399 alSourcei(mWindSource, AL_LOOPING, AL_FALSE);
400
401 }
402
403 int processed;
404 alGetSourcei(mWindSource, AL_BUFFERS_PROCESSED, &processed);
405
406 while(processed--)
368 { 407 {
369 ALuint buffer; 408 ALuint buffer;
370 int error; 409 alSourceUnqueueBuffers(mWindSource, 1, &buffer);
371 alGetError(); /* clear error */ 410 checkALError();
372 alSourceUnqueueBuffers(wind_source, 1, &buffer); 411 alBufferData(buffer,AL_FORMAT_STEREO16,windDSP((void*)mWindData,mWindDataSize/mBytesPerSample),mWindDataSize,mSampleRate);
373 error = alGetError(); 412 checkALError();
374 if(error != AL_NO_ERROR) 413 alSourceQueueBuffers(mWindSource, 1, &buffer);
375 { 414 checkALError();
376 llwarns << "LLAudioEngine_OpenAL::updateWind() error swapping (unqueuing) buffers" << llendl; 415 }
377 } 416
378 else 417 int playing;
418 alGetSourcei(mWindSource, AL_SOURCE_STATE, &playing);
419 if(playing==AL_STOPPED)
420 alSourcePlay(mWindSource);
421
422 checkALError();
423}
424
425
426void * LLAudioEngine_OpenAL::windDSP(void *newbuffer, int length)
427{
428 // *NOTE: This function gets called a *lot*.
429 // Keep performance in mind if you mess with this.
430 // newbuffer = the buffer being constructed
431 // length = length in samples of the buffer
432
433
434 //clear the buffer
435 memset(newbuffer, 0, length*mBytesPerSample);
436
437 // This turns off wind synth if it is muted or very very low volume
438 if (mTargetGain < 0.0005f)
439 {
440 llinfos << "Wind off" << llendl;
441 return newbuffer;
442 }
443
444 static const U8 SUBSAMPLES = 2;
445 static const F32 FILTER_SAMPLE_PERIOD = (F32)SUBSAMPLES / float(mSampleRate);
446 static const F32 BANDWIDTH = 50.0f;
447 static const F32 B2 = expf(-F_TWO_PI * BANDWIDTH * FILTER_SAMPLE_PERIOD);
448
449 static F32 pinking_buf0 = 0.0f;
450 static F32 pinking_buf1 = 0.0f;
451 static F32 pinking_buf2 = 0.0f;
452 static F32 Y0 = 0.0f;
453 static F32 Y1 = 0.0f;
454 static F32 last_sample = 0.0f;
455 static F32 current_freq = 0.0f;
456 static F32 current_gain = 0.0f;
457 static F32 current_pan_gain_r = 0.0f;
458
459 F32 a0 = 0.0f, b1 = 0.0f;
460
461 U8 *cursamplep = (U8*)newbuffer;
462
463 //we assume 16-bit samples, because the ALUT specification maxes out there
464 U8 wordsize = 2;
465
466 bool interp_freq = false;
467
468 //if the frequency isn't changing much, we don't need to interpolate in the inner loop
469 if (llabs(mTargetFreq - current_freq) > 200.0f)
470 {
471 interp_freq = true;
472 }
473 else
474 {
475 // calculate resonant filter coefficients
476 current_freq = mTargetFreq;
477 b1 = (-4.0f * B2) / (1.0f + B2) * cosf(F_TWO_PI * (current_freq * FILTER_SAMPLE_PERIOD));
478 a0 = (1.0f - B2) * sqrtf(1.0f - (b1 * b1) / (4.0f * B2));
479 }
480
481 while (length)
482 {
483 F32 next_sample;
484
485 // Start with white noise [-16384, 16383]
486 next_sample = (F32)rand() * (1.0f / (F32)(RAND_MAX / (U16_MAX / 4))) + (S16_MIN / 4);
487
488 // Apply a pinking filter
489 // Magic numbers taken from PKE method at http://www.firstpr.com.au/dsp/pink-noise/
490 pinking_buf0 = pinking_buf0 * 0.99765f + next_sample * 0.0990460f;
491 pinking_buf1 = pinking_buf1 * 0.96300f + next_sample * 0.2965164f;
492 pinking_buf2 = pinking_buf2 * 0.57000f + next_sample * 1.0526913f;
493
494 next_sample = pinking_buf0 + pinking_buf1 + pinking_buf2 + next_sample * 0.1848f;
495
496 if (interp_freq)
497 {
498 // calculate resonant filter coefficients
499 current_freq = (0.999f * current_freq) + (0.001f * mTargetFreq);
500 b1 = (-4.0f * B2) / (1.0f + B2) * cosf(F_TWO_PI * (current_freq * FILTER_SAMPLE_PERIOD));
501 a0 = (1.0f - B2) * sqrtf(1.0f - (b1 * b1) / (4.0f * B2));
502 }
503
504 // Apply a resonant low-pass filter on the pink noise
505 next_sample = ( a0 * next_sample - b1 * Y0 - B2 * Y1 );
506
507 Y1 = Y0;
508 Y0 = next_sample;
509
510 current_gain = (0.999f * current_gain) + (0.001f * mTargetGain);
511 current_pan_gain_r = (0.999f * current_pan_gain_r) + (0.001f * mTargetPanGainR);
512
513 next_sample *= current_gain;
514 F32 delta = (next_sample - last_sample) / (F32)SUBSAMPLES;
515
516 S32 sample_left;
517 S32 sample_right;
518
519 // Mix into the audio buffer, clipping if necessary for 16-bit mix buffers.
520 // *TODO: Should do something more intelligent like reducing wind gain to avoid clipping
521 for (int i=SUBSAMPLES; i && length; --i, --length)
522 {
523 last_sample = last_sample + delta;
524 sample_right = (S32)(last_sample * current_pan_gain_r);
525 sample_left = (S32)(last_sample - sample_right);
526
527 *(S16*)cursamplep = llclamp(sample_left, S16_MIN, S16_MAX);
528 cursamplep += wordsize;
529
530 *(S16*)cursamplep = llclamp(sample_right, S16_MIN, S16_MAX);
531 cursamplep += wordsize;
532 }
533 }
534 return newbuffer;
535
536}
537
538
539
540
541/*
542
543
544
545
546 // newbuffer = the buffer passed from the previous DSP unit.
547 // length = length in samples at this mix time.
548
549 U8 *cursamplep = (U8*)newbuffer;
550 U8 wordsize = 2;
551
552 double bandwidth = 50;
553 double inputSamplingRate = 44100;
554 double a0,b1,b2;
555
556 // calculate resonant filter coeffs
557 b2 = exp(-(F_TWO_PI) * (bandwidth / inputSamplingRate));
558
559 while (length--)
560 {
561 gCurrentFreq = (float)((0.999 * gCurrentFreq) + (0.001 * gTargetFreq));
562 gCurrentGain = (float)((0.999 * gCurrentGain) + (0.001 * gTargetGain));
563 gCurrentPanGainR = (float)((0.999 * gCurrentPanGainR) + (0.001 * gTargetPanGainR));
564 b1 = (-4.0 * b2) / (1.0 + b2) * cos(F_TWO_PI * (gCurrentFreq / inputSamplingRate));
565 a0 = (1.0 - b2) * sqrt(1.0 - (b1 * b1) / (4.0 * b2));
566 double nextSample;
567
568 // start with white noise
569 nextSample = ll_frand(2.0f) - 1.0f;
570
571 gbuf0 = 0.997f * gbuf0 + 0.0126502f * nextSample;
572 gbuf1 = 0.985f * gbuf1 + 0.0139083f * nextSample;
573 gbuf2 = 0.950f * gbuf2 + 0.0205439f * nextSample;
574 gbuf3 = 0.850f * gbuf3 + 0.0387225f * nextSample;
575 gbuf4 = 0.620f * gbuf4 + 0.0465932f * nextSample;
576 gbuf5 = 0.250f * gbuf5 + 0.1093477f * nextSample;
577
578 nextSample = gbuf0 + gbuf1 + gbuf2 + gbuf3 + gbuf4 + gbuf5;
579
580 nextSample = (double)( a0 * nextSample - b1 * gY0 - b2 * gY1 );
581
582 gY1 = gY0;
583 gY0 = nextSample;
584 nextSample *= gCurrentGain;
585
586 S16 sample;
587
588 sample = llfloor(((F32)nextSample*32768.f*(1.0f - gCurrentPanGainR))+0.5f);
589 *(S16*)cursamplep = clipSample(sample, -32768, 32767);
590
591 cursamplep += wordsize;
592
593 sample = llfloor(((F32)nextSample*32768.f*gCurrentPanGainR)+0.5f);
594
595 sample = llfloor(((F32)nextSample*32768.f*gCurrentPanGainR)+0.5f);
596 *(S16*)cursamplep = clipSample(sample, -32768, 32767);
597 cursamplep += wordsize;
598 }
599
600 return newbuffer;
601}
602*/
603
604// ------------
605
606void LLAudioEngine_OpenAL::InitStreamer()
607{
608 #if LL_GSTREAMER_ENABLED
609 m_streamer=new LLMediaImplGStreamer ();
610
611 if(!m_streamer)
612 {
613 llwarns << "LLAudioEngine_OpenAL::LLAudioEngine_OpenAL() Failed to create our private gstreamer audio instance" << llendl;
614 }
615
616 if(m_streamer)
617 {
618 m_streamer->init ();
619 }
620 #endif
621}
622
623
624// ------------
625
626void LLAudioEngine_OpenAL::initInternetStream()
627{
628 if(!mInternetStreamURL.empty())
629 mInternetStreamURL.erase();
630}
631
632
633void LLAudioEngine_OpenAL::startInternetStream(const std::string& url_cstr)
634{
635
636 std::string url(url_cstr);
637
638 #if LL_GSTREAMER_ENABLED
639 if(!m_streamer)
640 return;
641 // DCF_DEBUG
642 llinfos << "entered LLAudioEngine_OpenAL::startInternetStream()" << llendl;
643
644 if (!url.empty())
645 {
646 llinfos << "LLAudioEngine_OpenAL::startInternetStream() Starting internet stream: " << url << llendl;
647 mInternetStreamURL=url;
648 m_streamer->navigateTo ( url );
649 llinfos << "Playing....." << llendl;
650 m_streamer->addCommand(LLMediaBase::COMMAND_START);
651 m_streamer->updateMedia();
652
653 }
654 else
655 {
656 llinfos << "LLAudioEngine_OpenAL setting stream to NULL"<< llendl;
657 mInternetStreamURL.erase();
658 m_streamer->addCommand(LLMediaBase::COMMAND_STOP);
659 m_streamer->updateMedia();
660 }
661 #endif
662}
663
664
665void LLAudioEngine_OpenAL::updateInternetStream()
666{
667 // DCF_DEBUG
668 llinfos << "entered LLAudioEngine_OpenAL::updateInternetStream()" << llendl;
669
670}
671
672
673void LLAudioEngine_OpenAL::stopInternetStream()
674{
675 // DCF_DEBUG
676 llinfos << "entered LLAudioEngine_OpenAL::stopInternetStream()" << llendl;
677
678 #if LL_GSTREAMER_ENABLED
679 if( ! m_streamer->addCommand(LLMediaBase::COMMAND_STOP))
680 {
681 llinfos << "attempting to stop stream failed!" << llendl;
682 }
683 m_streamer->updateMedia();
684 #endif
685 mInternetStreamURL.erase();
686}
687
688
689void LLAudioEngine_OpenAL::pauseInternetStream(int pause)
690{
691 #if LL_GSTREAMER_ENABLED
692 if(!m_streamer)
693 return;
694 // DCF_DEBUG
695 llinfos << "entered LLAudioEngine_OpenAL::pauseInternetStream()" << llendl;
696
697 if(pause)
698 {
699 if(!m_streamer->addCommand(LLMediaBase::COMMAND_PAUSE))
379 { 700 {
380 alDeleteBuffers(1, &buffer); 701 llinfos << "attempting to pause stream failed!" << llendl;
381 } 702 }
703 m_streamer->updateMedia();
382 } 704 }
383 705 else
384 while (empty_num_wind_buffers > 0) // fill+queue new buffers
385 { 706 {
386 ALuint buffer; 707 if( ! m_streamer->addCommand(LLMediaBase::COMMAND_START))
387 alGetError(); /* clear error */
388 alGenBuffers(1,&buffer);
389 if((error=alGetError()) != AL_NO_ERROR)
390 { 708 {
391 llwarns << "LLAudioEngine_OpenAL::initWind() Error creating wind buffer: " << error << llendl; 709 llinfos << "attempting to pause stream failed!" << llendl;
392 break;
393 } 710 }
711 m_streamer->updateMedia();
712 }
713 #endif
714}
394 715
395 alBufferData(buffer,
396 AL_FORMAT_STEREO16,
397 mWindGen->windGenerate(winddata,
398 int(wind_gen_freq*wind_buffer_size_sec), 2),
399 int(2*wind_gen_freq*wind_buffer_size_sec*sizeof(S16)),
400 wind_gen_freq);
401 error = alGetError();
402 if(error != AL_NO_ERROR)
403 llwarns << "LLAudioEngine_OpenAL::updateWind() error swapping (bufferdata) buffers" << llendl;
404
405 alSourceQueueBuffers(wind_source, 1, &buffer);
406 error = alGetError();
407 if(error != AL_NO_ERROR)
408 llwarns << "LLAudioEngine_OpenAL::updateWind() error swapping (queuing) buffers" << llendl;
409 716
410 --empty_num_wind_buffers; 717int LLAudioEngine_OpenAL::isInternetStreamPlaying()
411 } 718{
412 719
413 int playing; 720 #if LL_GSTREAMER_ENABLED
414 alGetSourcei(wind_source, AL_SOURCE_STATE, &playing); 721 if(!m_streamer)
415 if(playing != AL_PLAYING) 722 return 0;
723
724 if(m_streamer->getStatus() == LLMediaBase::STATUS_STARTED)
416 { 725 {
417 alSourcePlay(wind_source); 726 return 1; // Active and playing
727 }
418 728
419 llinfos << "Wind had stopped - probably ran out of buffers - restarting: " << (unprocessed+empty_num_wind_buffers) << " now queued." << llendl; 729 if(m_streamer->getStatus() == LLMediaBase::STATUS_PAUSED)
730 {
731 return 2; // paused
420 } 732 }
733
734 #endif
735 return 0; // Stopped
736}
737
738
739void LLAudioEngine_OpenAL::getInternetStreamInfo(char* artist_out, char* title_out)
740{
741}
742
743
744void LLAudioEngine_OpenAL::setInternetStreamGain(F32 vol)
745{
746 #if LL_GSTREAMER_ENABLED
747 // Set the gstreamer volume here
748 if(!m_streamer)
749 return;
750
751 vol = llclamp(vol, 0.f, 1.f);
752 m_streamer->setVolume(vol);
753 m_streamer->updateMedia();
754 #endif
421} 755}
422 756
757
758const std::string& LLAudioEngine_OpenAL::getInternetStreamURL()
759{
760 return mInternetStreamURL;
761}
diff --git a/linden/indra/llaudio/audioengine_openal.h b/linden/indra/llaudio/audioengine_openal.h
index 6289f99..5d5c7d8 100644
--- a/linden/indra/llaudio/audioengine_openal.h
+++ b/linden/indra/llaudio/audioengine_openal.h
@@ -34,9 +34,13 @@
34#ifndef LL_AUDIOENGINE_OpenAL_H 34#ifndef LL_AUDIOENGINE_OpenAL_H
35#define LL_AUDIOENGINE_OpenAL_H 35#define LL_AUDIOENGINE_OpenAL_H
36 36
37#include <string>
38
37#include "audioengine.h" 39#include "audioengine.h"
38#include "listener_openal.h" 40#include "listener_openal.h"
39#include "windgen.h" 41#include "llmediamanager.h"
42#include "llmediaimplgstreamer.h"
43#include "llrand.h"
40 44
41class LLAudioEngine_OpenAL : public LLAudioEngine 45class LLAudioEngine_OpenAL : public LLAudioEngine
42{ 46{
@@ -44,23 +48,58 @@ class LLAudioEngine_OpenAL : public LLAudioEngine
44 LLAudioEngine_OpenAL(); 48 LLAudioEngine_OpenAL();
45 virtual ~LLAudioEngine_OpenAL(); 49 virtual ~LLAudioEngine_OpenAL();
46 50
47 virtual bool init(const S32 num_channels, void *user_data); 51 virtual BOOL init(const S32 num_channels);
52 virtual std::string getDriverName(bool verbose);
48 virtual void allocateListener(); 53 virtual void allocateListener();
49 54
50 virtual void shutdown(); 55 virtual void shutdown();
51 56
57 virtual void idle(F32 max_decode_time = 0.f);
58
52 void setInternalGain(F32 gain); 59 void setInternalGain(F32 gain);
53 60
54 LLAudioBuffer* createBuffer(); 61 LLAudioBuffer* createBuffer();
55 LLAudioChannel* createChannel(); 62 LLAudioChannel* createChannel();
56 63
57 /*virtual*/ void initWind(); 64 // Internet stream methods
58 /*virtual*/ void cleanupWind(); 65 virtual void initInternetStream();
59 /*virtual*/ void updateWind(LLVector3 direction, F32 camera_altitude); 66 virtual void startInternetStream(const std::string& url_cstr);
60 67 virtual void stopInternetStream();
61 private: 68 virtual void updateInternetStream();
69 virtual void pauseInternetStream(int pause);
70 virtual int isInternetStreamPlaying();
71 virtual void getInternetStreamInfo(char* artist, char* title);
72 virtual void setInternetStreamGain(F32 vol);
73 virtual const std::string& getInternetStreamURL();
74 virtual void InitStreamer();
75
76 void checkALError();
77
78 void initWind();
79 void cleanupWind();
80 void updateWind(LLVector3 direction, F32 camera_altitude);
81
82 protected:
83 static const S32 mNumWindBuffers=20;
84 static const S32 mSampleRate=44100;
85 static const S32 mBytesPerSample=4;
86 static const S32 mWindDataSize=8820; //44100 * 0.200 * 2 channels * 2 bytes per sample
87
88 BOOL mFirstWind;
89 ALuint mWindBuffers[mNumWindBuffers];
90 ALuint mWindSource;
91
92 F32 mTargetGain;
93 F32 mTargetFreq;
94 F32 mTargetPanGainR;
95 S16 mWindData[mWindDataSize];
96
97 std::string mInternetStreamURL;
62 void * windDSP(void *newbuffer, int length); 98 void * windDSP(void *newbuffer, int length);
63 LLWindGen<S16> *mWindGen; 99#if LL_GSTREAMER_ENABLED
100 LLMediaManagerData * mMedia_data;
101 LLMediaImplGStreamer * m_streamer;
102#endif
64}; 103};
65 104
66class LLAudioChannelOpenAL : public LLAudioChannel 105class LLAudioChannelOpenAL : public LLAudioChannel
@@ -78,7 +117,7 @@ class LLAudioChannelOpenAL : public LLAudioChannel
78 void update3DPosition(); 117 void update3DPosition();
79 void updateLoop(){}; 118 void updateLoop(){};
80 119
81 ALuint mALSource; 120 ALuint ALSource;
82}; 121};
83 122
84class LLAudioBufferOpenAL : public LLAudioBuffer{ 123class LLAudioBufferOpenAL : public LLAudioBuffer{
@@ -92,9 +131,8 @@ class LLAudioBufferOpenAL : public LLAudioBuffer{
92 friend class LLAudioChannelOpenAL; 131 friend class LLAudioChannelOpenAL;
93 protected: 132 protected:
94 void cleanup(); 133 void cleanup();
95 ALuint getBuffer() {return mALBuffer;} 134 ALuint getBuffer(){return ALBuffer;}
96 135 ALuint ALBuffer;
97 ALuint mALBuffer;
98}; 136};
99 137
100#endif 138#endif
diff --git a/linden/indra/llaudio/listener_openal.cpp b/linden/indra/llaudio/listener_openal.cpp
index e72b078..637af30 100644
--- a/linden/indra/llaudio/listener_openal.cpp
+++ b/linden/indra/llaudio/listener_openal.cpp
@@ -81,14 +81,18 @@ void LLListener_OpenAL::commitDeferredChanges(){
81} 81}
82 82
83void LLListener_OpenAL::setDopplerFactor(F32 factor){ 83void LLListener_OpenAL::setDopplerFactor(F32 factor){
84 // Effect is way too strong by default, scale it down here.
85 // Scaling the speed of sound up causes crashes.
86 factor *= 0.005f;
84 //llinfos << "LLListener_OpenAL::setDopplerFactor() : " << factor << llendl; 87 //llinfos << "LLListener_OpenAL::setDopplerFactor() : " << factor << llendl;
85 alDopplerFactor(factor); 88 alDopplerFactor(factor);
86} 89}
87 90
88F32 LLListener_OpenAL::getDopplerFactor(){ 91F32 LLListener_OpenAL::getDopplerFactor(){
89 ALfloat factor; 92 ALfloat factor;
90 factor = alGetFloat(AL_DOPPLER_FACTOR); 93 factor = 0.0f;
91 //llinfos << "LLListener_OpenAL::getDopplerFactor() : " << factor << llendl; 94 alDopplerFactor(factor);
95 llinfos << "LLListener_OpenAL::getDopplerFactor() : " << factor << llendl;
92 return factor; 96 return factor;
93} 97}
94 98
diff --git a/linden/indra/llaudio/listener_openal.h b/linden/indra/llaudio/listener_openal.h
index 33063bb..7551161 100644
--- a/linden/indra/llaudio/listener_openal.h
+++ b/linden/indra/llaudio/listener_openal.h
@@ -35,11 +35,18 @@
35 35
36#include "listener.h" 36#include "listener.h"
37 37
38#include "al.h" 38
39#include "alut.h" 39//#include "AL/al.h"
40#include "AL/alut.h"
40 41
41class LLListener_OpenAL : public LLListener 42class LLListener_OpenAL : public LLListener
42{ 43{
44 private:
45 protected:
46 public:
47
48 private:
49 protected:
43 public: 50 public:
44 LLListener_OpenAL(); 51 LLListener_OpenAL();
45 virtual ~LLListener_OpenAL(); 52 virtual ~LLListener_OpenAL();
@@ -52,8 +59,6 @@ class LLListener_OpenAL : public LLListener
52 59
53 virtual void setDopplerFactor(F32 factor); 60 virtual void setDopplerFactor(F32 factor);
54 virtual F32 getDopplerFactor(); 61 virtual F32 getDopplerFactor();
55
56 protected:
57}; 62};
58 63
59#endif 64#endif
diff --git a/linden/indra/llaudio/llaudiodecodemgr.cpp b/linden/indra/llaudio/llaudiodecodemgr.cpp
index 7cd48a9..cfd0500 100644
--- a/linden/indra/llaudio/llaudiodecodemgr.cpp
+++ b/linden/indra/llaudio/llaudiodecodemgr.cpp
@@ -374,16 +374,16 @@ BOOL LLVorbisDecodeState::finishDecode()
374 374
375 // write "data" chunk length, in little-endian format 375 // write "data" chunk length, in little-endian format
376 S32 data_length = mWAVBuffer.size() - WAV_HEADER_SIZE; 376 S32 data_length = mWAVBuffer.size() - WAV_HEADER_SIZE;
377 mWAVBuffer[40] = (data_length) & 0x000000FF; 377 mWAVBuffer[40] = (data_length - 8) & 0x000000FF;
378 mWAVBuffer[41] = (data_length >> 8) & 0x000000FF; 378 mWAVBuffer[41] = ((data_length - 8)>> 8) & 0x000000FF;
379 mWAVBuffer[42] = (data_length >> 16) & 0x000000FF; 379 mWAVBuffer[42] = ((data_length - 8)>> 16) & 0x000000FF;
380 mWAVBuffer[43] = (data_length >> 24) & 0x000000FF; 380 mWAVBuffer[43] = ((data_length - 8)>> 24) & 0x000000FF;
381
381 // write overall "RIFF" length, in little-endian format 382 // write overall "RIFF" length, in little-endian format
382 data_length += 36; 383 mWAVBuffer[4] = (data_length + 28) & 0x000000FF;
383 mWAVBuffer[4] = (data_length) & 0x000000FF; 384 mWAVBuffer[5] = ((data_length + 28) >> 8) & 0x000000FF;
384 mWAVBuffer[5] = (data_length >> 8) & 0x000000FF; 385 mWAVBuffer[6] = ((data_length + 28) >> 16) & 0x000000FF;
385 mWAVBuffer[6] = (data_length >> 16) & 0x000000FF; 386 mWAVBuffer[7] = ((data_length + 28) >> 24) & 0x000000FF;
386 mWAVBuffer[7] = (data_length >> 24) & 0x000000FF;
387 387
388 // 388 //
389 // FUDGECAKES!!! Vorbis encode/decode messes up loop point transitions (pop) 389 // FUDGECAKES!!! Vorbis encode/decode messes up loop point transitions (pop)
@@ -395,7 +395,8 @@ BOOL LLVorbisDecodeState::finishDecode()
395 S32 fade_length; 395 S32 fade_length;
396 char pcmout[4096]; /*Flawfinder: ignore*/ 396 char pcmout[4096]; /*Flawfinder: ignore*/
397 397
398 fade_length = llmin((S32)128,(S32)(data_length-36)/8); 398 fade_length = llmin((S32)128,(S32)(data_length)/8);
399
399 if((S32)mWAVBuffer.size() >= (WAV_HEADER_SIZE + 2* fade_length)) 400 if((S32)mWAVBuffer.size() >= (WAV_HEADER_SIZE + 2* fade_length))
400 { 401 {
401 memcpy(pcmout, &mWAVBuffer[WAV_HEADER_SIZE], (2 * fade_length)); /*Flawfinder: ignore*/ 402 memcpy(pcmout, &mWAVBuffer[WAV_HEADER_SIZE], (2 * fade_length)); /*Flawfinder: ignore*/
@@ -435,7 +436,7 @@ BOOL LLVorbisDecodeState::finishDecode()
435 } 436 }
436 } 437 }
437 438
438 if (36 == data_length) 439 if (0 == data_length)
439 { 440 {
440 llwarns << "BAD Vorbis decode in finishDecode!" << llendl; 441 llwarns << "BAD Vorbis decode in finishDecode!" << llendl;
441 mValid = FALSE; 442 mValid = FALSE;