aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llaudio/audioengine_openal.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'linden/indra/llaudio/audioengine_openal.cpp')
-rw-r--r--linden/indra/llaudio/audioengine_openal.cpp689
1 files changed, 514 insertions, 175 deletions
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}