From 041d5a5c0be1e79d28cbe84fdf78eeea2d17600a Mon Sep 17 00:00:00 2001 From: Ansariel Date: Thu, 9 Apr 2020 00:43:56 +0200 Subject: [PATCH] Sync FMOD Studio implementation with upstream so we can keep our version when merging with upstream --- indra/llaudio/llaudioengine_fmodstudio.cpp | 1162 +++++++++-------- indra/llaudio/llaudioengine_fmodstudio.h | 14 +- indra/llaudio/lllistener_fmodstudio.cpp | 84 +- indra/llaudio/lllistener_fmodstudio.h | 37 +- indra/llaudio/llstreamingaudio_fmodstudio.cpp | 758 +++++------ indra/llaudio/llstreamingaudio_fmodstudio.h | 62 +- 6 files changed, 1079 insertions(+), 1038 deletions(-) diff --git a/indra/llaudio/llaudioengine_fmodstudio.cpp b/indra/llaudio/llaudioengine_fmodstudio.cpp index 48203b0371..90525d0549 100644 --- a/indra/llaudio/llaudioengine_fmodstudio.cpp +++ b/indra/llaudio/llaudioengine_fmodstudio.cpp @@ -1,11 +1,11 @@ /** * @file audioengine_fmodstudio.cpp * @brief Implementation of LLAudioEngine class abstracting the audio - * support as a FMOD Studio implementation + * support as a FMODSTUDIO implementation * - * $LicenseInfo:firstyear=2014&license=viewerlgpl$ + * $LicenseInfo:firstyear=2020&license=viewerlgpl$ * Second Life Viewer Source Code - * Copyright (C) 2014, Linden Research, Inc. + * Copyright (C) 2020, Linden Research, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -37,8 +37,8 @@ #include "llmath.h" #include "llrand.h" -#include "fmod.hpp" -#include "fmod_errors.h" +#include "fmodstudio/fmod.hpp" +#include "fmodstudio/fmod_errors.h" #include "lldir.h" #include "sound_ids.h" @@ -47,498 +47,532 @@ const U32 EXTRA_SOUND_CHANNELS = 10; -FMOD_RESULT F_CALLBACK windDSPCallback(FMOD_DSP_STATE *dsp_state, float *inbuffer, float *outbuffer, unsigned int length, int inchannels, int *outchannels); +FMOD_RESULT F_CALLBACK windCallback(FMOD_DSP_STATE *dsp_state, float *inbuffer, float *outbuffer, unsigned int length, int inchannels, int *outchannels); FMOD::ChannelGroup *LLAudioEngine_FMODSTUDIO::mChannelGroups[LLAudioEngine::AUDIO_TYPE_COUNT] = {0}; static inline bool Check_FMOD_Error(FMOD_RESULT result, const char *string) { - if (result == FMOD_OK) - { - return false; - } + if (result == FMOD_OK) + { + return false; + } - if (result != FMOD_ERR_INVALID_HANDLE) - { - LL_WARNS() << string << " Error: " << FMOD_ErrorString(result) << LL_ENDL; - } - else - { - LL_DEBUGS() << string << " Error: " << FMOD_ErrorString(result) << LL_ENDL; - } + if (result != FMOD_ERR_INVALID_HANDLE) + { + LL_WARNS() << string << " Error: " << FMOD_ErrorString(result) << LL_ENDL; + } + else + { + LL_DEBUGS() << string << " Error: " << FMOD_ErrorString(result) << LL_ENDL; + } - return true; + return true; } LLUUID FMOD_GUID_to_LLUUID(FMOD_GUID guid) { - return LLUUID(llformat("%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", guid.Data1, guid.Data2, guid.Data3, - guid.Data4[0], guid.Data4[1], guid.Data4[2], guid.Data4[3], guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7])); + return LLUUID(llformat("%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", guid.Data1, guid.Data2, guid.Data3, + guid.Data4[0], guid.Data4[1], guid.Data4[2], guid.Data4[3], guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7])); } void set_device(FMOD::System* system, const LLUUID& device_uuid) { - LL_INFOS() << "LLAudioEngine_FMODSTUDIO::setDevice with device_uuid=" << device_uuid << LL_ENDL; + LL_INFOS() << "LLAudioEngine_FMODSTUDIO::setDevice with device_uuid=" << device_uuid << LL_ENDL; - int drivercount; - if (!Check_FMOD_Error(system->getNumDrivers(&drivercount), "FMOD::System::getNumDrivers") && drivercount > 0) - { - if (device_uuid.isNull()) - { - LL_INFOS() << "Setting driver \"Default\"" << LL_ENDL; - Check_FMOD_Error(system->setDriver(0), "FMOD::System::setDriver"); - } - else - { - FMOD_GUID guid; - int r_samplerate, r_channels; + int drivercount; + if (!Check_FMOD_Error(system->getNumDrivers(&drivercount), "FMOD::System::getNumDrivers") && drivercount > 0) + { + if (device_uuid.isNull()) + { + LL_INFOS() << "Setting driver \"Default\"" << LL_ENDL; + Check_FMOD_Error(system->setDriver(0), "FMOD::System::setDriver"); + } + else + { + FMOD_GUID guid; + int r_samplerate, r_channels; - for (int i = 0; i < drivercount; ++i) - { - if (!Check_FMOD_Error(system->getDriverInfo(i, NULL, 0, &guid, &r_samplerate, NULL, &r_channels), "FMOD::System::getDriverInfo")) - { - LLUUID driver_guid = FMOD_GUID_to_LLUUID(guid); + for (int i = 0; i < drivercount; ++i) + { + if (!Check_FMOD_Error(system->getDriverInfo(i, NULL, 0, &guid, &r_samplerate, NULL, &r_channels), "FMOD::System::getDriverInfo")) + { + LLUUID driver_guid = FMOD_GUID_to_LLUUID(guid); - if (driver_guid == device_uuid) - { - LL_INFOS() << "Setting driver " << i << ": " << driver_guid << LL_ENDL; - Check_FMOD_Error(system->setDriver(i), "FMOD::System::setDriver"); - return; - } - } - } + if (driver_guid == device_uuid) + { + LL_INFOS() << "Setting driver " << i << ": " << driver_guid << LL_ENDL; + Check_FMOD_Error(system->setDriver(i), "FMOD::System::setDriver"); + return; + } + } + } - LL_INFOS() << "Device not available (anymore) - falling back to default" << LL_ENDL; - Check_FMOD_Error(system->setDriver(0), "FMOD::System::setDriver"); - } - } + LL_INFOS() << "Device not available (anymore) - falling back to default" << LL_ENDL; + Check_FMOD_Error(system->setDriver(0), "FMOD::System::setDriver"); + } + } } FMOD_RESULT F_CALLBACK systemCallback(FMOD_SYSTEM *system, FMOD_SYSTEM_CALLBACK_TYPE type, void *commanddata1, void *commanddata2, void* userdata) { - FMOD::System* sys = (FMOD::System*)system; - LLAudioEngine_FMODSTUDIO* audio_engine = (LLAudioEngine_FMODSTUDIO*)userdata; + FMOD::System* sys = (FMOD::System*)system; + LLAudioEngine_FMODSTUDIO* audio_engine = (LLAudioEngine_FMODSTUDIO*)userdata; - switch (type) - { - case FMOD_SYSTEM_CALLBACK_DEVICELISTCHANGED: - LL_DEBUGS() << "FMOD system callback FMOD_SYSTEM_CALLBACK_DEVICELISTCHANGED" << LL_ENDL; - if (sys && audio_engine) - { - set_device(sys, audio_engine->getSelectedDeviceUUID()); - audio_engine->OnOutputDeviceListChanged(audio_engine->getDevices()); - } - break; - default: - break; - } - return FMOD_OK; + switch (type) + { + case FMOD_SYSTEM_CALLBACK_DEVICELISTCHANGED: + LL_DEBUGS() << "FMOD system callback FMOD_SYSTEM_CALLBACK_DEVICELISTCHANGED" << LL_ENDL; + if (sys && audio_engine) + { + set_device(sys, audio_engine->getSelectedDeviceUUID()); + audio_engine->OnOutputDeviceListChanged(audio_engine->getDevices()); + } + break; + default: + break; + } + return FMOD_OK; } LLAudioEngine_FMODSTUDIO::LLAudioEngine_FMODSTUDIO(bool enable_profiler, U32 resample_method) - : mInited(false) - , mWindGen(NULL) - , mWindDSPDesc(NULL) - , mWindDSP(NULL) - , mSystem(NULL) - , mEnableProfiler(enable_profiler) - , mResampleMethod(resample_method) - , mSelectedDeviceUUID() + : mInited(false), + mWindGen(nullptr), + mWindDSPDesc(nullptr), + mWindDSP(nullptr), + mSystem(nullptr), + mEnableProfiler(enable_profiler), + mResampleMethod(resample_method), + mSelectedDeviceUUID() { } LLAudioEngine_FMODSTUDIO::~LLAudioEngine_FMODSTUDIO() { + delete mWindDSPDesc; } bool LLAudioEngine_FMODSTUDIO::init(const S32 num_channels, void* userdata) { - U32 version; - FMOD_RESULT result; + U32 version; + FMOD_RESULT result; - LL_DEBUGS("AppInit") << "LLAudioEngine_FMODSTUDIO::init() initializing FMOD" << LL_ENDL; + LL_DEBUGS("AppInit") << "LLAudioEngine_FMODSTUDIO::init() initializing FMOD" << LL_ENDL; - result = FMOD::System_Create(&mSystem); - if(Check_FMOD_Error(result, "FMOD::System_Create")) - return false; + result = FMOD::System_Create(&mSystem); + if (Check_FMOD_Error(result, "FMOD::System_Create")) + return false; - //will call LLAudioEngine_FMODSTUDIO::allocateListener, which needs a valid mSystem pointer. - LLAudioEngine::init(num_channels, userdata); - - result = mSystem->getVersion(&version); - Check_FMOD_Error(result, "FMOD::System::getVersion"); + //will call LLAudioEngine_FMODSTUDIO::allocateListener, which needs a valid mSystem pointer. + LLAudioEngine::init(num_channels, userdata); - if (version < FMOD_VERSION) - { - LL_WARNS("AppInit") << "Error : You are using the wrong FMOD Studio version (" << version - << ")! You should be using FMOD Studio" << FMOD_VERSION << LL_ENDL; - } + result = mSystem->getVersion(&version); + Check_FMOD_Error(result, "FMOD::System::getVersion"); - // In this case, all sounds, PLUS wind and stream will be software. - result = mSystem->setSoftwareChannels(num_channels + EXTRA_SOUND_CHANNELS); - Check_FMOD_Error(result,"FMOD::System::setSoftwareChannels"); + if (version < FMOD_VERSION) + { + LL_WARNS("AppInit") << "FMOD Studio version mismatch, actual: " << version + << " expected:" << FMOD_VERSION << LL_ENDL; + } - Check_FMOD_Error(mSystem->setCallback(systemCallback), "FMOD::System::setCallback"); - Check_FMOD_Error(mSystem->setUserData(this), "FMOD::System::setUserData"); + // In this case, all sounds, PLUS wind and stream will be software. + result = mSystem->setSoftwareChannels(num_channels + EXTRA_SOUND_CHANNELS); + Check_FMOD_Error(result, "FMOD::System::setSoftwareChannels"); - FMOD_ADVANCEDSETTINGS adv_settings = { }; - adv_settings.cbSize = sizeof(FMOD_ADVANCEDSETTINGS); - switch (mResampleMethod) - { - default: - case RESAMPLE_LINEAR: - adv_settings.resamplerMethod = FMOD_DSP_RESAMPLER_LINEAR; - break; - case RESAMPLE_CUBIC: - adv_settings.resamplerMethod = FMOD_DSP_RESAMPLER_CUBIC; - break; - case RESAMPLE_SPLINE: - adv_settings.resamplerMethod = FMOD_DSP_RESAMPLER_SPLINE; - break; - } + Check_FMOD_Error(mSystem->setCallback(systemCallback), "FMOD::System::setCallback"); + Check_FMOD_Error(mSystem->setUserData(this), "FMOD::System::setUserData"); - result = mSystem->setAdvancedSettings(&adv_settings); - Check_FMOD_Error(result, "FMOD::System::setAdvancedSettings"); + FMOD_ADVANCEDSETTINGS settings = { }; + settings.cbSize = sizeof(FMOD_ADVANCEDSETTINGS); + switch (mResampleMethod) + { + default: + case RESAMPLE_LINEAR: + settings.resamplerMethod = FMOD_DSP_RESAMPLER_LINEAR; + break; + case RESAMPLE_CUBIC: + settings.resamplerMethod = FMOD_DSP_RESAMPLER_CUBIC; + break; + case RESAMPLE_SPLINE: + settings.resamplerMethod = FMOD_DSP_RESAMPLER_SPLINE; + break; + } - U32 fmod_flags = FMOD_INIT_NORMAL | FMOD_INIT_3D_RIGHTHANDED | FMOD_INIT_THREAD_UNSAFE; - if(mEnableProfiler) - { - fmod_flags |= FMOD_INIT_PROFILE_ENABLE; - } + result = mSystem->setAdvancedSettings(&settings); + Check_FMOD_Error(result, "FMOD::System::setAdvancedSettings"); + + U32 fmod_flags = FMOD_INIT_NORMAL | FMOD_INIT_3D_RIGHTHANDED | FMOD_INIT_THREAD_UNSAFE; + if (mEnableProfiler) + { + fmod_flags |= FMOD_INIT_PROFILE_ENABLE; + } #if LL_LINUX - bool audio_ok = false; + bool audio_ok = false; - if (!audio_ok) - { - if (NULL == getenv("LL_BAD_FMOD_PULSEAUDIO")) /*Flawfinder: ignore*/ - { - LL_DEBUGS("AppInit") << "Trying PulseAudio audio output..." << LL_ENDL; - if((result = mSystem->setOutput(FMOD_OUTPUTTYPE_PULSEAUDIO)) == FMOD_OK && - (result = mSystem->init(num_channels + EXTRA_SOUND_CHANNELS, fmod_flags, const_cast(APP_NAME.c_str()))) == FMOD_OK) - { - LL_DEBUGS("AppInit") << "PulseAudio output initialized OKAY" << LL_ENDL; - audio_ok = true; - } - else - { - Check_FMOD_Error(result, "PulseAudio audio output FAILED to initialize"); - } - } - else - { - LL_DEBUGS("AppInit") << "PulseAudio audio output SKIPPED" << LL_ENDL; - } - } - if (!audio_ok) - { - if (NULL == getenv("LL_BAD_FMOD_ALSA")) /*Flawfinder: ignore*/ - { - LL_DEBUGS("AppInit") << "Trying ALSA audio output..." << LL_ENDL; - if((result = mSystem->setOutput(FMOD_OUTPUTTYPE_ALSA)) == FMOD_OK && - (result = mSystem->init(num_channels + EXTRA_SOUND_CHANNELS, fmod_flags, 0)) == FMOD_OK) - { - LL_DEBUGS("AppInit") << "ALSA audio output initialized OKAY" << LL_ENDL; - audio_ok = true; - } - else - { - Check_FMOD_Error(result, "ALSA audio output FAILED to initialize"); - } - } - else - { - LL_DEBUGS("AppInit") << "ALSA audio output SKIPPED" << LL_ENDL; - } - } - if (!audio_ok) - { - LL_WARNS("AppInit") << "Overall audio init failure." << LL_ENDL; - return false; - } + if (!audio_ok) + { + const char* env_string = getenv("LL_BAD_FMOD_PULSEAUDIO"); + if (NULL == env_string) + { + LL_DEBUGS("AppInit") << "Trying PulseAudio audio output..." << LL_ENDL; + if ((result = mSystem->setOutput(FMOD_OUTPUTTYPE_PULSEAUDIO)) == FMOD_OK && + (result = mSystem->init(num_channels + EXTRA_SOUND_CHANNELS, fmod_flags, const_cast(APP_NAME.c_str()))) == FMOD_OK) + { + LL_DEBUGS("AppInit") << "PulseAudio output initialized OKAY" << LL_ENDL; + audio_ok = true; + } + else + { + Check_FMOD_Error(result, "PulseAudio audio output FAILED to initialize"); + } + } + else + { + LL_DEBUGS("AppInit") << "PulseAudio audio output SKIPPED" << LL_ENDL; + } + } + if (!audio_ok) + { + const char* env_string = getenv("LL_BAD_FMOD_ALSA"); + if (NULL == env_string) + { + LL_DEBUGS("AppInit") << "Trying ALSA audio output..." << LL_ENDL; + if ((result = mSystem->setOutput(FMOD_OUTPUTTYPE_ALSA)) == FMOD_OK && + (result = mSystem->init(num_channels + EXTRA_SOUND_CHANNELS, fmod_flags, 0)) == FMOD_OK) + { + LL_DEBUGS("AppInit") << "ALSA audio output initialized OKAY" << LL_ENDL; + audio_ok = true; + } + else + { + Check_FMOD_Error(result, "ALSA audio output FAILED to initialize"); + } + } + else + { + LL_DEBUGS("AppInit") << "ALSA audio output SKIPPED" << LL_ENDL; + } + } + if (!audio_ok) + { + LL_WARNS("AppInit") << "Overall audio init failure." << LL_ENDL; + return false; + } - // We're interested in logging which output method we - // ended up with, for QA purposes. - FMOD_OUTPUTTYPE output_type; - if(!Check_FMOD_Error(mSystem->getOutput(&output_type), "FMOD::System::getOutput")) - { - switch (output_type) - { - case FMOD_OUTPUTTYPE_NOSOUND: - LL_INFOS("AppInit") << "Audio output: NoSound" << LL_ENDL; break; - case FMOD_OUTPUTTYPE_PULSEAUDIO: - LL_INFOS("AppInit") << "Audio output: PulseAudio" << LL_ENDL; break; - case FMOD_OUTPUTTYPE_ALSA: - LL_INFOS("AppInit") << "Audio output: ALSA" << LL_ENDL; break; - default: - LL_INFOS("AppInit") << "Audio output: Unknown!" << LL_ENDL; break; - }; - } + // We're interested in logging which output method we + // ended up with, for QA purposes. + FMOD_OUTPUTTYPE output_type; + if (!Check_FMOD_Error(mSystem->getOutput(&output_type), "FMOD::System::getOutput")) + { + switch (output_type) + { + case FMOD_OUTPUTTYPE_NOSOUND: + LL_INFOS("AppInit") << "Audio output: NoSound" << LL_ENDL; break; + case FMOD_OUTPUTTYPE_PULSEAUDIO: + LL_INFOS("AppInit") << "Audio output: PulseAudio" << LL_ENDL; break; + case FMOD_OUTPUTTYPE_ALSA: + LL_INFOS("AppInit") << "Audio output: ALSA" << LL_ENDL; break; + default: + LL_INFOS("AppInit") << "Audio output: Unknown!" << LL_ENDL; break; + }; + } #else // LL_LINUX - // initialize the FMOD engine - result = mSystem->init( num_channels + EXTRA_SOUND_CHANNELS, fmod_flags, 0); - if (result == FMOD_ERR_OUTPUT_CREATEBUFFER) - { - /* - Ok, the speaker mode selected isn't supported by this soundcard. Switch it - back to stereo... - */ - result = mSystem->setSoftwareFormat(44100, FMOD_SPEAKERMODE_STEREO, 0); - Check_FMOD_Error(result,"Error falling back to stereo mode"); - /* - ... and re-init. - */ - result = mSystem->init( num_channels + EXTRA_SOUND_CHANNELS, fmod_flags, 0); - } - if(Check_FMOD_Error(result, "Error initializing FMOD Studio")) - return false; + // initialize the FMOD engine + result = mSystem->init(num_channels + EXTRA_SOUND_CHANNELS, fmod_flags, 0); + if (result == FMOD_ERR_OUTPUT_CREATEBUFFER) + { + /* + Ok, the speaker mode selected isn't supported by this soundcard. Switch it + back to stereo... + */ + result = mSystem->setSoftwareFormat(44100, FMOD_SPEAKERMODE_STEREO, 0); + Check_FMOD_Error(result,"Error falling back to stereo mode"); + /* + ... and re-init. + */ + result = mSystem->init(num_channels + EXTRA_SOUND_CHANNELS, fmod_flags, 0); + } + if (Check_FMOD_Error(result, "Error initializing FMOD Studio")) + { + return false; + } #endif - if (mEnableProfiler) - { - Check_FMOD_Error(mSystem->createChannelGroup("None", &mChannelGroups[AUDIO_TYPE_NONE]), "FMOD::System::createChannelGroup"); - Check_FMOD_Error(mSystem->createChannelGroup("SFX", &mChannelGroups[AUDIO_TYPE_SFX]), "FMOD::System::createChannelGroup"); - Check_FMOD_Error(mSystem->createChannelGroup("UI", &mChannelGroups[AUDIO_TYPE_UI]), "FMOD::System::createChannelGroup"); - Check_FMOD_Error(mSystem->createChannelGroup("Ambient", &mChannelGroups[AUDIO_TYPE_AMBIENT]), "FMOD::System::createChannelGroup"); - } + if (mEnableProfiler) + { + Check_FMOD_Error(mSystem->createChannelGroup("None", &mChannelGroups[AUDIO_TYPE_NONE]), "FMOD::System::createChannelGroup"); + Check_FMOD_Error(mSystem->createChannelGroup("SFX", &mChannelGroups[AUDIO_TYPE_SFX]), "FMOD::System::createChannelGroup"); + Check_FMOD_Error(mSystem->createChannelGroup("UI", &mChannelGroups[AUDIO_TYPE_UI]), "FMOD::System::createChannelGroup"); + Check_FMOD_Error(mSystem->createChannelGroup("Ambient", &mChannelGroups[AUDIO_TYPE_AMBIENT]), "FMOD::System::createChannelGroup"); + } - // set up our favourite FMOD-native streaming audio implementation if none has already been added - if (!getStreamingAudioImpl()) // no existing implementation added - setStreamingAudioImpl(new LLStreamingAudio_FMODSTUDIO(mSystem)); + // set up our favourite FMOD-native streaming audio implementation if none has already been added + if (!getStreamingAudioImpl()) // no existing implementation added + setStreamingAudioImpl(new LLStreamingAudio_FMODSTUDIO(mSystem)); - LL_INFOS("AppInit") << "LLAudioEngine_FMODSTUDIO::init() FMOD Studio initialized correctly" << LL_ENDL; + LL_INFOS("AppInit") << "LLAudioEngine_FMODSTUDIO::init() FMOD Studio initialized correctly" << LL_ENDL; - FMOD_ADVANCEDSETTINGS adv_settings_dump = { }; - mSystem->getAdvancedSettings(&adv_settings_dump); + FMOD_ADVANCEDSETTINGS settings_dump = { }; + mSystem->getAdvancedSettings(&settings_dump); + LL_INFOS("AppInit") << "LLAudioEngine_FMODSTUDIO::init(): resampler=" << settings_dump.resamplerMethod << " bytes" << LL_ENDL; - LL_INFOS("AppInit") << "LLAudioEngine_FMODSTUDIO::init(): resampler=" << adv_settings.resamplerMethod << " bytes" << LL_ENDL; + int r_numbuffers, r_samplerate, r_channels; + unsigned int r_bufferlength; + char r_name[512]; + int latency = 100; + mSystem->getDSPBufferSize(&r_bufferlength, &r_numbuffers); + LL_INFOS("AppInit") << "LLAudioEngine_FMODSTUDIO::init(): r_bufferlength=" << r_bufferlength << " bytes" << LL_ENDL; + LL_INFOS("AppInit") << "LLAudioEngine_FMODSTUDIO::init(): r_numbuffers=" << r_numbuffers << LL_ENDL; - int r_numbuffers, r_samplerate, r_channels; - unsigned int r_bufferlength; - mSystem->getDSPBufferSize(&r_bufferlength, &r_numbuffers); - LL_INFOS("AppInit") << "LLAudioEngine_FMODSTUDIO::init(): r_bufferlength=" << r_bufferlength << " bytes" << LL_ENDL; - LL_INFOS("AppInit") << "LLAudioEngine_FMODSTUDIO::init(): r_numbuffers=" << r_numbuffers << LL_ENDL; + mSystem->getDriverInfo(0, r_name, 511, NULL, &r_samplerate, NULL, &r_channels); + r_name[511] = '\0'; + LL_INFOS("AppInit") << "LLAudioEngine_FMODSTUDIO::init(): r_name=\"" << r_name << "\"" << LL_ENDL; + LL_INFOS("AppInit") << "LLAudioEngine_FMODSTUDIO::init(): r_samplerate=" << r_samplerate << "Hz" << LL_ENDL; + LL_INFOS("AppInit") << "LLAudioEngine_FMODSTUDIO::init(): r_channels=" << r_channels << LL_ENDL; - char r_name[512]; - mSystem->getDriverInfo(0, r_name, 511, NULL, &r_samplerate, NULL, &r_channels); - r_name[511] = '\0'; - LL_INFOS("AppInit") << "LLAudioEngine_FMODSTUDIO::init(): r_name=\"" << r_name << "\"" << LL_ENDL; - LL_INFOS("AppInit") << "LLAudioEngine_FMODSTUDIO::init(): r_samplerate=" << r_samplerate << "Hz" << LL_ENDL; - LL_INFOS("AppInit") << "LLAudioEngine_FMODSTUDIO::init(): r_channels=" << r_channels << LL_ENDL; + if (r_samplerate != 0) + latency = (int)(1000.0f * r_bufferlength * r_numbuffers / r_samplerate); + LL_INFOS("AppInit") << "LLAudioEngine_FMODSTUDIO::init(): latency=" << latency << "ms" << LL_ENDL; - int latency = 100; // optimistic default - i suspect if sample rate is 0, everything breaks. - if ( r_samplerate != 0 ) - latency = (int)(1000.0f * r_bufferlength * r_numbuffers / r_samplerate); - LL_INFOS("AppInit") << "LLAudioEngine_FMODSTUDIO::init(): latency=" << latency << "ms" << LL_ENDL; + mInited = true; - mInited = true; + LL_INFOS("AppInit") << "LLAudioEngine_FMODSTUDIO::init(): initialization complete." << LL_ENDL; - LL_INFOS("AppInit") << "LLAudioEngine_FMODSTUDIO::init(): initialization complete." << LL_ENDL; + getDevices(); // Purely to print out available devices for debugging reasons - getDevices(); // Purely to print out available devices for debugging reasons - - return true; + return true; } //virtual LLAudioEngine_FMODSTUDIO::output_device_map_t LLAudioEngine_FMODSTUDIO::getDevices() { - output_device_map_t driver_map; + output_device_map_t driver_map; - int drivercount; - int r_samplerate, r_channels; - char r_name[512]; - FMOD_GUID guid; + int drivercount; + int r_samplerate, r_channels; + char r_name[512]; + FMOD_GUID guid; - if (!Check_FMOD_Error(mSystem->getNumDrivers(&drivercount), "FMOD::System::getNumDrivers")) - { - for (int i = 0; i < drivercount; ++i) - { - memset(r_name, 0, sizeof(r_name)); - if (!Check_FMOD_Error(mSystem->getDriverInfo(i, r_name, 511, &guid, &r_samplerate, NULL, &r_channels), "FMOD::System::getDriverInfo")) - { - LLUUID driver_guid = FMOD_GUID_to_LLUUID(guid); - driver_map.insert(std::make_pair(driver_guid, r_name)); + if (!Check_FMOD_Error(mSystem->getNumDrivers(&drivercount), "FMOD::System::getNumDrivers")) + { + for (int i = 0; i < drivercount; ++i) + { + memset(r_name, 0, sizeof(r_name)); + if (!Check_FMOD_Error(mSystem->getDriverInfo(i, r_name, 511, &guid, &r_samplerate, NULL, &r_channels), "FMOD::System::getDriverInfo")) + { + LLUUID driver_guid = FMOD_GUID_to_LLUUID(guid); + driver_map.insert(std::make_pair(driver_guid, r_name)); - LL_INFOS("AppInit") << "LLAudioEngine_FMODSTUDIO::getDevices(): r_name=\"" << r_name << "\" - guid: " << driver_guid << LL_ENDL; - } - } - } + LL_INFOS("AppInit") << "LLAudioEngine_FMODSTUDIO::getDevices(): r_name=\"" << r_name << "\" - guid: " << driver_guid << LL_ENDL; + } + } + } - return driver_map; + return driver_map; } //virtual void LLAudioEngine_FMODSTUDIO::setDevice(const LLUUID& device_uuid) { - mSelectedDeviceUUID = device_uuid; - set_device(mSystem, device_uuid); + mSelectedDeviceUUID = device_uuid; + set_device(mSystem, device_uuid); } std::string LLAudioEngine_FMODSTUDIO::getDriverName(bool verbose) { - llassert_always(mSystem); - if (verbose) - { - U32 version; - if(!Check_FMOD_Error(mSystem->getVersion(&version), "FMOD::System::getVersion")) - { - return llformat("FMOD Studio %1x.%02x.%02x", version >> 16, version >> 8 & 0x000000FF, version & 0x000000FF); - } - } - return "FMOD Studio"; + llassert_always(mSystem); + if (verbose) + { + U32 version; + if (!Check_FMOD_Error(mSystem->getVersion(&version), "FMOD::System::getVersion")) + { + return llformat("FMOD Studio %1x.%02x.%02x", version >> 16, version >> 8 & 0x000000FF, version & 0x000000FF); + } + } + return "FMOD Studio"; } void LLAudioEngine_FMODSTUDIO::allocateListener(void) -{ - try - { - mListenerp = (LLListener *) new LLListener_FMODSTUDIO(mSystem); - } - catch (const std::bad_alloc& e) - { - LL_WARNS() << "Listener allocation failed due to: " << e.what() << LL_ENDL; - } +{ + try + { + mListenerp = (LLListener *) new LLListener_FMODSTUDIO(mSystem); + } + catch (const std::bad_alloc& e) + { + LL_WARNS() << "Listener allocation failed due to: " << e.what() << LL_ENDL; + } } void LLAudioEngine_FMODSTUDIO::shutdown() { - LL_INFOS() << "About to LLAudioEngine::shutdown()" << LL_ENDL; - LLAudioEngine::shutdown(); - - LL_INFOS() << "LLAudioEngine_FMODSTUDIO::shutdown() closing FMOD Studio" << LL_ENDL; - if ( mSystem ) // speculative fix for MAINT-2657 - { - Check_FMOD_Error(mSystem->close(), "FMOD::System::close"); - Check_FMOD_Error(mSystem->release(), "FMOD::System::release"); - } - LL_INFOS() << "LLAudioEngine_FMODSTUDIO::shutdown() done closing FMOD Studio" << LL_ENDL; + stopInternetStream(); - delete mListenerp; - mListenerp = NULL; + LL_INFOS() << "About to LLAudioEngine::shutdown()" << LL_ENDL; + LLAudioEngine::shutdown(); + + LL_INFOS() << "LLAudioEngine_FMODSTUDIO::shutdown() closing FMOD Studio" << LL_ENDL; + if (mSystem) + { + Check_FMOD_Error(mSystem->close(), "FMOD::System::close"); + Check_FMOD_Error(mSystem->release(), "FMOD::System::release"); + } + LL_INFOS() << "LLAudioEngine_FMODSTUDIO::shutdown() done closing FMOD Studio" << LL_ENDL; + + delete mListenerp; + mListenerp = NULL; } LLAudioBuffer * LLAudioEngine_FMODSTUDIO::createBuffer() { - return new LLAudioBufferFMODSTUDIO(mSystem); + return new LLAudioBufferFMODSTUDIO(mSystem); } LLAudioChannel * LLAudioEngine_FMODSTUDIO::createChannel() { - return new LLAudioChannelFMODSTUDIO(mSystem); + return new LLAudioChannelFMODSTUDIO(mSystem); } bool LLAudioEngine_FMODSTUDIO::initWind() { - mNextWindUpdate = 0.0; + mNextWindUpdate = 0.0; - cleanupWind(); + if (!mWindDSPDesc) + { + mWindDSPDesc = new FMOD_DSP_DESCRIPTION(); + } - mWindDSPDesc = new FMOD_DSP_DESCRIPTION(); - memset(mWindDSPDesc, 0, sizeof(*mWindDSPDesc)); //Set everything to zero - mWindDSPDesc->pluginsdkversion = FMOD_PLUGIN_SDK_VERSION; - strncpy(mWindDSPDesc->name, "Wind Unit", sizeof(mWindDSPDesc->name)); //Set name to "Wind Unit" - mWindDSPDesc->numoutputbuffers = 1; - mWindDSPDesc->read = &windDSPCallback; //Assign callback. - if (Check_FMOD_Error(mSystem->createDSP(mWindDSPDesc, &mWindDSP), "FMOD::createDSP") || !mWindDSP) - return false; + if (!mWindDSP) + { + memset(mWindDSPDesc, 0, sizeof(*mWindDSPDesc)); //Set everything to zero + strncpy(mWindDSPDesc->name, "Wind Unit", sizeof(mWindDSPDesc->name)); + mWindDSPDesc->pluginsdkversion = FMOD_PLUGIN_SDK_VERSION; + mWindDSPDesc->numoutputbuffers = 1; + mWindDSPDesc->read = &windCallback; // Assign callback - may be called from arbitrary threads + if (Check_FMOD_Error(mSystem->createDSP(mWindDSPDesc, &mWindDSP), "FMOD::createDSP")) + return false; - int frequency = 44100; - FMOD_SPEAKERMODE mode; - if (!Check_FMOD_Error(mSystem->getSoftwareFormat(&frequency, &mode, nullptr), "FMOD::System::getSoftwareFormat")) - { - mWindGen = new LLWindGen((U32)frequency); + if (mWindGen) + delete mWindGen; - if (!Check_FMOD_Error(mWindDSP->setUserData((void*)mWindGen), "FMOD::DSP::setUserData") && - !Check_FMOD_Error(mWindDSP->setChannelFormat(FMOD_CHANNELMASK_STEREO, 2, mode), "FMOD::DSP::setChannelFormat") && - !Check_FMOD_Error(mSystem->playDSP(mWindDSP, nullptr, false, nullptr), "FMOD::System::playDSP")) - return true; //Success - } + int frequency = 44100; - cleanupWind(); - return false; + FMOD_SPEAKERMODE mode; + if (Check_FMOD_Error(mSystem->getSoftwareFormat(&frequency, &mode, nullptr), "FMOD::System::getSoftwareFormat")) + { + cleanupWind(); + return false; + } + + mWindGen = new LLWindGen((U32)frequency); + + if (Check_FMOD_Error(mWindDSP->setUserData((void*)mWindGen), "FMOD::DSP::setUserData")) + { + cleanupWind(); + return false; + } + if (Check_FMOD_Error(mWindDSP->setChannelFormat(FMOD_CHANNELMASK_STEREO, 2, mode), "FMOD::DSP::setChannelFormat")) + { + cleanupWind(); + return false; + } + } + + // *TODO: Should this guard against multiple plays? + if (Check_FMOD_Error(mSystem->playDSP(mWindDSP, nullptr, false, nullptr), "FMOD::System::playDSP")) + { + cleanupWind(); + return false; + } + return true; } void LLAudioEngine_FMODSTUDIO::cleanupWind() { - if (mWindDSP) - { - FMOD::ChannelGroup* mastergroup = NULL; - if (!Check_FMOD_Error(mSystem->getMasterChannelGroup(&mastergroup), "FMOD::System::getMasterChannelGroup") && mastergroup) - Check_FMOD_Error(mastergroup->removeDSP(mWindDSP), "FMOD::ChannelGroup::removeDSP"); - Check_FMOD_Error(mWindDSP->release(), "FMOD::DSP::release"); - mWindDSP = NULL; - } + if (mWindDSP) + { + FMOD::ChannelGroup* master_group = NULL; + if (!Check_FMOD_Error(mSystem->getMasterChannelGroup(&master_group), "FMOD::System::getMasterChannelGroup") + && master_group) + { + Check_FMOD_Error(master_group->removeDSP(mWindDSP), "FMOD::ChannelGroup::removeDSP"); + } + Check_FMOD_Error(mWindDSP->release(), "FMOD::DSP::release"); + mWindDSP = NULL; + } - delete mWindDSPDesc; - mWindDSPDesc = NULL; + delete mWindDSPDesc; + mWindDSPDesc = NULL; - delete mWindGen; - mWindGen = NULL; + delete mWindGen; + mWindGen = NULL; } //----------------------------------------------------------------------- void LLAudioEngine_FMODSTUDIO::updateWind(LLVector3 wind_vec, F32 camera_height_above_water) { - LLVector3 wind_pos; - F64 pitch; - F64 center_freq; + LLVector3 wind_pos; + F64 pitch; + F64 center_freq; - if (!mEnableWind) - { - return; - } - - if (mWindUpdateTimer.checkExpirationAndReset(LL_WIND_UPDATE_INTERVAL)) - { - - // wind comes in as Linden coordinate (+X = forward, +Y = left, +Z = up) - // need to convert this to the conventional orientation DS3D and OpenAL use - // where +X = right, +Y = up, +Z = backwards + if (!mEnableWind) + { + return; + } - wind_vec.setVec(-wind_vec.mV[1], wind_vec.mV[2], -wind_vec.mV[0]); + if (mWindUpdateTimer.checkExpirationAndReset(LL_WIND_UPDATE_INTERVAL)) + { - // cerr << "Wind update" << endl; + // wind comes in as Linden coordinate (+X = forward, +Y = left, +Z = up) + // need to convert this to the conventional orientation DS3D and OpenAL use + // where +X = right, +Y = up, +Z = backwards - pitch = 1.0 + mapWindVecToPitch(wind_vec); - center_freq = 80.0 * pow(pitch,2.5*(mapWindVecToGain(wind_vec)+1.0)); - - mWindGen->mTargetFreq = (F32)center_freq; - mWindGen->mTargetGain = (F32)mapWindVecToGain(wind_vec) * mMaxWindGain; - mWindGen->mTargetPanGainR = (F32)mapWindVecToPan(wind_vec); - } + wind_vec.setVec(-wind_vec.mV[1], wind_vec.mV[2], -wind_vec.mV[0]); + + // cerr << "Wind update" << endl; + + pitch = 1.0 + mapWindVecToPitch(wind_vec); + center_freq = 80.0 * pow(pitch, 2.5*(mapWindVecToGain(wind_vec) + 1.0)); + + mWindGen->mTargetFreq = (F32)center_freq; + mWindGen->mTargetGain = (F32)mapWindVecToGain(wind_vec) * mMaxWindGain; + mWindGen->mTargetPanGainR = (F32)mapWindVecToPan(wind_vec); + } } //----------------------------------------------------------------------- void LLAudioEngine_FMODSTUDIO::setInternalGain(F32 gain) { - if (!mInited) - { - return; - } + if (!mInited) + { + return; + } - gain = llclamp( gain, 0.0f, 1.0f ); + gain = llclamp(gain, 0.0f, 1.0f); - FMOD::ChannelGroup *master_group; - if(Check_FMOD_Error(mSystem->getMasterChannelGroup(&master_group), "FMOD::System::getMasterChannelGroup")) - return; + FMOD::ChannelGroup *master_group; + if (Check_FMOD_Error(mSystem->getMasterChannelGroup(&master_group), "FMOD::System::getMasterChannelGroup")) + { + return; + } - master_group->setVolume(gain); + master_group->setVolume(gain); - LLStreamingAudioInterface *saimpl = getStreamingAudioImpl(); - if ( saimpl ) - { - // fmod likes its streaming audio channel gain re-asserted after - // master volume change. - saimpl->setGain(saimpl->getGain()); - } + LLStreamingAudioInterface *saimpl = getStreamingAudioImpl(); + if (saimpl) + { + // fmod likes its streaming audio channel gain re-asserted after + // master volume change. + saimpl->setGain(saimpl->getGain()); + } } // @@ -552,191 +586,191 @@ LLAudioChannelFMODSTUDIO::LLAudioChannelFMODSTUDIO(FMOD::System *system) : LLAud LLAudioChannelFMODSTUDIO::~LLAudioChannelFMODSTUDIO() { - cleanup(); + cleanup(); } bool LLAudioChannelFMODSTUDIO::updateBuffer() { - if (mCurrentSourcep) - { - if (LLAudioChannel::updateBuffer()) - { - // Base class update returned true, which means that we need to actually - // set up the channel for a different buffer. + if (mCurrentSourcep) + { + if (LLAudioChannel::updateBuffer()) + { + // Base class update returned true, which means that we need to actually + // set up the channel for a different buffer. - LLAudioBufferFMODSTUDIO *bufferp = (LLAudioBufferFMODSTUDIO *) mCurrentSourcep->getCurrentBuffer(); + LLAudioBufferFMODSTUDIO *bufferp = (LLAudioBufferFMODSTUDIO *) mCurrentSourcep->getCurrentBuffer(); - // Grab the FMOD sample associated with the buffer - FMOD::Sound *soundp = bufferp->getSound(); - if (!soundp) - { - // This is bad, there should ALWAYS be a sound associated with a legit - // buffer. - LL_ERRS() << "No FMOD sound!" << LL_ENDL; - return false; - } + // Grab the FMOD sample associated with the buffer + FMOD::Sound *soundp = bufferp->getSound(); + if (!soundp) + { + // This is bad, there should ALWAYS be a sound associated with a legit + // buffer. + LL_ERRS() << "No FMOD sound!" << LL_ENDL; + return false; + } - // Actually play the sound. Start it off paused so we can do all the necessary - // setup. - if (!mChannelp) - { - FMOD_RESULT result = getSystem()->playSound(soundp, nullptr, true, &mChannelp); - Check_FMOD_Error(result, "FMOD::System::playSound"); - } + // Actually play the sound. Start it off paused so we can do all the necessary + // setup. + if (!mChannelp) + { + FMOD_RESULT result = getSystem()->playSound(soundp, nullptr, true, &mChannelp); + Check_FMOD_Error(result, "FMOD::System::playSound"); + } - //LL_INFOS() << "Setting up channel " << std::hex << mChannelID << std::dec << LL_ENDL; - } + //LL_INFOS() << "Setting up channel " << std::hex << mChannelID << std::dec << LL_ENDL; + } - //FMOD_RESULT result; + //FMOD_RESULT result; - mChannelp->setVolume(getSecondaryGain() * mCurrentSourcep->getGain()); - //Check_FMOD_Error(result, "FMOD::Channel::setVolume"); + mChannelp->setVolume(getSecondaryGain() * mCurrentSourcep->getGain()); + //Check_FMOD_Error(result, "FMOD::Channel::setVolume"); - mChannelp->setMode(mCurrentSourcep->isLoop() ? FMOD_LOOP_NORMAL : FMOD_LOOP_OFF); - /*if(Check_FMOD_Error(result, "FMOD::Channel::setMode")) - { - S32 index; - mChannelp->getIndex(&index); - LL_WARNS() << "Channel " << index << "Source ID: " << mCurrentSourcep->getID() - << " at " << mCurrentSourcep->getPositionGlobal() << LL_ENDL; - }*/ - } - else - { - LL_DEBUGS() << "No source buffer!" << LL_ENDL; - return false; - } + mChannelp->setMode(mCurrentSourcep->isLoop() ? FMOD_LOOP_NORMAL : FMOD_LOOP_OFF); + /*if(Check_FMOD_Error(result, "FMOD::Channel::setMode")) + { + S32 index; + mChannelp->getIndex(&index); + LL_WARNS() << "Channel " << index << "Source ID: " << mCurrentSourcep->getID() + << " at " << mCurrentSourcep->getPositionGlobal() << LL_ENDL; + }*/ + } + else + { + LL_DEBUGS() << "No source buffer!" << LL_ENDL; + return false; + } - return true; + return true; } void LLAudioChannelFMODSTUDIO::update3DPosition() { - if (!mChannelp) - { - // We're not actually a live channel (i.e., we're not playing back anything) - return; - } + if (!mChannelp) + { + // We're not actually a live channel (i.e., we're not playing back anything) + return; + } - LLAudioBufferFMODSTUDIO *bufferp = (LLAudioBufferFMODSTUDIO *)mCurrentBufferp; - if (!bufferp) - { - // We don't have a buffer associated with us (should really have been picked up - // by the above if. - return; - } + LLAudioBufferFMODSTUDIO *bufferp = (LLAudioBufferFMODSTUDIO *)mCurrentBufferp; + if (!bufferp) + { + // We don't have a buffer associated with us (should really have been picked up + // by the above if. + return; + } - if (mCurrentSourcep->isAmbient()) - { - // Ambient sound, don't need to do any positional updates. - set3DMode(false); - } - else - { - // Localized sound. Update the position and velocity of the sound. - set3DMode(true); + if (mCurrentSourcep->isAmbient()) + { + // Ambient sound, don't need to do any positional updates. + set3DMode(false); + } + else + { + // Localized sound. Update the position and velocity of the sound. + set3DMode(true); - LLVector3 float_pos; - float_pos.setVec(mCurrentSourcep->getPositionGlobal()); - FMOD_RESULT result = mChannelp->set3DAttributes((FMOD_VECTOR*)float_pos.mV, (FMOD_VECTOR*)mCurrentSourcep->getVelocity().mV); - Check_FMOD_Error(result, "FMOD::Channel::set3DAttributes"); - } + LLVector3 float_pos; + float_pos.setVec(mCurrentSourcep->getPositionGlobal()); + FMOD_RESULT result = mChannelp->set3DAttributes((FMOD_VECTOR*)float_pos.mV, (FMOD_VECTOR*)mCurrentSourcep->getVelocity().mV); + Check_FMOD_Error(result, "FMOD::Channel::set3DAttributes"); + } } void LLAudioChannelFMODSTUDIO::updateLoop() { - if (!mChannelp) - { - // May want to clear up the loop/sample counters. - return; - } + if (!mChannelp) + { + // May want to clear up the loop/sample counters. + return; + } - // - // Hack: We keep track of whether we looped or not by seeing when the - // sample position looks like it's going backwards. Not reliable; may - // yield false negatives. - // - U32 cur_pos; - Check_FMOD_Error(mChannelp->getPosition(&cur_pos,FMOD_TIMEUNIT_PCMBYTES),"FMOD::Channel::getPosition"); + // + // Hack: We keep track of whether we looped or not by seeing when the + // sample position looks like it's going backwards. Not reliable; may + // yield false negatives. + // + U32 cur_pos; + Check_FMOD_Error(mChannelp->getPosition(&cur_pos, FMOD_TIMEUNIT_PCMBYTES), "FMOD::Channel::getPosition"); - if (cur_pos < (U32)mLastSamplePos) - { - mLoopedThisFrame = true; - } - mLastSamplePos = cur_pos; + if (cur_pos < (U32)mLastSamplePos) + { + mLoopedThisFrame = true; + } + mLastSamplePos = cur_pos; } void LLAudioChannelFMODSTUDIO::cleanup() { - if (!mChannelp) - { - //LL_INFOS() << "Aborting cleanup with no channel handle." << LL_ENDL; - return; - } + if (!mChannelp) + { + // Aborting cleanup with no channel handle. + return; + } - //LL_INFOS() << "Cleaning up channel: " << mChannelID << LL_ENDL; - Check_FMOD_Error(mChannelp->stop(),"FMOD::Channel::stop"); + //Cleaning up channel mChannelID + Check_FMOD_Error(mChannelp->stop(), "FMOD::Channel::stop"); - mCurrentBufferp = NULL; - mChannelp = NULL; + mCurrentBufferp = NULL; + mChannelp = NULL; } void LLAudioChannelFMODSTUDIO::play() { - if (!mChannelp) - { - LL_WARNS() << "Playing without a channel handle, aborting" << LL_ENDL; - return; - } + if (!mChannelp) + { + LL_WARNS() << "Playing without a channel handle, aborting" << LL_ENDL; + return; + } - Check_FMOD_Error(mChannelp->setPaused(false), "FMOD::Channel::setPaused"); + Check_FMOD_Error(mChannelp->setPaused(false), "FMOD::Channel::setPaused"); - getSource()->setPlayedOnce(true); + getSource()->setPlayedOnce(true); - if(LLAudioEngine_FMODSTUDIO::mChannelGroups[getSource()->getType()]) - Check_FMOD_Error(mChannelp->setChannelGroup(LLAudioEngine_FMODSTUDIO::mChannelGroups[getSource()->getType()]),"FMOD::Channel::setChannelGroup"); + if (LLAudioEngine_FMODSTUDIO::mChannelGroups[getSource()->getType()]) + Check_FMOD_Error(mChannelp->setChannelGroup(LLAudioEngine_FMODSTUDIO::mChannelGroups[getSource()->getType()]), "FMOD::Channel::setChannelGroup"); } void LLAudioChannelFMODSTUDIO::playSynced(LLAudioChannel *channelp) { - LLAudioChannelFMODSTUDIO *fmod_channelp = (LLAudioChannelFMODSTUDIO*)channelp; - if (!(fmod_channelp->mChannelp && mChannelp)) - { - // Don't have channels allocated to both the master and the slave - return; - } + LLAudioChannelFMODSTUDIO *fmod_channelp = (LLAudioChannelFMODSTUDIO*)channelp; + if (!(fmod_channelp->mChannelp && mChannelp)) + { + // Don't have channels allocated to both the master and the slave + return; + } - U32 cur_pos; - if(Check_FMOD_Error(mChannelp->getPosition(&cur_pos,FMOD_TIMEUNIT_PCMBYTES), "Unable to retrieve current position")) - return; + U32 cur_pos; + if (Check_FMOD_Error(mChannelp->getPosition(&cur_pos, FMOD_TIMEUNIT_PCMBYTES), "Unable to retrieve current position")) + return; - cur_pos %= mCurrentBufferp->getLength(); - - // Try to match the position of our sync master - Check_FMOD_Error(mChannelp->setPosition(cur_pos,FMOD_TIMEUNIT_PCMBYTES),"Unable to set current position"); + cur_pos %= mCurrentBufferp->getLength(); - // Start us playing - play(); + // Try to match the position of our sync master + Check_FMOD_Error(mChannelp->setPosition(cur_pos, FMOD_TIMEUNIT_PCMBYTES), "Unable to set current position"); + + // Start us playing + play(); } bool LLAudioChannelFMODSTUDIO::isPlaying() { - if (!mChannelp) - { - return false; - } + if (!mChannelp) + { + return false; + } - bool paused, playing; - Check_FMOD_Error(mChannelp->getPaused(&paused),"FMOD::Channel::getPaused"); - Check_FMOD_Error(mChannelp->isPlaying(&playing),"FMOD::Channel::isPlaying"); - return !paused && playing; + bool paused, playing; + Check_FMOD_Error(mChannelp->getPaused(&paused),"FMOD::Channel::getPaused"); + Check_FMOD_Error(mChannelp->isPlaying(&playing),"FMOD::Channel::isPlaying"); + return !paused && playing; } @@ -752,109 +786,109 @@ LLAudioBufferFMODSTUDIO::LLAudioBufferFMODSTUDIO(FMOD::System *system) : mSystem LLAudioBufferFMODSTUDIO::~LLAudioBufferFMODSTUDIO() { - if(mSoundp) - { - Check_FMOD_Error(mSoundp->release(),"FMOD::Sound::Release"); - mSoundp = NULL; - } + if (mSoundp) + { + Check_FMOD_Error(mSoundp->release(), "FMOD::Sound::Release"); + mSoundp = NULL; + } } bool LLAudioBufferFMODSTUDIO::loadWAV(const std::string& filename) { - // Try to open a wav file from disk. This will eventually go away, as we don't - // really want to block doing this. - if (filename.empty()) - { - // invalid filename, abort. - return false; - } + // Try to open a wav file from disk. This will eventually go away, as we don't + // really want to block doing this. + if (filename.empty()) + { + // invalid filename, abort. + return false; + } - if (!gDirUtilp->fileExists(filename)) - { - // File not found, abort. - return false; - } - - if (mSoundp) - { - // If there's already something loaded in this buffer, clean it up. - Check_FMOD_Error(mSoundp->release(),"FMOD::Sound::release"); - mSoundp = NULL; - } + if (!gDirUtilp->fileExists(filename)) + { + // File not found, abort. + return false; + } - FMOD_MODE base_mode = FMOD_LOOP_NORMAL; - FMOD_CREATESOUNDEXINFO exinfo; - memset(&exinfo,0,sizeof(exinfo)); - exinfo.cbsize = sizeof(exinfo); - exinfo.suggestedsoundtype = FMOD_SOUND_TYPE_WAV; //Hint to speed up loading. - // Load up the wav file into an fmod sample - FMOD_RESULT result = getSystem()->createSound(filename.c_str(), base_mode, &exinfo, &mSoundp); - if (result != FMOD_OK) - { - // We failed to load the file for some reason. - LL_WARNS() << "Could not load data '" << filename << "': " << FMOD_ErrorString(result) << LL_ENDL; + if (mSoundp) + { + // If there's already something loaded in this buffer, clean it up. + Check_FMOD_Error(mSoundp->release(), "FMOD::Sound::release"); + mSoundp = NULL; + } - // - // If we EVER want to load wav files provided by end users, we need - // to rethink this! - // - // file is probably corrupt - remove it. - LLFile::remove(filename); - return false; - } + FMOD_MODE base_mode = FMOD_LOOP_NORMAL; + FMOD_CREATESOUNDEXINFO exinfo; + memset(&exinfo, 0, sizeof(exinfo)); + exinfo.cbsize = sizeof(exinfo); + exinfo.suggestedsoundtype = FMOD_SOUND_TYPE_WAV; //Hint to speed up loading. + // Load up the wav file into an fmod sample + FMOD_RESULT result = getSystem()->createSound(filename.c_str(), base_mode, &exinfo, &mSoundp); - // Everything went well, return true - return true; + if (result != FMOD_OK) + { + // We failed to load the file for some reason. + LL_WARNS() << "Could not load data '" << filename << "': " << FMOD_ErrorString(result) << LL_ENDL; + + // + // If we EVER want to load wav files provided by end users, we need + // to rethink this! + // + // file is probably corrupt - remove it. + LLFile::remove(filename); + return false; + } + + // Everything went well, return true + return true; } U32 LLAudioBufferFMODSTUDIO::getLength() { - if (!mSoundp) - { - return 0; - } + if (!mSoundp) + { + return 0; + } - U32 length; - Check_FMOD_Error(mSoundp->getLength(&length, FMOD_TIMEUNIT_PCMBYTES),"FMOD::Sound::getLength"); - return length; + U32 length; + Check_FMOD_Error(mSoundp->getLength(&length, FMOD_TIMEUNIT_PCMBYTES), "FMOD::Sound::getLength"); + return length; } void LLAudioChannelFMODSTUDIO::set3DMode(bool use3d) { - FMOD_MODE current_mode; - if(Check_FMOD_Error(mChannelp->getMode(¤t_mode),"FMOD::Channel::getMode")) - return; - FMOD_MODE new_mode = current_mode; - new_mode &= ~(use3d ? FMOD_2D : FMOD_3D); - new_mode |= use3d ? FMOD_3D : FMOD_2D; + FMOD_MODE current_mode; + if (Check_FMOD_Error(mChannelp->getMode(¤t_mode), "FMOD::Channel::getMode")) + return; + FMOD_MODE new_mode = current_mode; + new_mode &= ~(use3d ? FMOD_2D : FMOD_3D); + new_mode |= use3d ? FMOD_3D : FMOD_2D; - if(current_mode != new_mode) - { - Check_FMOD_Error(mChannelp->setMode(new_mode),"FMOD::Channel::setMode"); - } + if (current_mode != new_mode) + { + Check_FMOD_Error(mChannelp->setMode(new_mode), "FMOD::Channel::setMode"); + } } // *NOTE: This is almost certainly being called on the mixer thread, // not the main thread. May have implications for callees or audio // engine shutdown. -FMOD_RESULT F_CALLBACK windDSPCallback(FMOD_DSP_STATE *dsp_state, float *inbuffer, float *outbuffer, unsigned int length, int inchannels, int *outchannels) +FMOD_RESULT F_CALLBACK windCallback(FMOD_DSP_STATE *dsp_state, float *inbuffer, float *outbuffer, unsigned int length, int inchannels, int *outchannels) { - // inbuffer = incomming data. - // newbuffer = outgoing data. AKA this DSP's output. - // length = length in samples at this mix time. True buffer size, in bytes, would be (length * sizeof(float) * inchannels). - // userdata = user-provided data attached this DSP via FMOD::DSP::setUserData. - - LLWindGen *windgen; - FMOD::DSP *thisdsp = (FMOD::DSP *)dsp_state->instance; + // inbuffer = fmod's original mixbuffer. + // outbuffer = the buffer passed from the previous DSP unit. + // length = length in samples at this mix time. - thisdsp->getUserData((void **)&windgen); - - if (windgen) - windgen->windGenerate((LLAudioEngine_FMODSTUDIO::MIXBUFFERFORMAT *)outbuffer, length); + LLWindGen *windgen; + FMOD::DSP *thisdsp = (FMOD::DSP *)dsp_state->instance; - return FMOD_OK; + thisdsp->getUserData((void **)&windgen); + + if (windgen) + windgen->windGenerate((LLAudioEngine_FMODSTUDIO::MIXBUFFERFORMAT *)outbuffer, length); + + return FMOD_OK; } diff --git a/indra/llaudio/llaudioengine_fmodstudio.h b/indra/llaudio/llaudioengine_fmodstudio.h index 3b80f45336..be283dec1c 100644 --- a/indra/llaudio/llaudioengine_fmodstudio.h +++ b/indra/llaudio/llaudioengine_fmodstudio.h @@ -1,11 +1,11 @@ /** * @file audioengine_fmodstudio.h * @brief Definition of LLAudioEngine class abstracting the audio - * support as a FMOD Studio implementation + * support as a FMODSTUDIO implementation * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * $LicenseInfo:firstyear=2020&license=viewerlgpl$ * Second Life Viewer Source Code - * Copyright (C) 2014, Linden Research, Inc. + * Copyright (C) 2020, Linden Research, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -103,8 +103,8 @@ public: class LLAudioChannelFMODSTUDIO : public LLAudioChannel { public: - LLAudioChannelFMODSTUDIO(FMOD::System *audioengine); - virtual ~LLAudioChannelFMODSTUDIO(); + LLAudioChannelFMODSTUDIO(FMOD::System *audioengine); + virtual ~LLAudioChannelFMODSTUDIO(); protected: /*virtual*/ void play(); @@ -128,8 +128,8 @@ protected: class LLAudioBufferFMODSTUDIO : public LLAudioBuffer { public: - LLAudioBufferFMODSTUDIO(FMOD::System *audioengine); - virtual ~LLAudioBufferFMODSTUDIO(); + LLAudioBufferFMODSTUDIO(FMOD::System *audioengine); + virtual ~LLAudioBufferFMODSTUDIO(); /*virtual*/ bool loadWAV(const std::string& filename); /*virtual*/ U32 getLength(); diff --git a/indra/llaudio/lllistener_fmodstudio.cpp b/indra/llaudio/lllistener_fmodstudio.cpp index f5a10442dc..d2e8f4e846 100644 --- a/indra/llaudio/lllistener_fmodstudio.cpp +++ b/indra/llaudio/lllistener_fmodstudio.cpp @@ -1,11 +1,11 @@ /** * @file listener_fmodstudio.cpp * @brief Implementation of LISTENER class abstracting the audio - * support as a FMOD Studio implementation + * support as a FMODSTUDIO implementation * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * $LicenseInfo:firstyear=2020&license=viewerlgpl$ * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. + * Copyright (C) 2020, Linden Research, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -28,17 +28,15 @@ #include "linden_common.h" #include "llaudioengine.h" #include "lllistener_fmodstudio.h" -#include "fmod.hpp" +#include "fmodstudio/fmod.hpp" //----------------------------------------------------------------------- // constructor //----------------------------------------------------------------------- -LLListener_FMODSTUDIO::LLListener_FMODSTUDIO(FMOD::System *system) - : LLListener(), - mDopplerFactor(1.0f), - mRolloffFactor(1.0f) +LLListener_FMODSTUDIO::LLListener_FMODSTUDIO(FMOD::System *system) { - mSystem = system; + mSystem = system; + init(); } //----------------------------------------------------------------------- @@ -46,82 +44,90 @@ LLListener_FMODSTUDIO::~LLListener_FMODSTUDIO() { } +//----------------------------------------------------------------------- +void LLListener_FMODSTUDIO::init(void) +{ + // do inherited + LLListener::init(); + mDopplerFactor = 1.0f; + mRolloffFactor = 1.0f; +} + //----------------------------------------------------------------------- void LLListener_FMODSTUDIO::translate(LLVector3 offset) { - LLListener::translate(offset); + LLListener::translate(offset); - mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*)mPosition.mV, NULL, NULL, NULL); + mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*)mPosition.mV, NULL, NULL, NULL); } //----------------------------------------------------------------------- void LLListener_FMODSTUDIO::setPosition(LLVector3 pos) { - LLListener::setPosition(pos); + LLListener::setPosition(pos); - mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*)mPosition.mV, NULL, NULL, NULL); + mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*)mPosition.mV, NULL, NULL, NULL); } //----------------------------------------------------------------------- void LLListener_FMODSTUDIO::setVelocity(LLVector3 vel) { - LLListener::setVelocity(vel); + LLListener::setVelocity(vel); - mSystem->set3DListenerAttributes(0, NULL, (FMOD_VECTOR*)mVelocity.mV, NULL, NULL); + mSystem->set3DListenerAttributes(0, NULL, (FMOD_VECTOR*)mVelocity.mV, NULL, NULL); } //----------------------------------------------------------------------- void LLListener_FMODSTUDIO::orient(LLVector3 up, LLVector3 at) { - LLListener::orient(up, at); + LLListener::orient(up, at); - mSystem->set3DListenerAttributes(0, NULL, NULL, (FMOD_VECTOR*)at.mV, (FMOD_VECTOR*)up.mV); + mSystem->set3DListenerAttributes(0, NULL, NULL, (FMOD_VECTOR*)at.mV, (FMOD_VECTOR*)up.mV); } //----------------------------------------------------------------------- void LLListener_FMODSTUDIO::commitDeferredChanges() { - if(!mSystem) - { - return; - } + if (!mSystem) + { + return; + } - mSystem->update(); + mSystem->update(); } void LLListener_FMODSTUDIO::setRolloffFactor(F32 factor) { - //An internal FMOD Studio optimization skips 3D updates if there have not been changes to the 3D sound environment. - //Sadly, a change in rolloff is not accounted for, thus we must touch the listener properties as well. - //In short: Changing the position ticks a dirtyflag inside fmod studio, which makes it not skip 3D processing next update call. - if(mRolloffFactor != factor) - { - LLVector3 tmp_pos = mPosition - LLVector3(0.f,0.f,.1f); - mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*) tmp_pos.mV, NULL, NULL, NULL); - mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*) mPosition.mV, NULL, NULL, NULL); - } - mRolloffFactor = factor; - mSystem->set3DSettings(mDopplerFactor, 1.f, mRolloffFactor); + //An internal FMOD optimization skips 3D updates if there have not been changes to the 3D sound environment. + // (this was true for FMODex, looks to be still true for FMOD STUDIO) + //Sadly, a change in rolloff is not accounted for, thus we must touch the listener properties as well. + //In short: Changing the position ticks a dirtyflag inside fmod, which makes it not skip 3D processing next update call. + if (mRolloffFactor != factor) + { + LLVector3 pos = mPosition - LLVector3(0.f,0.f,.1f); + mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*) pos.mV, NULL, NULL, NULL); + mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*) mPosition.mV, NULL, NULL, NULL); + } + mRolloffFactor = factor; + mSystem->set3DSettings(mDopplerFactor, 1.f, mRolloffFactor); } F32 LLListener_FMODSTUDIO::getRolloffFactor() { - return mRolloffFactor; + return mRolloffFactor; } void LLListener_FMODSTUDIO::setDopplerFactor(F32 factor) { - mDopplerFactor = factor; - mSystem->set3DSettings(mDopplerFactor, 1.f, mRolloffFactor); + mDopplerFactor = factor; + mSystem->set3DSettings(mDopplerFactor, 1.f, mRolloffFactor); } F32 LLListener_FMODSTUDIO::getDopplerFactor() { - return mDopplerFactor; + return mDopplerFactor; } - - diff --git a/indra/llaudio/lllistener_fmodstudio.h b/indra/llaudio/lllistener_fmodstudio.h index ebe42f0e38..2dd02fc783 100644 --- a/indra/llaudio/lllistener_fmodstudio.h +++ b/indra/llaudio/lllistener_fmodstudio.h @@ -3,9 +3,9 @@ * @brief Description of LISTENER class abstracting the audio support * as an FMOD Studio implementation (windows and Linux) * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * $LicenseInfo:firstyear=2020&license=viewerlgpl$ * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. + * Copyright (C) 2020, Linden Research, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -39,24 +39,25 @@ namespace FMOD //Interfaces class LLListener_FMODSTUDIO : public LLListener { - public: - LLListener_FMODSTUDIO(FMOD::System *system); - virtual ~LLListener_FMODSTUDIO(); +public: + LLListener_FMODSTUDIO(FMOD::System *system); + virtual ~LLListener_FMODSTUDIO(); + virtual void init(); - virtual void translate(LLVector3 offset); - virtual void setPosition(LLVector3 pos); - virtual void setVelocity(LLVector3 vel); - virtual void orient(LLVector3 up, LLVector3 at); - virtual void commitDeferredChanges(); + virtual void translate(LLVector3 offset); + virtual void setPosition(LLVector3 pos); + virtual void setVelocity(LLVector3 vel); + virtual void orient(LLVector3 up, LLVector3 at); + virtual void commitDeferredChanges(); - virtual void setDopplerFactor(F32 factor); - virtual F32 getDopplerFactor(); - virtual void setRolloffFactor(F32 factor); - virtual F32 getRolloffFactor(); - protected: - FMOD::System *mSystem; - F32 mDopplerFactor; - F32 mRolloffFactor; + virtual void setDopplerFactor(F32 factor); + virtual F32 getDopplerFactor(); + virtual void setRolloffFactor(F32 factor); + virtual F32 getRolloffFactor(); +protected: + FMOD::System *mSystem; + F32 mDopplerFactor; + F32 mRolloffFactor; }; #endif diff --git a/indra/llaudio/llstreamingaudio_fmodstudio.cpp b/indra/llaudio/llstreamingaudio_fmodstudio.cpp index edf63c90c6..6d622b4e19 100644 --- a/indra/llaudio/llstreamingaudio_fmodstudio.cpp +++ b/indra/llaudio/llstreamingaudio_fmodstudio.cpp @@ -2,9 +2,9 @@ * @file streamingaudio_fmodstudio.cpp * @brief LLStreamingAudio_FMODSTUDIO implementation * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * $LicenseInfo:firstyear=2020&license=viewerlgpl$ * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. + * Copyright (C) 2020, Linden Research, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -28,38 +28,38 @@ #include "llmath.h" -#include "fmod.hpp" -#include "fmod_errors.h" +#include "fmodstudio/fmod.hpp" +#include "fmodstudio/fmod_errors.h" #include "llstreamingaudio_fmodstudio.h" inline bool Check_FMOD_Error(FMOD_RESULT result, const char *string) { - if (result == FMOD_OK) - return false; - LL_WARNS("AudioImpl") << string << " Error: " << FMOD_ErrorString(result) << LL_ENDL; - return true; + if (result == FMOD_OK) + return false; + LL_WARNS("AudioImpl") << string << " Error: " << FMOD_ErrorString(result) << LL_ENDL; + return true; } class LLAudioStreamManagerFMODSTUDIO { public: - LLAudioStreamManagerFMODSTUDIO(FMOD::System *system, FMOD::ChannelGroup *group, const std::string& url); - FMOD::Channel* startStream(); - bool stopStream(); // Returns true if the stream was successfully stopped. - bool ready(); + LLAudioStreamManagerFMODSTUDIO(FMOD::System *system, FMOD::ChannelGroup *group, const std::string& url); + FMOD::Channel* startStream(); + bool stopStream(); // Returns true if the stream was successfully stopped. + bool ready(); - const std::string& getURL() { return mInternetStreamURL; } + const std::string& getURL() { return mInternetStreamURL; } - FMOD_RESULT getOpenState(FMOD_OPENSTATE& openstate, unsigned int* percentbuffered = NULL, bool* starving = NULL, bool* diskbusy = NULL); + FMOD_RESULT getOpenState(FMOD_OPENSTATE& openstate, unsigned int* percentbuffered = NULL, bool* starving = NULL, bool* diskbusy = NULL); protected: - FMOD::System* mSystem; - FMOD::ChannelGroup* mChannelGroup; - FMOD::Channel* mStreamChannel; - FMOD::Sound* mInternetStream; - bool mReady; + FMOD::System* mSystem; + FMOD::ChannelGroup* mChannelGroup; + FMOD::Channel* mStreamChannel; + FMOD::Sound* mInternetStream; + bool mReady; - std::string mInternetStreamURL; + std::string mInternetStreamURL; }; @@ -68,290 +68,290 @@ protected: // Internet Streaming //--------------------------------------------------------------------------- LLStreamingAudio_FMODSTUDIO::LLStreamingAudio_FMODSTUDIO(FMOD::System *system) : - mSystem(system), - mCurrentInternetStreamp(NULL), - mStreamGroup(NULL), - mFMODInternetStreamChannelp(NULL), - mGain(1.0f) + mSystem(system), + mCurrentInternetStreamp(NULL), + mStreamGroup(NULL), + mFMODInternetStreamChannelp(NULL), + mGain(1.0f) { - FMOD_RESULT result; + FMOD_RESULT result; - // Number of milliseconds of audio to buffer for the audio card. - // Must be larger than the usual Second Life frame stutter time. - const U32 buffer_seconds = 10; //sec - const U32 estimated_bitrate = 128; //kbit/sec - result = mSystem->setStreamBufferSize(estimated_bitrate * buffer_seconds * 128/*bytes/kbit*/, FMOD_TIMEUNIT_RAWBYTES); - Check_FMOD_Error(result, "FMOD::System::setStreamBufferSize"); + // Number of milliseconds of audio to buffer for the audio card. + // Must be larger than the usual Second Life frame stutter time. + const U32 buffer_seconds = 10; //sec + const U32 estimated_bitrate = 128; //kbit/sec + result = mSystem->setStreamBufferSize(estimated_bitrate * buffer_seconds * 128/*bytes/kbit*/, FMOD_TIMEUNIT_RAWBYTES); + Check_FMOD_Error(result, "FMOD::System::setStreamBufferSize"); - Check_FMOD_Error(system->createChannelGroup("stream", &mStreamGroup), "FMOD::System::createChannelGroup"); + Check_FMOD_Error(system->createChannelGroup("stream", &mStreamGroup), "FMOD::System::createChannelGroup"); } LLStreamingAudio_FMODSTUDIO::~LLStreamingAudio_FMODSTUDIO() { - stop(); - for (U32 i = 0; i < 100; ++i) - { - if (releaseDeadStreams()) - break; - ms_sleep(10); - } + stop(); + for (U32 i = 0; i < 100; ++i) + { + if (releaseDeadStreams()) + break; + ms_sleep(10); + } } void LLStreamingAudio_FMODSTUDIO::start(const std::string& url) { - //if (!mInited) - //{ - // LL_WARNS() << "startInternetStream before audio initialized" << LL_ENDL; - // return; - //} + //if (!mInited) + //{ + // LL_WARNS() << "startInternetStream before audio initialized" << LL_ENDL; + // return; + //} - // "stop" stream but don't clear url, etc. in case url == mInternetStreamURL - stop(); + // "stop" stream but don't clear url, etc. in case url == mInternetStreamURL + stop(); - if (!url.empty()) - { - if(mDeadStreams.empty()) - { - LL_INFOS() << "Starting internet stream: " << url << LL_ENDL; - mCurrentInternetStreamp = new LLAudioStreamManagerFMODSTUDIO(mSystem, mStreamGroup, url); - mURL = url; - } - else - { - LL_INFOS() << "Deferring stream load until buffer release: " << url << LL_ENDL; - mPendingURL = url; - } - } - else - { - LL_INFOS() << "Set internet stream to null" << LL_ENDL; - mURL.clear(); - } + if (!url.empty()) + { + if(mDeadStreams.empty()) + { + LL_INFOS() << "Starting internet stream: " << url << LL_ENDL; + mCurrentInternetStreamp = new LLAudioStreamManagerFMODSTUDIO(mSystem, mStreamGroup, url); + mURL = url; + } + else + { + LL_INFOS() << "Deferring stream load until buffer release: " << url << LL_ENDL; + mPendingURL = url; + } + } + else + { + LL_INFOS() << "Set internet stream to null" << LL_ENDL; + mURL.clear(); + } } void LLStreamingAudio_FMODSTUDIO::update() { - if (!releaseDeadStreams()) - { - llassert_always(mCurrentInternetStreamp == NULL); - return; - } + if (!releaseDeadStreams()) + { + llassert_always(mCurrentInternetStreamp == NULL); + return; + } - if(!mPendingURL.empty()) - { - llassert_always(mCurrentInternetStreamp == NULL); - LL_INFOS() << "Starting internet stream: " << mPendingURL << LL_ENDL; - mCurrentInternetStreamp = new LLAudioStreamManagerFMODSTUDIO(mSystem, mStreamGroup, mPendingURL); - mURL = mPendingURL; - mPendingURL.clear(); - } + if(!mPendingURL.empty()) + { + llassert_always(mCurrentInternetStreamp == NULL); + LL_INFOS() << "Starting internet stream: " << mPendingURL << LL_ENDL; + mCurrentInternetStreamp = new LLAudioStreamManagerFMODSTUDIO(mSystem, mStreamGroup, mPendingURL); + mURL = mPendingURL; + mPendingURL.clear(); + } - // Don't do anything if there are no streams playing - if (!mCurrentInternetStreamp) - { - return; - } + // Don't do anything if there are no streams playing + if (!mCurrentInternetStreamp) + { + return; + } - unsigned int progress; - bool starving; - bool diskbusy; - FMOD_OPENSTATE open_state; - FMOD_RESULT result = mCurrentInternetStreamp->getOpenState(open_state, &progress, &starving, &diskbusy); + unsigned int progress; + bool starving; + bool diskbusy; + FMOD_OPENSTATE open_state; + FMOD_RESULT result = mCurrentInternetStreamp->getOpenState(open_state, &progress, &starving, &diskbusy); - if (result != FMOD_OK || open_state == FMOD_OPENSTATE_ERROR) - { - stop(); - return; - } - else if (open_state == FMOD_OPENSTATE_READY) - { - // Stream is live + if (result != FMOD_OK || open_state == FMOD_OPENSTATE_ERROR) + { + stop(); + return; + } + else if (open_state == FMOD_OPENSTATE_READY) + { + // Stream is live - // start the stream if it's ready - if (!mFMODInternetStreamChannelp && - (mFMODInternetStreamChannelp = mCurrentInternetStreamp->startStream())) - { - // Reset volume to previously set volume - setGain(getGain()); - Check_FMOD_Error(mFMODInternetStreamChannelp->setPaused(false), "FMOD::Channel::setPaused"); - } - } + // start the stream if it's ready + if (!mFMODInternetStreamChannelp && + (mFMODInternetStreamChannelp = mCurrentInternetStreamp->startStream())) + { + // Reset volume to previously set volume + setGain(getGain()); + Check_FMOD_Error(mFMODInternetStreamChannelp->setPaused(false), "FMOD::Channel::setPaused"); + } + } - if(mFMODInternetStreamChannelp) - { - FMOD::Sound *sound = NULL; + if (mFMODInternetStreamChannelp) + { + FMOD::Sound *sound = NULL; - if (!Check_FMOD_Error(mFMODInternetStreamChannelp->getCurrentSound(&sound), "FMOD::Channel::getCurrentSound") && sound) - { - FMOD_TAG tag; - S32 tagcount, dirtytagcount; + if (!Check_FMOD_Error(mFMODInternetStreamChannelp->getCurrentSound(&sound), "FMOD::Channel::getCurrentSound") && sound) + { + FMOD_TAG tag; + S32 tagcount, dirtytagcount; - if (!Check_FMOD_Error(sound->getNumTags(&tagcount, &dirtytagcount), "FMOD::Sound::getNumTags") && dirtytagcount) - { - LL_DEBUGS("StreamMetadata") << "Tag count: " << tagcount << " Dirty tag count: " << dirtytagcount << LL_ENDL; + if (!Check_FMOD_Error(sound->getNumTags(&tagcount, &dirtytagcount), "FMOD::Sound::getNumTags") && dirtytagcount) + { + LL_DEBUGS("StreamMetadata") << "Tag count: " << tagcount << " Dirty tag count: " << dirtytagcount << LL_ENDL; - // Stream metadata - originally by Shyotl Khur - mMetadata.clear(); - mNewMetadata = true; - // - for(S32 i = 0; i < tagcount; ++i) - { - if(Check_FMOD_Error(sound->getTag(NULL, i, &tag), "FMOD::Sound::getTag")) - continue; + // Stream metadata - originally by Shyotl Khur + mMetadata.clear(); + mNewMetadata = true; + // + for(S32 i = 0; i < tagcount; ++i) + { + if(Check_FMOD_Error(sound->getTag(NULL, i, &tag), "FMOD::Sound::getTag")) + continue; - LL_DEBUGS("StreamMetadata") << "Tag name: " << tag.name << " - Tag type: " << tag.type << " - Tag data type: " << tag.datatype << LL_ENDL; + LL_DEBUGS("StreamMetadata") << "Tag name: " << tag.name << " - Tag type: " << tag.type << " - Tag data type: " << tag.datatype << LL_ENDL; - std::string name = tag.name; - switch(tag.type) - { - case(FMOD_TAGTYPE_ID3V2): - { - if(name == "TIT2") name = "TITLE"; - else if(name == "TPE1") name = "ARTIST"; - break; - } - case(FMOD_TAGTYPE_ASF): - { - if(name == "Title") name = "TITLE"; - else if(name == "WM/AlbumArtist") name = "ARTIST"; - break; - } - case(FMOD_TAGTYPE_VORBISCOMMENT): - { - if(name == "title") name = "TITLE"; - else if(name == "artist") name = "ARTIST"; - break; - } - case(FMOD_TAGTYPE_FMOD): - { - if (!strcmp(tag.name, "Sample Rate Change")) - { - LL_INFOS() << "Stream forced changing sample rate to " << *((float *)tag.data) << LL_ENDL; - mFMODInternetStreamChannelp->setFrequency(*((float *)tag.data)); - } - continue; - } - default: - break; - } - switch(tag.datatype) - { - case(FMOD_TAGDATATYPE_INT): - { - (mMetadata)[name]=*(LLSD::Integer*)(tag.data); - LL_DEBUGS("StreamMetadata") << tag.name << ": " << *(int*)(tag.data) << LL_ENDL; - break; - } - case(FMOD_TAGDATATYPE_FLOAT): - { - (mMetadata)[name]=*(LLSD::Real*)(tag.data); - LL_DEBUGS("StreamMetadata") << tag.name << ": " << *(float*)(tag.data) << LL_ENDL; - break; - } - case(FMOD_TAGDATATYPE_STRING): - { - std::string out = rawstr_to_utf8(std::string((char*)tag.data,tag.datalen)); - (mMetadata)[name]=out; - LL_DEBUGS("StreamMetadata") << tag.name << ": " << out << LL_ENDL; - break; - } - case(FMOD_TAGDATATYPE_STRING_UTF8): - { - std::string out((char*)tag.data); - (mMetadata)[name]=out; - LL_DEBUGS("StreamMetadata") << tag.name << ": " << out << LL_ENDL; - break; - } - case(FMOD_TAGDATATYPE_STRING_UTF16): - { - std::string out((char*)tag.data,tag.datalen); - (mMetadata)[std::string(tag.name)]=out; - LL_DEBUGS("StreamMetadata") << tag.name << ": " << out << LL_ENDL; - break; - } - case(FMOD_TAGDATATYPE_STRING_UTF16BE): - { - std::string out((char*)tag.data,tag.datalen); - //U16* buf = (U16*)out.c_str(); - //for(U32 j = 0; j < out.size()/2; ++j) - //(((buf[j] & 0xff)<<8) | ((buf[j] & 0xff00)>>8)); - (mMetadata)[std::string(tag.name)]=out; - LL_DEBUGS("StreamMetadata") << tag.name << ": " << out << LL_ENDL; - break; - } - default: - break; - } - } - } + std::string name = tag.name; + switch(tag.type) + { + case(FMOD_TAGTYPE_ID3V2): + { + if(name == "TIT2") name = "TITLE"; + else if(name == "TPE1") name = "ARTIST"; + break; + } + case(FMOD_TAGTYPE_ASF): + { + if(name == "Title") name = "TITLE"; + else if(name == "WM/AlbumArtist") name = "ARTIST"; + break; + } + case(FMOD_TAGTYPE_VORBISCOMMENT): + { + if(name == "title") name = "TITLE"; + else if(name == "artist") name = "ARTIST"; + break; + } + case(FMOD_TAGTYPE_FMOD): + { + if (!strcmp(tag.name, "Sample Rate Change")) + { + LL_INFOS() << "Stream forced changing sample rate to " << *((float *)tag.data) << LL_ENDL; + mFMODInternetStreamChannelp->setFrequency(*((float *)tag.data)); + } + continue; + } + default: + break; + } + switch(tag.datatype) + { + case(FMOD_TAGDATATYPE_INT): + { + (mMetadata)[name]=*(LLSD::Integer*)(tag.data); + LL_DEBUGS("StreamMetadata") << tag.name << ": " << *(int*)(tag.data) << LL_ENDL; + break; + } + case(FMOD_TAGDATATYPE_FLOAT): + { + (mMetadata)[name]=*(LLSD::Real*)(tag.data); + LL_DEBUGS("StreamMetadata") << tag.name << ": " << *(float*)(tag.data) << LL_ENDL; + break; + } + case(FMOD_TAGDATATYPE_STRING): + { + std::string out = rawstr_to_utf8(std::string((char*)tag.data,tag.datalen)); + (mMetadata)[name]=out; + LL_DEBUGS("StreamMetadata") << tag.name << ": " << out << LL_ENDL; + break; + } + case(FMOD_TAGDATATYPE_STRING_UTF8): + { + std::string out((char*)tag.data); + (mMetadata)[name]=out; + LL_DEBUGS("StreamMetadata") << tag.name << ": " << out << LL_ENDL; + break; + } + case(FMOD_TAGDATATYPE_STRING_UTF16): + { + std::string out((char*)tag.data,tag.datalen); + (mMetadata)[std::string(tag.name)]=out; + LL_DEBUGS("StreamMetadata") << tag.name << ": " << out << LL_ENDL; + break; + } + case(FMOD_TAGDATATYPE_STRING_UTF16BE): + { + std::string out((char*)tag.data,tag.datalen); + //U16* buf = (U16*)out.c_str(); + //for(U32 j = 0; j < out.size()/2; ++j) + //(((buf[j] & 0xff)<<8) | ((buf[j] & 0xff00)>>8)); + (mMetadata)[std::string(tag.name)]=out; + LL_DEBUGS("StreamMetadata") << tag.name << ": " << out << LL_ENDL; + break; + } + default: + break; + } + } + } - if(starving) - { - bool paused = false; - if (mFMODInternetStreamChannelp->getPaused(&paused) == FMOD_OK && !paused) - { - LL_INFOS() << "Stream starvation detected! Pausing stream until buffer nearly full." << LL_ENDL; - LL_INFOS() << " (diskbusy="<setPaused(true), "FMOD::Channel::setPaused"); - } - } - else if(progress > 80) - { - Check_FMOD_Error(mFMODInternetStreamChannelp->setPaused(false), "FMOD::Channel::setPaused"); - } - } - } + if (starving) + { + bool paused = false; + if (mFMODInternetStreamChannelp->getPaused(&paused) == FMOD_OK && !paused) + { + LL_INFOS() << "Stream starvation detected! Pausing stream until buffer nearly full." << LL_ENDL; + LL_INFOS() << " (diskbusy="<setPaused(true), "FMOD::Channel::setPaused"); + } + } + else if (progress > 80) + { + Check_FMOD_Error(mFMODInternetStreamChannelp->setPaused(false), "FMOD::Channel::setPaused"); + } + } + } } void LLStreamingAudio_FMODSTUDIO::stop() { - mPendingURL.clear(); + mPendingURL.clear(); - if (mFMODInternetStreamChannelp) - { - Check_FMOD_Error(mFMODInternetStreamChannelp->setPaused(true), "FMOD::Channel::setPaused"); - Check_FMOD_Error(mFMODInternetStreamChannelp->setPriority(0), "FMOD::Channel::setPriority"); - mFMODInternetStreamChannelp = NULL; - } + if (mFMODInternetStreamChannelp) + { + Check_FMOD_Error(mFMODInternetStreamChannelp->setPaused(true), "FMOD::Channel::setPaused"); + Check_FMOD_Error(mFMODInternetStreamChannelp->setPriority(0), "FMOD::Channel::setPriority"); + mFMODInternetStreamChannelp = NULL; + } - if (mCurrentInternetStreamp) - { - LL_INFOS() << "Stopping internet stream: " << mCurrentInternetStreamp->getURL() << LL_ENDL; - if (mCurrentInternetStreamp->stopStream()) - { - delete mCurrentInternetStreamp; - } - else - { - LL_WARNS() << "Pushing stream to dead list: " << mCurrentInternetStreamp->getURL() << LL_ENDL; - mDeadStreams.push_back(mCurrentInternetStreamp); - } - mCurrentInternetStreamp = NULL; - } + if (mCurrentInternetStreamp) + { + LL_INFOS() << "Stopping internet stream: " << mCurrentInternetStreamp->getURL() << LL_ENDL; + if (mCurrentInternetStreamp->stopStream()) + { + delete mCurrentInternetStreamp; + } + else + { + LL_WARNS() << "Pushing stream to dead list: " << mCurrentInternetStreamp->getURL() << LL_ENDL; + mDeadStreams.push_back(mCurrentInternetStreamp); + } + mCurrentInternetStreamp = NULL; + } } void LLStreamingAudio_FMODSTUDIO::pause(int pauseopt) { - if (pauseopt < 0) - { - pauseopt = mCurrentInternetStreamp ? 1 : 0; - } + if (pauseopt < 0) + { + pauseopt = mCurrentInternetStreamp ? 1 : 0; + } - if (pauseopt) - { - if (mCurrentInternetStreamp) - { - stop(); - } - } - else - { - start(getURL()); - } + if (pauseopt) + { + if (mCurrentInternetStreamp) + { + stop(); + } + } + else + { + start(getURL()); + } } @@ -359,179 +359,179 @@ void LLStreamingAudio_FMODSTUDIO::pause(int pauseopt) // doesn't necessarily mean audio is coming out of the speakers. int LLStreamingAudio_FMODSTUDIO::isPlaying() { - if (mCurrentInternetStreamp) - { - return 1; // Active and playing - } - else if (!mURL.empty() || !mPendingURL.empty()) - { - return 2; // "Paused" - } - else - { - return 0; - } + if (mCurrentInternetStreamp) + { + return 1; // Active and playing + } + else if (!mURL.empty() || !mPendingURL.empty()) + { + return 2; // "Paused" + } + else + { + return 0; + } } F32 LLStreamingAudio_FMODSTUDIO::getGain() { - return mGain; + return mGain; } std::string LLStreamingAudio_FMODSTUDIO::getURL() { - return mURL; + return mURL; } void LLStreamingAudio_FMODSTUDIO::setGain(F32 vol) { - mGain = vol; + mGain = vol; - if (mFMODInternetStreamChannelp) - { - vol = llclamp(vol * vol, 0.f, 1.f); //should vol be squared here? + if (mFMODInternetStreamChannelp) + { + vol = llclamp(vol * vol, 0.f, 1.f); //should vol be squared here? - Check_FMOD_Error(mFMODInternetStreamChannelp->setVolume(vol), "FMOD::Channel::setVolume"); - } + Check_FMOD_Error(mFMODInternetStreamChannelp->setVolume(vol), "FMOD::Channel::setVolume"); + } } // Streamtitle display // virtual bool LLStreamingAudio_FMODSTUDIO::getNewMetadata(LLSD& metadata) { - if (mCurrentInternetStreamp) - { - if (mNewMetadata) - { - metadata = mMetadata; - mNewMetadata = false; - return true; - } - - return mNewMetadata; - } + if (mCurrentInternetStreamp) + { + if (mNewMetadata) + { + metadata = mMetadata; + mNewMetadata = false; + return true; + } + + return mNewMetadata; + } - metadata = LLSD(); - return false; + metadata = LLSD(); + return false; } // /////////////////////////////////////////////////////// // manager of possibly-multiple internet audio streams LLAudioStreamManagerFMODSTUDIO::LLAudioStreamManagerFMODSTUDIO(FMOD::System *system, FMOD::ChannelGroup *group, const std::string& url) : - mSystem(system), - mChannelGroup(group), - mStreamChannel(NULL), - mInternetStream(NULL), - mReady(false) + mSystem(system), + mChannelGroup(group), + mStreamChannel(NULL), + mInternetStream(NULL), + mReady(false) { - mInternetStreamURL = url; + mInternetStreamURL = url; - FMOD_RESULT result = mSystem->createStream(url.c_str(), FMOD_2D | FMOD_NONBLOCKING | FMOD_IGNORETAGS, 0, &mInternetStream); + FMOD_RESULT result = mSystem->createStream(url.c_str(), FMOD_2D | FMOD_NONBLOCKING | FMOD_IGNORETAGS, 0, &mInternetStream); - if (result!= FMOD_OK) - { - LL_WARNS() << "Couldn't open fmod stream, error " - << FMOD_ErrorString(result) - << LL_ENDL; - mReady = false; - return; - } + if (result!= FMOD_OK) + { + LL_WARNS() << "Couldn't open fmod stream, error " + << FMOD_ErrorString(result) + << LL_ENDL; + mReady = false; + return; + } - mReady = true; + mReady = true; } FMOD::Channel *LLAudioStreamManagerFMODSTUDIO::startStream() { - // We need a live and opened stream before we try and play it. - FMOD_OPENSTATE open_state; - if (getOpenState(open_state) != FMOD_OK || open_state != FMOD_OPENSTATE_READY) - { - LL_WARNS() << "No internet stream to start playing!" << LL_ENDL; - return NULL; - } + // We need a live and opened stream before we try and play it. + FMOD_OPENSTATE open_state; + if (getOpenState(open_state) != FMOD_OK || open_state != FMOD_OPENSTATE_READY) + { + LL_WARNS() << "No internet stream to start playing!" << LL_ENDL; + return NULL; + } - if(mStreamChannel) - return mStreamChannel; //Already have a channel for this stream. + if(mStreamChannel) + return mStreamChannel; //Already have a channel for this stream. - Check_FMOD_Error(mSystem->playSound(mInternetStream, mChannelGroup, true, &mStreamChannel), "FMOD::System::playSound"); - return mStreamChannel; + Check_FMOD_Error(mSystem->playSound(mInternetStream, mChannelGroup, true, &mStreamChannel), "FMOD::System::playSound"); + return mStreamChannel; } bool LLAudioStreamManagerFMODSTUDIO::stopStream() { - if (mInternetStream) - { - bool close = true; - FMOD_OPENSTATE open_state; - if (getOpenState(open_state) == FMOD_OK) - { - switch (open_state) - { - case FMOD_OPENSTATE_CONNECTING: - close = false; - break; - default: - close = true; - } - } + if (mInternetStream) + { + bool close = true; + FMOD_OPENSTATE open_state; + if (getOpenState(open_state) == FMOD_OK) + { + switch (open_state) + { + case FMOD_OPENSTATE_CONNECTING: + close = false; + break; + default: + close = true; + } + } - if (close && mInternetStream->release() == FMOD_OK) - { - mStreamChannel = NULL; - mInternetStream = NULL; - return true; - } - else - { - return false; - } - } - else - { - return true; - } + if (close && mInternetStream->release() == FMOD_OK) + { + mStreamChannel = NULL; + mInternetStream = NULL; + return true; + } + else + { + return false; + } + } + else + { + return true; + } } FMOD_RESULT LLAudioStreamManagerFMODSTUDIO::getOpenState(FMOD_OPENSTATE& state, unsigned int* percentbuffered, bool* starving, bool* diskbusy) { - if (!mInternetStream) - return FMOD_ERR_INVALID_HANDLE; - FMOD_RESULT result = mInternetStream->getOpenState(&state, percentbuffered, starving, diskbusy); - Check_FMOD_Error(result, "FMOD::Sound::getOpenState"); - return result; + if (!mInternetStream) + return FMOD_ERR_INVALID_HANDLE; + FMOD_RESULT result = mInternetStream->getOpenState(&state, percentbuffered, starving, diskbusy); + Check_FMOD_Error(result, "FMOD::Sound::getOpenState"); + return result; } void LLStreamingAudio_FMODSTUDIO::setBufferSizes(U32 streambuffertime, U32 decodebuffertime) { - Check_FMOD_Error(mSystem->setStreamBufferSize(streambuffertime / 1000 * 128 * 128, FMOD_TIMEUNIT_RAWBYTES), "FMOD::System::setStreamBufferSize"); - FMOD_ADVANCEDSETTINGS settings; - memset(&settings,0,sizeof(settings)); - settings.cbSize=sizeof(settings); - settings.defaultDecodeBufferSize = decodebuffertime;//ms - Check_FMOD_Error(mSystem->setAdvancedSettings(&settings), "FMOD::System::setAdvancedSettings"); + Check_FMOD_Error(mSystem->setStreamBufferSize(streambuffertime / 1000 * 128 * 128, FMOD_TIMEUNIT_RAWBYTES), "FMOD::System::setStreamBufferSize"); + FMOD_ADVANCEDSETTINGS settings; + memset(&settings,0,sizeof(settings)); + settings.cbSize=sizeof(settings); + settings.defaultDecodeBufferSize = decodebuffertime;//ms + Check_FMOD_Error(mSystem->setAdvancedSettings(&settings), "FMOD::System::setAdvancedSettings"); } bool LLStreamingAudio_FMODSTUDIO::releaseDeadStreams() { - // Kill dead internet streams, if possible - std::list::iterator iter; - for (iter = mDeadStreams.begin(); iter != mDeadStreams.end();) - { - LLAudioStreamManagerFMODSTUDIO *streamp = *iter; - if (streamp->stopStream()) - { - LL_INFOS() << "Closed dead stream" << LL_ENDL; - delete streamp; - mDeadStreams.erase(iter++); - } - else - { - iter++; - } - } + // Kill dead internet streams, if possible + std::list::iterator iter; + for (iter = mDeadStreams.begin(); iter != mDeadStreams.end();) + { + LLAudioStreamManagerFMODSTUDIO *streamp = *iter; + if (streamp->stopStream()) + { + LL_INFOS() << "Closed dead stream" << LL_ENDL; + delete streamp; + mDeadStreams.erase(iter++); + } + else + { + iter++; + } + } - return mDeadStreams.empty(); + return mDeadStreams.empty(); } diff --git a/indra/llaudio/llstreamingaudio_fmodstudio.h b/indra/llaudio/llstreamingaudio_fmodstudio.h index d220ddd02c..7ec5a0dbf4 100644 --- a/indra/llaudio/llstreamingaudio_fmodstudio.h +++ b/indra/llaudio/llstreamingaudio_fmodstudio.h @@ -2,9 +2,9 @@ * @file streamingaudio_fmodstudio.h * @brief Definition of LLStreamingAudio_FMODSTUDIO implementation * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * $LicenseInfo:firstyear=2020&license=viewerlgpl$ * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. + * Copyright (C) 2020, Linden Research, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -45,41 +45,41 @@ namespace FMOD //Interfaces class LLStreamingAudio_FMODSTUDIO : public LLStreamingAudioInterface { - public: - LLStreamingAudio_FMODSTUDIO(FMOD::System *system); - /*virtual*/ ~LLStreamingAudio_FMODSTUDIO(); +public: + LLStreamingAudio_FMODSTUDIO(FMOD::System *system); + /*virtual*/ ~LLStreamingAudio_FMODSTUDIO(); - /*virtual*/ void start(const std::string& url); - /*virtual*/ void stop(); - /*virtual*/ void pause(S32 pause); - /*virtual*/ void update(); - /*virtual*/ S32 isPlaying(); - /*virtual*/ void setGain(F32 vol); - /*virtual*/ F32 getGain(); - /*virtual*/ std::string getURL(); + /*virtual*/ void start(const std::string& url); + /*virtual*/ void stop(); + /*virtual*/ void pause(S32 pause); + /*virtual*/ void update(); + /*virtual*/ S32 isPlaying(); + /*virtual*/ void setGain(F32 vol); + /*virtual*/ F32 getGain(); + /*virtual*/ std::string getURL(); - /*virtual*/ bool supportsAdjustableBufferSizes(){return true;} - /*virtual*/ void setBufferSizes(U32 streambuffertime, U32 decodebuffertime); - //Streamtitle display DKO - virtual bool getNewMetadata(LLSD& metadata); - // DKO + /*virtual*/ bool supportsAdjustableBufferSizes(){return true;} + /*virtual*/ void setBufferSizes(U32 streambuffertime, U32 decodebuffertime); + //Streamtitle display DKO + virtual bool getNewMetadata(LLSD& metadata); + // DKO private: - bool releaseDeadStreams(); + bool releaseDeadStreams(); - FMOD::System *mSystem; + FMOD::System *mSystem; - LLAudioStreamManagerFMODSTUDIO *mCurrentInternetStreamp; - FMOD::ChannelGroup* mStreamGroup; - FMOD::Channel *mFMODInternetStreamChannelp; - std::list mDeadStreams; + LLAudioStreamManagerFMODSTUDIO *mCurrentInternetStreamp; + FMOD::ChannelGroup* mStreamGroup; + FMOD::Channel *mFMODInternetStreamChannelp; + std::list mDeadStreams; - std::string mURL; - std::string mPendingURL; - F32 mGain; - // Streamtitle display - bool mNewMetadata; - LLSD mMetadata; - // Streamtitle display + std::string mURL; + std::string mPendingURL; + F32 mGain; + // Streamtitle display + bool mNewMetadata; + LLSD mMetadata; + // Streamtitle display };