| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536 |
- #include "SoundService.h"
- #include "SoundsEngine.h"
- #include "SoundBanks.h"
- #include "Sound.h"
- #include "..\..\common_h\FileService.h"
- #include "..\..\common_h\LocStrings.h"
- #include "UnitTests\SoundServiceUnitTests.h"
- //============================================================================================
- CREATE_SERVICE_NAMED("SoundService", SoundService, 2)
- //============================================================================================
- SoundService::SoundService() : scenes(_FL_)
- #ifndef NO_TOOLS
- , previewSounds(_FL_)
- #endif
- {
- states = 0;
- engine = NEW SoundsEngine();
- soundBanks = NEW SoundBanks();
- //Громкости
- globalVolume = 1.0f;
- soundsVolume = 1.0f;
- musicVolume = 0.4f;
- //Текущие громкости
- curSoundsVolume = globalVolume*soundsVolume;
- curMusicVolume = globalVolume*musicVolume;
- //Доступ к громкостям в базе
- stGlobalVolume = api->Storage().GetItemFloat("Options.GlobalVolume", _FL_);
- Assert(stGlobalVolume);
- stSoundsVolume = api->Storage().GetItemFloat("Options.FxVolume", _FL_);
- Assert(stSoundsVolume);
- stMusicVolume = api->Storage().GetItemFloat("Options.MusicVolume", _FL_);
- Assert(stMusicVolume);
- #ifndef NO_TOOLS
- isEnablePreview = false;
-
-
- //********************
- // UnitTestWaveSelectorsProcess(false);
- //********************
- #endif
- }
- SoundService::~SoundService()
- {
- while(scenes)
- {
- scenes[scenes - 1]->UnReleaseMessage();
- scenes[scenes - 1]->Release();
- }
- SoundScene::ClearPulls();
- delete engine;
- delete soundBanks;
- stGlobalVolume->Release();
- stSoundsVolume->Release();
- stMusicVolume->Release();
- }
- //Инициализвация
- bool SoundService::Init()
- {
- //Параметры сервиса
- IFileService * fs = (IFileService *)api->GetService("FileService");
- Assert(fs);
- IIniFile * ini = fs->SystemIni();
- if(ini)
- {
- if(ini->GetLong("Sound", "off", 0) != 0)
- {
- states |= SoundsEngine::dbg_snd_off;
- }
- long traceMode = ini->GetLong("Sound", "trace", 0);
- if(traceMode != 0)
- {
- states |= SoundsEngine::dbg_logout;
- }
- if(traceMode > 1)
- {
- states |= SoundsEngine::dbg_tracecreates;
- }
- long dl = ini->GetLong("Sound", "debug", 0);
- switch(dl)
- {
- case 0:
- SetDebugView(dv_none);
- break;
- case 1:
- SetDebugLevel(dl_minimal);
- SetDebugView(dv_all);
- break;
- default:
- SetDebugLevel(dl_maximum);
- SetDebugView(dv_all);
- }
- globalVolume = (float)ini->GetDouble("Sound", "global volume", 1.0f);
- soundsVolume = (float)ini->GetDouble("Sound", "sounds volume", 1.0f);
- musicVolume = (float)ini->GetDouble("Sound", "music volume", 0.4f);
- ini = null;
- }
- //Если выключен то прекращаем инициализацию
- if(states & SoundsEngine::dbg_snd_off)
- {
- api->Trace("SoundService started in silence mode (off)...");
- return true;
- }
- //Инициализируем звук
- if(!engine->Init())
- {
- api->Trace("SoundService error: Sound engine init error. Switch to silence mode (off)...");
- engine->Release();
- states |= SoundsEngine::dbg_snd_off;
- return true;
- }
- //Подписываем сервис
- api->SetEndFrameLevel(this, Core_DefaultExecuteLevel);
- api->Trace("SoundService started is successful");
- states |= s_needUpdateVolumes;
- EndFrame(0.0f);
- return true;
- }
- //Исполнение
- void SoundService::EndFrame(float dltTime)
- {
- //Проверяем изменение громкостей
- float vol = Clampf(stGlobalVolume->Get(globalVolume), 0.0f, 1.0f);
- if(fabsf(vol - globalVolume) > 1e-8f)
- {
- globalVolume = vol;
- states |= s_needUpdateVolumes;
- }
- vol = Clampf(stSoundsVolume->Get(soundsVolume), 0.0f, 1.0f);
- if(fabsf(vol - soundsVolume) > 1e-8f)
- {
- soundsVolume = vol;
- states |= s_needUpdateVolumes;
- }
- vol = Clampf(stMusicVolume->Get(musicVolume), 0.0f, 1.0f)*0.6f;
- if(fabsf(vol - musicVolume) > 1e-8f)
- {
- musicVolume = vol;
- states |= s_needUpdateVolumes;
- }
- //Звук не умеет скалироваться
- dltTime = api->GetNoScaleDeltaTime();
- if(!(states & s_needUpdateVolumes))
- {
- //Обновляем сцены
- for(long i = 0; i < scenes; i++)
- {
- scenes[i]->Update(dltTime);
- }
- }else{
- curSoundsVolume = soundsVolume*globalVolume;
- curMusicVolume = musicVolume*globalVolume;
- #ifndef NO_TOOLS
- engine->EditPrewiewSetMasterVolume(curSoundsVolume);
- #endif
- //Обновляем сцены
- for(long i = 0; i < scenes; i++)
- {
- scenes[i]->UpdateVolumes();
- scenes[i]->Update(dltTime);
- }
- states &= ~s_needUpdateVolumes;
- }
- if(engine)
- {
- engine->Update();
- bool isPause = !api->IsActive();
- engine->SetPause(isPause);
- }
-
-
- }
- //Создать звуковую сцену
- ISoundScene * SoundService::CreateScene(const char * ovnerName, const char * cppFile, long cppLine)
- {
- if(states & SoundsEngine::dbg_snd_off)
- {
- return &sceneOff;
- }
- SoundScene * scene = NEW SoundScene(*this, ovnerName, cppFile, cppLine);
- scenes.Add(scene);
- return scene;
- }
- //Загрузить звуковой банк
- bool SoundService::LoadSoundBank(const char * path)
- {
- if(states & SoundsEngine::dbg_snd_off)
- {
- return true;
- }
- return soundBanks->LoadSoundBank(path);
- }
- //Удалить звуковой банк
- void SoundService::ReleaseSoundBank(const char * path)
- {
- //Поток XAudio после удаления продолжал работать, поэтому банки не удаляю
- return;
- if(states & SoundsEngine::dbg_snd_off)
- {
- return;
- }
- path = soundBanks->GetSoundBankNativeName(path);
- if(!path)
- {
- return;
- }
- for(dword i = 0; i < scenes.Size(); i++)
- {
- scenes[i]->CheckForDelete(path);
- }
- return soundBanks->ReleaseSoundBank(path);
- }
- //Установить общую громкость
- void SoundService::SetGlobalVolume(float volume)
- {
- globalVolume = volume;
- states |= s_needUpdateVolumes;
- }
- //Получить общую громкость
- float SoundService::GetGlobalVolume()
- {
- return globalVolume;
- }
- //Установить громкость звуков
- void SoundService::SetSoundsVolume(float volume)
- {
- soundsVolume = volume;
- states |= s_needUpdateVolumes;
- }
- //Получить громкость звуков
- float SoundService::GetSoundsVolume()
- {
- return soundsVolume;
- }
- //Установить громкость музыки
- void SoundService::SetMusicVolume(float volume)
- {
- musicVolume = volume;
- }
- //Получить громкость музыки
- float SoundService::GetMusicVolume()
- {
- return musicVolume;
- }
- //Установка отладочных параметров
- void SoundService::SetDebugLevel(DebugLevel dl)
- {
- switch(dl)
- {
- case dl_minimal:
- states = (states & ~SoundsEngine::dbg_drawlevel_mask) | SoundsEngine::dbg_drawlevel_min;
- break;
- case dl_maximum:
- states = (states & ~SoundsEngine::dbg_drawlevel_mask) | SoundsEngine::dbg_drawlevel_max;
- break;
- }
- }
- SoundService::DebugLevel SoundService::GetDebugLevel()
- {
- if((states & SoundsEngine::dbg_drawlevel_mask) == SoundsEngine::dbg_drawlevel_max)
- {
- return dl_maximum;
- }
- return dl_minimal;
- }
- void SoundService::SetDebugView(dword dv)
- {
- states &= ~(SoundsEngine::dbg_draw2d | SoundsEngine::dbg_draw3d | SoundsEngine::dbg_drawlistener);
- if(dv & dv_2d)
- {
- states |= SoundsEngine::dbg_draw2d;
- }
- if(dv & dv_3d)
- {
- states |= SoundsEngine::dbg_draw3d;
- }
- if(dv & dv_listener)
- {
- states |= SoundsEngine::dbg_drawlistener;
- }
- }
- dword SoundService::GetDebugView()
- {
- dword debugView = 0;
- if(states & SoundsEngine::dbg_draw2d)
- {
- debugView |= dv_2d;
- }
- if(states & SoundsEngine::dbg_draw3d)
- {
- debugView |= dv_3d;
- }
- if(states & SoundsEngine::dbg_drawlistener)
- {
- debugView |= dv_listener;
- }
- return debugView;
- }
- //Нарисовать отладочную информацию
- void SoundService::DebugDraw()
- {
- if(!IsDebugDraw() || !engine) return;
- long line = 0;
- //Рисуем сцены
- for(dword i = 0; i < scenes.Size(); i++)
- {
- scenes[i]->DebugDraw(states, line);
- }
- //Вывод глобальной информации
- Sound::DebugDrawGlobals(states, *this);
- }
- #ifdef _XBOX
- void * SoundService::GetXAudio2()
- {
- if(engine)
- {
- return engine->GetXAudio();
- }
- return null;
- }
- #endif
- //Найти звук по имени
- SoundBankFileSound * SoundService::FindSound(const ConstString & name, const char ** bankName)
- {
- #ifndef NO_TOOLS
- if(isEnablePreview)
- {
- static const char * previewBankName = "Fake preview bank name";
- if(bankName)
- {
- *bankName = previewBankName;
- }
- if(previewSounds.Size() > 0)
- {
- for(dword i = 0; i < previewSounds.Size(); i++)
- {
- if(string::IsEqual(previewSounds[i]->name, name.c_str()))
- {
- return previewSounds[i];
- }
- }
- }
- return null;
- }
- #endif
- return soundBanks->FindSound(name, bankName);
- }
- //Получить количество звуков ожидающих продолжение
- dword SoundService::GetContinueWaiting()
- {
- #ifndef STOP_DEBUG
- dword count = 0;
- for(dword i = 0; i < scenes.Size(); i++)
- {
- SoundScene * scene = scenes[i];
- if(scene)
- {
- count += scene->GetCouninueQueueSize();
- }
- }
- return count;
- #else
- return 0;
- #endif
- }
- #ifndef NO_TOOLS
- //Разрешить-запретить создавать звуки с временных данных
- void SoundService::EditEnablePreview(bool isEnable)
- {
- isEnablePreview = isEnable;
- }
- //Зарегистрировать звук для предпрослушивания
- void SoundService::EditRegistrySound(SoundBankFileSound * sbfs)
- {
- for(dword i = 0; i < previewSounds.Size(); i++)
- {
- if(previewSounds[i] == sbfs)
- {
- return;
- }
- }
- previewSounds.Add(sbfs);
- }
- //Отменить регистрацию звука для предпрослушивания
- bool SoundService::EditUnregistrySound(SoundBankFileSound * sbfs)
- {
- Assert(sbfs);
- for(dword i = 0; i < scenes.Size(); i++)
- {
- if(scenes[i]->IsUse(*sbfs))
- {
- return false;
- }
- }
- for(dword i = 0; i < previewSounds.Size(); i++)
- {
- if(previewSounds[i] == sbfs)
- {
- previewSounds.DelIndex(i);
- }
- }
- return true;
- }
- //Обновить параметры звука
- bool SoundService::EditPatchSound(EditPatchSoundData & data, bool isCheckIds)
- {
- if(string::IsEmpty(data.soundName))
- {
- return false;
- }
- //Получаем по имени звук
- Assert(data.nameLen < sizeof(data.soundName));
- SoundBankFileHeader * header = null;
- SoundBankFileSound * sbfSound = soundBanks->FindSound(data.soundName, data.nameHash, data.nameLen, &header);
- if(!sbfSound || sbfSound->wavesCount != data.wavesCount)
- {
- return false;
- }
- //Таблица отладки
- Assert(header);
- if(!header->ids)
- {
- return false;
- }
- SoundBankFileObjectId * ids = header->ids;
- dword idsCount = header->idsCount;
- if(isCheckIds)
- {
- //Сверяем идентификаторы звука
- for(dword i = 0; i < idsCount; i++)
- {
- if(ids[i].objectPtr == (byte *)sbfSound)
- {
- if(!ids[i].IsEqual(data.soundId))
- {
- return false;
- }
- }
- }
- //Сверяем волны
- for(dword i = 0; i < sbfSound->wavesCount; i++)
- {
- if(sbfSound->waves[i].wave)
- {
- byte * wavePtr = (byte *)sbfSound->waves[i].wave;
- for(dword j = 0; j < idsCount; j++)
- {
- if(ids[i].objectPtr == wavePtr)
- {
- if(!ids[i].IsEqual(data.waves[i].waveId))
- {
- return false;
- }
- }
- }
- }else{
- dword * wid = data.waves[i].waveId;
- if(wid[0] | wid[1] | wid[2] | wid[3])
- {
- //Идентификатор не пустой
- return false;
- }
- }
- }
- }
- //Обнавляем параметры
- dword priority = data.priority & SoundBankFileSetup::mode_priority_mask;
- Assert(priority == data.priority);
- sbfSound->setup.mode &= ~SoundBankFileSetup::mode_priority_mask;
- sbfSound->setup.mode |= priority;
- sbfSound->setup.maxCount = data.maxCount;
- sbfSound->att.c[0] = data.c[0];
- sbfSound->att.c[1] = data.c[1];
- sbfSound->att.c[2] = data.c[2];
- sbfSound->att.c[3] = data.c[3];
- Assert(data.minDist2 < data.maxDist2);
- sbfSound->att.minDist2 = data.minDist2;
- sbfSound->att.maxDist2 = data.maxDist2;
- sbfSound->att.kNorm2 = data.kNorm2;
- Assert(data.wavesCount == sbfSound->wavesCount);
- for(dword i = 0; i < data.wavesCount; i++)
- {
- sbfSound->waves[i].volume = data.waves[i].volume;
- sbfSound->waves[i].probability = data.waves[i].probability;
- sbfSound->waves[i].playTime = data.waves[i].playTime;
- }
- states |= s_needUpdateVolumes;
- return true;
- }
- //Остановить проигрывание всех звуков
- void SoundService::EditStopAllSounds(const char * sceneOvner)
- {
- for(dword i = 0; i < scenes.Size(); i++)
- {
- scenes[i]->StopAllSounds(sceneOvner);
- }
- }
- #endif
|