aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llaudio/llaudioengine_fmod.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--linden/indra/llaudio/llaudioengine_fmod.cpp (renamed from linden/indra/llaudio/audioengine_fmod.cpp)361
1 files changed, 17 insertions, 344 deletions
diff --git a/linden/indra/llaudio/audioengine_fmod.cpp b/linden/indra/llaudio/llaudioengine_fmod.cpp
index 938c2aa..85ae863 100644
--- a/linden/indra/llaudio/audioengine_fmod.cpp
+++ b/linden/indra/llaudio/llaudioengine_fmod.cpp
@@ -32,8 +32,11 @@
32 32
33#include "linden_common.h" 33#include "linden_common.h"
34 34
35#include "audioengine_fmod.h" 35#include "llstreamingaudio.h"
36#include "listener_fmod.h" 36#include "llstreamingaudio_fmod.h"
37
38#include "llaudioengine_fmod.h"
39#include "lllistener_fmod.h"
37 40
38#include "llerror.h" 41#include "llerror.h"
39#include "llmath.h" 42#include "llmath.h"
@@ -46,6 +49,7 @@
46 49
47#include "sound_ids.h" 50#include "sound_ids.h"
48 51
52
49extern "C" { 53extern "C" {
50 void * F_CALLBACKAPI windCallback(void *originalbuffer, void *newbuffer, int length, void* userdata); 54 void * F_CALLBACKAPI windCallback(void *originalbuffer, void *newbuffer, int length, void* userdata);
51} 55}
@@ -53,35 +57,9 @@ extern "C" {
53FSOUND_DSPUNIT *gWindDSP = NULL; 57FSOUND_DSPUNIT *gWindDSP = NULL;
54 58
55 59
56// Safe strcpy
57#if 0 //(unused) //LL_WINDOWS || LL_LINUX
58static size_t strlcpy( char* dest, const char* src, size_t dst_size )
59{
60 size_t source_len = 0;
61 size_t min_len = 0;
62 if( dst_size > 0 )
63 {
64 if( src )
65 {
66 source_len = strlen(src); /*Flawfinder: ignore*/
67 min_len = llmin( dst_size - 1, source_len );
68 memcpy(dest, src, min_len); /*Flawfinder: ignore*/
69 }
70 dest[min_len] = '\0';
71 }
72 return source_len;
73}
74#else
75// apple ships with the non-standard strlcpy in /usr/include/string.h:
76// size_t strlcpy(char *, const char *, size_t);
77#endif
78
79
80LLAudioEngine_FMOD::LLAudioEngine_FMOD() 60LLAudioEngine_FMOD::LLAudioEngine_FMOD()
81{ 61{
82 mInited = false; 62 mInited = false;
83 mCurrentInternetStreamp = NULL;
84 mInternetStreamChannel = -1;
85 mWindGen = NULL; 63 mWindGen = NULL;
86} 64}
87 65
@@ -93,8 +71,6 @@ LLAudioEngine_FMOD::~LLAudioEngine_FMOD()
93 71
94bool LLAudioEngine_FMOD::init(const S32 num_channels, void* userdata) 72bool LLAudioEngine_FMOD::init(const S32 num_channels, void* userdata)
95{ 73{
96 mFadeIn = -10000;
97
98 LLAudioEngine::init(num_channels, userdata); 74 LLAudioEngine::init(num_channels, userdata);
99 75
100 // Reserve one extra channel for the http stream. 76 // Reserve one extra channel for the http stream.
@@ -241,7 +217,9 @@ bool LLAudioEngine_FMOD::init(const S32 num_channels, void* userdata)
241 217
242#endif 218#endif
243 219
244 initInternetStream(); 220 // set up our favourite FMOD-native streaming audio implementation if none has already been added
221 if (!getStreamingAudioImpl()) // no existing implementation added
222 setStreamingAudioImpl(new LLStreamingAudio_FMOD());
245 223
246 LL_DEBUGS("AppInit") << "LLAudioEngine_FMOD::init() FMOD initialized correctly" << LL_ENDL; 224 LL_DEBUGS("AppInit") << "LLAudioEngine_FMOD::init() FMOD initialized correctly" << LL_ENDL;
247 225
@@ -296,13 +274,13 @@ void LLAudioEngine_FMOD::shutdown()
296} 274}
297 275
298 276
299LLAudioBuffer *LLAudioEngine_FMOD::createBuffer() 277LLAudioBuffer * LLAudioEngine_FMOD::createBuffer()
300{ 278{
301 return new LLAudioBufferFMOD(); 279 return new LLAudioBufferFMOD();
302} 280}
303 281
304 282
305LLAudioChannel *LLAudioEngine_FMOD::createChannel() 283LLAudioChannel * LLAudioEngine_FMOD::createChannel()
306{ 284{
307 return new LLAudioChannelFMOD(); 285 return new LLAudioChannelFMOD();
308} 286}
@@ -432,10 +410,12 @@ void LLAudioEngine_FMOD::setInternalGain(F32 gain)
432 gain = llclamp( gain, 0.0f, 1.0f ); 410 gain = llclamp( gain, 0.0f, 1.0f );
433 FSOUND_SetSFXMasterVolume( llround( 255.0f * gain ) ); 411 FSOUND_SetSFXMasterVolume( llround( 255.0f * gain ) );
434 412
435 if ( mInternetStreamChannel != -1 ) 413 LLStreamingAudioInterface *saimpl = getStreamingAudioImpl();
414 if ( saimpl )
436 { 415 {
437 F32 clamp_internet_stream_gain = llclamp( mInternetStreamGain, 0.0f, 1.0f ); 416 // fmod likes its streaming audio channel gain re-asserted after
438 FSOUND_SetVolumeAbsolute( mInternetStreamChannel, llround( 255.0f * clamp_internet_stream_gain ) ); 417 // master volume change.
418 saimpl->setGain(saimpl->getGain());
439 } 419 }
440} 420}
441 421
@@ -660,7 +640,7 @@ bool LLAudioBufferFMOD::loadWAV(const std::string& filename)
660 return false; 640 return false;
661 } 641 }
662 642
663 if (!LLAPRFile::isExist(filename, NULL, LL_APR_RPB)) 643 if (!LLAPRFile::isExist(filename, LL_APR_RPB))
664 { 644 {
665 // File not found, abort. 645 // File not found, abort.
666 return false; 646 return false;
@@ -752,313 +732,6 @@ void LLAudioBufferFMOD::set3DMode(bool use3d)
752} 732}
753 733
754 734
755
756//---------------------------------------------------------------------------
757// Internet Streaming
758//---------------------------------------------------------------------------
759void LLAudioEngine_FMOD::initInternetStream()
760{
761 // Number of milliseconds of audio to buffer for the audio card.
762 // Must be larger than the usual Second Life frame stutter time.
763 FSOUND_Stream_SetBufferSize(200);
764
765 // Here's where we set the size of the network buffer and some buffering
766 // parameters. In this case we want a network buffer of 16k, we want it
767 // to prebuffer 40% of that when we first connect, and we want it
768 // to rebuffer 80% of that whenever we encounter a buffer underrun.
769
770 // Leave the net buffer properties at the default.
771 //FSOUND_Stream_Net_SetBufferProperties(20000, 40, 80);
772 mInternetStreamURL.clear();
773}
774
775
776void LLAudioEngine_FMOD::startInternetStream(const std::string& url)
777{
778 if (!mInited)
779 {
780 llwarns << "startInternetStream before audio initialized" << llendl;
781 return;
782 }
783
784 // "stop" stream but don't clear url, etc. in calse url == mInternetStreamURL
785 stopInternetStream();
786 if (!url.empty())
787 {
788 llinfos << "Starting internet stream: " << url << llendl;
789 mCurrentInternetStreamp = new LLAudioStreamFMOD(url);
790 mInternetStreamURL = url;
791 }
792 else
793 {
794 llinfos << "Set internet stream to null" << llendl;
795 mInternetStreamURL.clear();
796 }
797}
798
799
800signed char F_CALLBACKAPI LLAudioEngine_FMOD::callbackMetaData(char *name, char *value, void *userdata)
801{
802 /*
803 LLAudioEngine_FMOD* self = (LLAudioEngine_FMOD*)userdata;
804
805 if (!strcmp("ARTIST", name))
806 {
807 strlcpy(self->mInternetStreamArtist, value, 256);
808 self->mInternetStreamNewMetaData = true;
809 return true;
810 }
811
812 if (!strcmp("TITLE", name))
813 {
814 strlcpy(self->mInternetStreamTitle, value, 256);
815 self->mInternetStreamNewMetaData = true;
816 return true;
817 }
818 */
819
820 return true;
821}
822
823
824void LLAudioEngine_FMOD::updateInternetStream()
825{
826 // Kill dead internet streams, if possible
827 std::list<LLAudioStreamFMOD *>::iterator iter;
828 for (iter = mDeadStreams.begin(); iter != mDeadStreams.end();)
829 {
830 LLAudioStreamFMOD *streamp = *iter;
831 if (streamp->stopStream())
832 {
833 llinfos << "Closed dead stream" << llendl;
834 delete streamp;
835 mDeadStreams.erase(iter++);
836 }
837 else
838 {
839 iter++;
840 }
841 }
842
843 // Don't do anything if there are no streams playing
844 if (!mCurrentInternetStreamp)
845 {
846 return;
847 }
848
849 int open_state = mCurrentInternetStreamp->getOpenState();
850
851 if (!open_state)
852 {
853 // Stream is live
854
855
856 // start the stream if it's ready
857 if (mInternetStreamChannel < 0)
858 {
859 mInternetStreamChannel = mCurrentInternetStreamp->startStream();
860
861 if (mInternetStreamChannel != -1)
862 {
863 // Reset volume to previously set volume
864 setInternetStreamGain(mInternetStreamGain);
865 FSOUND_SetPaused(mInternetStreamChannel, false);
866 //FSOUND_Stream_Net_SetMetadataCallback(mInternetStream, callbackMetaData, this);
867 }
868 }
869 }
870
871 switch(open_state)
872 {
873 default:
874 case 0:
875 // success
876 break;
877 case -1:
878 // stream handle is invalid
879 llwarns << "InternetStream - invalid handle" << llendl;
880 stopInternetStream();
881 return;
882 case -2:
883 // opening
884 //strlcpy(mInternetStreamArtist, "Opening", 256);
885 break;
886 case -3:
887 // failed to open, file not found, perhaps
888 llwarns << "InternetSteam - failed to open" << llendl;
889 stopInternetStream();
890 return;
891 case -4:
892 // connecting
893 //strlcpy(mInternetStreamArtist, "Connecting", 256);
894 break;
895 case -5:
896 // buffering
897 //strlcpy(mInternetStreamArtist, "Buffering", 256);
898 break;
899 }
900
901}
902
903void LLAudioEngine_FMOD::stopInternetStream()
904{
905 if (mInternetStreamChannel != -1)
906 {
907 FSOUND_SetPaused(mInternetStreamChannel, true);
908 FSOUND_SetPriority(mInternetStreamChannel, 0);
909 mInternetStreamChannel = -1;
910 }
911
912 if (mCurrentInternetStreamp)
913 {
914 llinfos << "Stopping internet stream: " << mCurrentInternetStreamp->getURL() << llendl;
915 if (mCurrentInternetStreamp->stopStream())
916 {
917 delete mCurrentInternetStreamp;
918 }
919 else
920 {
921 llwarns << "Pushing stream to dead list: " << mCurrentInternetStreamp->getURL() << llendl;
922 mDeadStreams.push_back(mCurrentInternetStreamp);
923 }
924 mCurrentInternetStreamp = NULL;
925 //mInternetStreamURL.clear();
926 }
927}
928
929void LLAudioEngine_FMOD::pauseInternetStream(int pause)
930{
931 if (pause < 0)
932 {
933 pause = mCurrentInternetStreamp ? 1 : 0;
934 }
935
936 if (pause)
937 {
938 if (mCurrentInternetStreamp)
939 {
940 stopInternetStream();
941 }
942 }
943 else
944 {
945 startInternetStream(mInternetStreamURL);
946 }
947}
948
949
950// A stream is "playing" if it has been requested to start. That
951// doesn't necessarily mean audio is coming out of the speakers.
952int LLAudioEngine_FMOD::isInternetStreamPlaying()
953{
954 if (mCurrentInternetStreamp)
955 {
956 return 1; // Active and playing
957 }
958 else if (!mInternetStreamURL.empty())
959 {
960 return 2; // "Paused"
961 }
962 else
963 {
964 return 0;
965 }
966}
967
968
969void LLAudioEngine_FMOD::setInternetStreamGain(F32 vol)
970{
971 mInternetStreamGain = vol;
972
973 if (mInternetStreamChannel != -1)
974 {
975 vol = llclamp(vol, 0.f, 1.f);
976 int vol_int = llround(vol * 255.f);
977 FSOUND_SetVolumeAbsolute(mInternetStreamChannel, vol_int);
978 }
979}
980
981
982LLAudioStreamFMOD::LLAudioStreamFMOD(const std::string& url) :
983 mInternetStream(NULL),
984 mReady(false)
985{
986 mInternetStreamURL = url;
987 mInternetStream = FSOUND_Stream_Open(url.c_str(), FSOUND_NORMAL | FSOUND_NONBLOCKING, 0, 0);
988 if (!mInternetStream)
989 {
990 llwarns << "Couldn't open fmod stream, error "
991 << FMOD_ErrorString(FSOUND_GetError())
992 << llendl;
993 mReady = false;
994 return;
995 }
996
997 mReady = true;
998}
999
1000int LLAudioStreamFMOD::startStream()
1001{
1002 // We need a live and opened stream before we try and play it.
1003 if (!mInternetStream || getOpenState())
1004 {
1005 llwarns << "No internet stream to start playing!" << llendl;
1006 return -1;
1007 }
1008
1009 // Make sure the stream is set to 2D mode.
1010 FSOUND_Stream_SetMode(mInternetStream, FSOUND_2D);
1011
1012 return FSOUND_Stream_PlayEx(FSOUND_FREE, mInternetStream, NULL, true);
1013}
1014
1015bool LLAudioStreamFMOD::stopStream()
1016{
1017 if (mInternetStream)
1018 {
1019 int read_percent = 0;
1020 int status = 0;
1021 int bitrate = 0;
1022 unsigned int flags = 0x0;
1023 FSOUND_Stream_Net_GetStatus(mInternetStream, &status, &read_percent, &bitrate, &flags);
1024
1025 bool close = true;
1026 switch (status)
1027 {
1028 case FSOUND_STREAM_NET_CONNECTING:
1029 close = false;
1030 break;
1031 case FSOUND_STREAM_NET_NOTCONNECTED:
1032 case FSOUND_STREAM_NET_BUFFERING:
1033 case FSOUND_STREAM_NET_READY:
1034 case FSOUND_STREAM_NET_ERROR:
1035 default:
1036 close = true;
1037 }
1038
1039 if (close)
1040 {
1041 FSOUND_Stream_Close(mInternetStream);
1042 mInternetStream = NULL;
1043 return true;
1044 }
1045 else
1046 {
1047 return false;
1048 }
1049 }
1050 else
1051 {
1052 return true;
1053 }
1054}
1055
1056int LLAudioStreamFMOD::getOpenState()
1057{
1058 int open_state = FSOUND_Stream_GetOpenState(mInternetStream);
1059 return open_state;
1060}
1061
1062void * F_CALLBACKAPI windCallback(void *originalbuffer, void *newbuffer, int length, void* userdata) 735void * F_CALLBACKAPI windCallback(void *originalbuffer, void *newbuffer, int length, void* userdata)
1063{ 736{
1064 // originalbuffer = fmod's original mixbuffer. 737 // originalbuffer = fmod's original mixbuffer.