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