diff --git a/indra/llaudio/llaudioengine_fmodex.cpp b/indra/llaudio/llaudioengine_fmodex.cpp index b39d7f8be..67d720c21 100644 --- a/indra/llaudio/llaudioengine_fmodex.cpp +++ b/indra/llaudio/llaudioengine_fmodex.cpp @@ -72,12 +72,13 @@ bool attemptDelayLoad() FMOD_RESULT F_CALLBACK windCallback(FMOD_DSP_STATE *dsp_state, float *inbuffer, float *outbuffer, unsigned int length, int inchannels, int outchannels); -LLAudioEngine_FMODEX::LLAudioEngine_FMODEX() +LLAudioEngine_FMODEX::LLAudioEngine_FMODEX(bool enable_profiler) { mInited = false; mWindGen = NULL; mWindDSP = NULL; mSystem = NULL; + mEnableProfiler = enable_profiler; } @@ -145,7 +146,7 @@ bool LLAudioEngine_FMODEX::init(const S32 num_channels, void* userdata) Set the user selected speaker mode. */ result = mSystem->setSpeakerMode(speakermode); - Check_FMOD_Error(result, "FMOD::System::getDriverCaps"); + Check_FMOD_Error(result, "FMOD::System::setSpeakerMode"); if (caps & FMOD_CAPS_HARDWARE_EMULATED) { /* @@ -170,11 +171,13 @@ bool LLAudioEngine_FMODEX::init(const S32 num_channels, void* userdata) } #endif //LL_WINDOWS - // Reserve one extra channel for the http stream. - result = mSystem->setHardwareChannels(num_channels + 1); + // Only static sounds (not wind, not stream) can possibly be hardware. Only reserve for those. + result = mSystem->setHardwareChannels(num_channels); Check_FMOD_Error(result,"FMOD::System::setHardwareChannels"); U32 fmod_flags = FMOD_INIT_NORMAL; + if(mEnableProfiler) + fmod_flags |= FMOD_INIT_ENABLE_PROFILE; #if LL_LINUX // If we don't set an output method, Linux FMOD always @@ -301,6 +304,13 @@ bool LLAudioEngine_FMODEX::init(const S32 num_channels, void* userdata) if (!getStreamingAudioImpl()) // no existing implementation added setStreamingAudioImpl(new LLStreamingAudio_FMODEX(mSystem)); + result = mSystem->createSoundGroup("World Sounds", &mWorldSoundGroup); + if(!Check_FMOD_Error(result, "Error creating 'World Sounds' group.")) + { + mWorldSoundGroup->setMaxAudible(num_channels); + mWorldSoundGroup->setMaxAudibleBehavior(FMOD_SOUNDGROUP_BEHAVIOR_MUTE); + } + LL_DEBUGS("AppInit") << "LLAudioEngine_FMODEX::init() FMOD initialized correctly" << LL_ENDL; mInited = true; @@ -352,63 +362,17 @@ void LLAudioEngine_FMODEX::shutdown() LLAudioBuffer * LLAudioEngine_FMODEX::createBuffer() { - return new LLAudioBufferFMODEX(mSystem); + return new LLAudioBufferFMODEX(this); } LLAudioChannel * LLAudioEngine_FMODEX::createChannel() { - return new LLAudioChannelFMODEX(mSystem); + return new LLAudioChannelFMODEX(this); } bool LLAudioEngine_FMODEX::initWind() { - if (!mWindGen) - { - int samplerate; - FMOD_SOUND_FORMAT format; - mSystem->getSoftwareFormat(&samplerate,&format,NULL,NULL,NULL,NULL); - - //May need to check format. eg, PCM16 may require 16bit LLWindGen. - - /*bool enable; - - FMOD_SOUND_FORMAT format; - mSystem->getFormat(0,&format,0,0); - switch (format) - { - case FSOUND_MIXER_MMXP5: - case FSOUND_MIXER_MMXP6: - case FSOUND_MIXER_QUALITY_MMXP5: - case FSOUND_MIXER_QUALITY_MMXP6: - enable = (typeid(MIXBUFFERFORMAT) == typeid(S16)); - break; - case FSOUND_MIXER_BLENDMODE: - enable = (typeid(MIXBUFFERFORMAT) == typeid(S32)); - break; - case FSOUND_MIXER_QUALITY_FPU: - enable = (typeid(MIXBUFFERFORMAT) == typeid(F32)); - break; - default: - // FSOUND_GetMixer() does not return a valid mixer type on Darwin - LL_INFOS("AppInit") << "Unknown FMOD mixer type, assuming default" << LL_ENDL; - enable = true; - break; - } - - if (enable) - { - mWindGen = new LLWindGen(FSOUND_GetOutputRate()); - } - else - { - LL_WARNS("AppInit") << "Incompatible FMOD mixer type, wind noise disabled" << LL_ENDL; - }*/ - - - mWindGen = new LLWindGen(samplerate); - } - mNextWindUpdate = 0.0; if (!mWindDSP) @@ -417,15 +381,22 @@ bool LLAudioEngine_FMODEX::initWind() memset(&dspdesc, 0, sizeof(FMOD_DSP_DESCRIPTION)); //Set everything to zero strncpy(dspdesc.name,"Wind Unit", sizeof(dspdesc.name)); //Set name to "Wind Unit" dspdesc.read = &windCallback; //Assign callback. - dspdesc.userdata = (void*)mWindGen; - Check_FMOD_Error(mSystem->createDSP(&dspdesc, &mWindDSP), "FMOD::createDSP"); + if(Check_FMOD_Error(mSystem->createDSP(&dspdesc, &mWindDSP), "FMOD::createDSP")) + return false; + + if(mWindGen) + delete mWindGen; + + float frequency = 44100; + mWindDSP->getDefaults(&frequency,0,0,0); + mWindGen = new LLWindGen((U32)frequency); + mWindDSP->setUserData((void*)mWindGen); } if (mWindDSP) { - mSystem->addDSP(mWindDSP, NULL); + mSystem->playDSP(FMOD_CHANNEL_FREE, mWindDSP, false, 0); return true; } - return false; } @@ -438,6 +409,11 @@ void LLAudioEngine_FMODEX::cleanupWind() mWindDSP->release(); mWindDSP = NULL; } + if(mWorldSoundGroup) + { + mWorldSoundGroup->release(); + mWorldSoundGroup = NULL; + } delete mWindGen; mWindGen = NULL; @@ -504,7 +480,7 @@ void LLAudioEngine_FMODEX::setInternalGain(F32 gain) // LLAudioChannelFMODEX implementation // -LLAudioChannelFMODEX::LLAudioChannelFMODEX(FMOD::System *system) : LLAudioChannel(), mSystem(system), mChannelp(NULL), mLastSamplePos(0) +LLAudioChannelFMODEX::LLAudioChannelFMODEX(LLAudioEngine_FMODEX *audioengine) : LLAudioChannel(), mEnginep(audioengine), mChannelp(NULL), mLastSamplePos(0) { } @@ -537,8 +513,16 @@ bool LLAudioChannelFMODEX::updateBuffer() // Actually play the sound. Start it off paused so we can do all the necessary // setup. - FMOD_RESULT result = mSystem->playSound(FMOD_CHANNEL_FREE, soundp, true, &mChannelp); - Check_FMOD_Error(result, "FMOD::System::playSound"); + FMOD_RESULT result = getEngine()->getSystem()->playSound(FMOD_CHANNEL_FREE, soundp, true, &mChannelp); + if(!Check_FMOD_Error(result, "FMOD::System::playSound") && + mCurrentSourcep && + (mCurrentSourcep->getType() == LLAudioEngine::AUDIO_TYPE_SFX || + mCurrentSourcep->getType() == LLAudioEngine::AUDIO_TYPE_AMBIENT)) + { + FMOD::SoundGroup *world_group = getEngine()->getWorldSoundGroup(); + if(world_group) + soundp->setSoundGroup(world_group); + } //llinfos << "Setting up channel " << std::hex << mChannelID << std::dec << llendl; } @@ -696,7 +680,7 @@ bool LLAudioChannelFMODEX::isPlaying() // -LLAudioBufferFMODEX::LLAudioBufferFMODEX(FMOD::System *system) : mSystem(system), mSoundp(NULL) +LLAudioBufferFMODEX::LLAudioBufferFMODEX(LLAudioEngine_FMODEX *audioengine) : mEnginep(audioengine), mSoundp(NULL) { } @@ -734,45 +718,16 @@ bool LLAudioBufferFMODEX::loadWAV(const std::string& filename) mSoundp = NULL; } - bool creation_attempted = false; - FMOD_RESULT result = FMOD_OK; - - FMOD_MODE base_mode = FMOD_SOFTWARE | FMOD_LOOP_NORMAL; + FMOD_MODE base_mode = FMOD_LOOP_NORMAL; // Load up the wav file into an fmod sample #if LL_WINDOWS - // MikeS. - Loading the sound file manually and then handing it over to FMOD, - // since FMOD uses posix IO internally, - // which doesn't work with unicode file paths. - LLFILE* sound_file = LLFile::fopen(filename,"rb"); /* Flawfinder: ignore */ - if (sound_file) - { - fseek(sound_file,0,SEEK_END); - U32 file_length = ftell(sound_file); //Find the length of the file by seeking to the end and getting the offset - size_t read_count; - fseek(sound_file,0,SEEK_SET); //Seek back to the beginning - char* buffer = new char[file_length]; - llassert(buffer); - read_count = fread((void*)buffer,file_length,1,sound_file);//Load it.. - if(ferror(sound_file)==0 && (read_count == 1)) - {//No read error, and we got 1 chunk of our size... - - FMOD_CREATESOUNDEXINFO info; - memset(&info, 0, sizeof(info)); - info.cbsize = sizeof(info); - info.length = file_length; - result = mSystem->createSound(buffer, base_mode | FMOD_OPENMEMORY , &info, &mSoundp); - creation_attempted = true; - } - delete[] buffer; - fclose(sound_file); - } + FMOD_RESULT result = getEngine()->getSystem()->createSound((const char*)utf8str_to_utf16str(filename).c_str(), base_mode | FMOD_UNICODE, 0, &mSoundp); #else - result = mSystem->createSound(filename.c_str(), base_mode, 0, &mSoundp); - creation_attempted = true; + FMOD_RESULT result = getEngine()->getSystem()->createSound(filename.c_str(), base_mode | FMOD_SOFTWARE, 0, &mSoundp); #endif - if (creation_attempted && result != FMOD_OK) + if (result != FMOD_OK) { // We failed to load the file for some reason. llwarns << "Could not load data '" << filename << "': " << FMOD_ErrorString(result) << llendl; diff --git a/indra/llaudio/llaudioengine_fmodex.h b/indra/llaudio/llaudioengine_fmodex.h index 4fb2dccd8..89d75be2e 100644 --- a/indra/llaudio/llaudioengine_fmodex.h +++ b/indra/llaudio/llaudioengine_fmodex.h @@ -46,13 +46,14 @@ namespace FMOD class Channel; class Sound; class DSP; + class SoundGroup; } //Interfaces class LLAudioEngine_FMODEX : public LLAudioEngine { public: - LLAudioEngine_FMODEX(); + LLAudioEngine_FMODEX(bool enable_profiler); virtual ~LLAudioEngine_FMODEX(); // initialization/startup/shutdown @@ -69,6 +70,8 @@ public: typedef F32 MIXBUFFERFORMAT; + FMOD::System *getSystem() const {return mSystem;} + FMOD::SoundGroup *getWorldSoundGroup() const {return mWorldSoundGroup;} protected: /*virtual*/ LLAudioBuffer *createBuffer(); // Get a free buffer, or flush an existing one if you have to. /*virtual*/ LLAudioChannel *createChannel(); // Create a new audio channel. @@ -77,20 +80,19 @@ protected: bool mInited; - // On Windows, userdata is the HWND of the application window. - void* mUserData; - LLWindGen *mWindGen; FMOD::DSP *mWindDSP; FMOD::System *mSystem; + FMOD::SoundGroup *mWorldSoundGroup; + bool mEnableProfiler; }; class LLAudioChannelFMODEX : public LLAudioChannel { public: - LLAudioChannelFMODEX(FMOD::System *system); + LLAudioChannelFMODEX(LLAudioEngine_FMODEX *audioengine); virtual ~LLAudioChannelFMODEX(); protected: @@ -105,7 +107,8 @@ protected: void set3DMode(bool use3d); protected: - FMOD::System *mSystem; + LLAudioEngine_FMODEX *getEngine() const {return mEnginep;} + LLAudioEngine_FMODEX *mEnginep; FMOD::Channel *mChannelp; S32 mLastSamplePos; }; @@ -114,7 +117,7 @@ protected: class LLAudioBufferFMODEX : public LLAudioBuffer { public: - LLAudioBufferFMODEX(FMOD::System *system); + LLAudioBufferFMODEX(LLAudioEngine_FMODEX *audioengine); virtual ~LLAudioBufferFMODEX(); /*virtual*/ bool loadWAV(const std::string& filename); @@ -123,8 +126,9 @@ public: void set3DMode(bool use3d); protected: - FMOD::Sound *getSound() { return mSoundp; } - FMOD::System *mSystem; + LLAudioEngine_FMODEX *getEngine() const {return mEnginep;} + LLAudioEngine_FMODEX *mEnginep; + FMOD::Sound *getSound() const{ return mSoundp; } FMOD::Sound *mSoundp; }; diff --git a/indra/newview/app_settings/settings_sh.xml b/indra/newview/app_settings/settings_sh.xml index f7e90e784..d1c5f640b 100644 --- a/indra/newview/app_settings/settings_sh.xml +++ b/indra/newview/app_settings/settings_sh.xml @@ -1,7 +1,17 @@ - + SHEnableFMODExProfiler + + Comment + Enable profiler tool if using FMOD Ex + Persist + 1 + Type + Boolean + Value + 0 + SHAllowScriptCommands Comment diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 3063135fe..a23c3ddd1 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -677,7 +677,7 @@ bool idle_startup() #endif // !LL_WINDOWS ) { - gAudiop = (LLAudioEngine *) new LLAudioEngine_FMODEX(); + gAudiop = (LLAudioEngine *) new LLAudioEngine_FMODEX(gSavedSettings.getBOOL("SHEnableFMODExProfiler")); } #endif