| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910 |
- #include "SoundService.h"
- #include "SoundsEngine.h"
- #include "SoundScene.h"
- #include "Sound.h"
- Sound::Sound(SoundScene & scene, bool is3D, bool isAutodelete, SoundBankFileSound & snd, const char * bankName, const char * _cppFile, long _cppLine) : soundScene(scene), sbfSound(snd)
- {
- cppFile = _cppFile;
- cppLine = _cppLine;
- channel = null;
- soundBankName = bankName;
- states = 0;
- if(is3D) states |= att_is3D;
- if(isAutodelete) states |= att_isAutoDelete;
- if(sbfSound.setup.GetModeLoop() != SoundBankFileSetup::mode_loop_diasble)
- {
- Assert(!isAutodelete); //Не должно быть флага автоудаления
- states |= att_isLoop;
- }
- currentTime = 0.0f;
- wave = null;
- phonemes = null;
- phonemesFrame = 0;
- currentVolume = 1.0f;
- globalPos = 0.0f;
- fadeTime = 0.0f;
- playPrev = null;
- playNext = null;
- pullCode = -1;
- }
- Sound::~Sound()
- {
- //В списках уже не значимся, осталось только вычистить себя
- StopNow(true);
- }
- //Удалить звук
- void Sound::Release()
- {
- //Сцена удалит из своих списков и вызовет деструктор
- soundScene.ReleaseSound(this);
- }
- //Проиграть
- void Sound::Play()
- {
- //Запустим проигрывание в конце кадра
- if(!(states & s_play))
- {
- SetCommand(cmd_play);
- }
- }
- //Остановить
- void Sound::Stop()
- {
- //Остановим в конце кадра
- if(states & s_play)
- {
- SetCommand(cmd_stop);
- }
- }
- //Узнать текущее состояние
- bool Sound::IsPlay()
- {
- //Если играем или ждём запуска, считаем что играем
- if(states & s_play) return true;
- if((states & cmd_mask) == cmd_play) return true;
- if((states & cmd_mask) == cmd_fadein) return true;
- return false;
- }
- //Установить громкость звука
- void Sound::SetVolume(float volume)
- {
- currentVolume = volume;
- UpdateVolume();
- }
- //Получить громкость звука
- float Sound::GetVolume()
- {
- return currentVolume;
- }
- //Получить имя звука
- const char * Sound::GetName()
- {
- return sbfSound.name;
- }
- //Получить имя звукового банка
- const char * Sound::GetSoundBankName()
- {
- return soundBankName;
- }
- //Запустить звук проигрываться и плавно увеличить громкость за time секунд
- void Sound::FadeIn(float time)
- {
- //Фейдиться начнём в конце кадра
- if(!(states & s_play))
- {
- if(time > 0.001f)
- {
- fadeTime = time;
- SetCommand(cmd_fadein);
- }else{
- SetCommand(cmd_play);
- }
- }
- }
- //Плавно уменьшить громкость до 0 за time секунд и остановить проигрывание звука
- void Sound::FadeOut(float time)
- {
- //Фейдиться начнём в конце кадра
- if(states & s_play)
- {
- if(time > 0.001f)
- {
- fadeTime = time;
- SetCommand(cmd_fadeout);
- }else{
- SetCommand(cmd_stop);
- }
- }
- }
- //Узнать, зациклен звук или нет
- bool Sound::IsLoop()
- {
- return (states & att_isLoop) != 0;
- }
- //Вернуть идентификатор фонемы. Если отрицательный результат - фонемы нет, 0 - тишина
- long Sound::GetPhonemeId(ErrorCode * ecode)
- {
- //Если нет указателя на фонемы, попробуем его получить
- if(!phonemes)
- {
- phonemesFrame = 0;
- if(!wave)
- {
- if(ecode)
- {
- *ecode = ec_phonemes_sound_not_play;
- }
- return -1;
- }
- SoundBankFileWave * w = wave->wave;
- if(!w)
- {
- if(ecode)
- {
- *ecode = ec_phonemes_sound_not_play;
- }
- return -1;
- }
- for(dword i = 0; i < w->extraCount; i++)
- {
- if(w->extraData[i].id == sbf_extra_phonemes)
- {
- phonemes = (SoundBankFilePhonemes *)w->extraData[i].data;
- break;
- }
- }
- if(!phonemes)
- {
- if(ecode)
- {
- *ecode = ec_phonemes_no_data;
- }
- return -1;
- }
- if(phonemes->framesCount == 0)
- {
- phonemes = null;
- if(ecode)
- {
- *ecode = ec_phonemes_data_is_empty;
- }
- return -1;
- }
- }
- //Получаем текущее время волны
- dword timeInMs;
- /*
- if(channel && !channel->IsLost(this) && channel->GetPlayPosition(timeInMs))
- {
- dword sample = timeInMs;
- timeInMs = long(1000.0f*timeInMs/float(wave->wave->format & SoundBankFileWave::f_freq_mask));
- }else{
- timeInMs = long(currentTime*1000.0f);
- }
-
- Assert(fabsf(timeInMs*0.001f - currentTime) < 2.0f);
- */
- timeInMs = long(currentTime*1000.0f);
- phonemesFrame = phonemes->FindFrame(timeInMs, phonemesFrame);
- dword phoneme = (long)phonemes->GetPhonemeId(phonemesFrame);
- if(ecode)
- {
- *ecode = ec_ok;
- }
- //api->Trace("^^^ GetPhonemeId() = %i", phoneme);
- return phoneme;
- }
- //Установить позицию источника звука
- void Sound::SetPosition(const Vector & position)
- {
- globalPos = position;
- }
- //Получить позицию источника звука
- Vector Sound::GetPosition()
- {
- return globalPos;
- }
- //Приостоновить звук
- void Sound::ScenePause()
- {
- //Если уже на паузе, ничего не делаем
- if(states & s_pause)
- {
- return;
- }
- //Молчащий звук тоже не играем
- if((states & s_play) == 0 || !channel || channel->IsLost(this))
- {
- return;
- }
- //Запоминаем позицию проигрывания
- if(channel->GetPlayPosition(pausePosition))
- {
- states |= s_pause;
- }
- //Освобождаем канал
- soundScene.GetSoundsEngine().ReleaseSoundChannel(channel, this);
- channel = null;
- }
- //Продолжить проигрывать звук
- void Sound::SceneResume()
- {
- if((states & s_pause) == 0)
- {
- return;
- }
- if(states & s_play)
- {
- states &= ~s_play;
- //Востанавливаем канал
- PlayNow(false);
- states &= ~s_pause;
- }
- }
- //Продолжить проигрывание звука с потерянным каналом
- bool Sound::ContinueLost()
- {
- //Проверяем что условия запуска не изменились
- if(!(states & s_play) || !wave || wave->playTime <= 0.0f || wave->playTime - currentTime <= c_time_to_skip_lost_ms*0.001f)
- {
- return true;
- }
- if(states & s_pause)
- {
- return false;
- }
- states |= s_pause;
- Assert(wave->wave);
- Assert(wave->wave->samplesCount > 0);
- float kPos = Clampf(currentTime/wave->playTime);
- long pos = long(kPos*wave->wave->samplesCount);
- if(pos < 0) pos = 0;
- if((dword)pos >= wave->wave->samplesCount)
- {
- return true;
- }
- pausePosition = (dword)pos;
- if(states & att_is3D)
- {
- float att = Update3DPosition(false);
- fadeTime = Clampf(att, 0.0f, c_fade_time_to_restore*0.001f);
- }else{
- fadeTime = c_fade_time_to_restore*0.001f;
- }
- states &= ~s_play;
- PlayNow(true);
- pausePosition = 0;
- states &= ~s_pause;
- return true;
- }
- //Исполнить команду
- void Sound::ExecuteCommand()
- {
- //Отложенная до конца кадра команда
- dword cmd = states & cmd_mask;
- SetCommand(cmd_none);
- switch(cmd)
- {
- case cmd_play:
- if(states & s_play)
- {
- StopNow();
- }
- PlayNow(false);
- break;
- case cmd_stop:
- StopNow();
- break;
- case cmd_fadein:
- if(states & s_play)
- {
- StopNow();
- }
- PlayNow(true);
- break;
- case cmd_fadeout:
- if(channel && !channel->IsLost(this))
- {
- channel->FadeOut(fadeTime);
- }else{
- StopNow();
- }
- break;
- }
- }
- //Обновить звук
- void Sound::Update(float dltTime)
- {
- if(!wave)
- {
- StopNow();
- return;
- }
- //Счётчик времени
- bool isLoop = (sbfSound.setup.GetModeLoop() != SoundBankFileSetup::mode_loop_diasble);
- currentTime += dltTime;
- if(!wave->wave)
- {
- //Если играем тишину, то только проверяем счётчик и занимаем очередь
- if(currentTime >= wave->playTime)
- {
- StopNow();
- }
- return;
- }
- //Зацикливаем счётчик времени
- if(isLoop)
- {
- while(currentTime >= wave->playTime)
- {
- currentTime -= wave->playTime;
- }
- if(currentTime < 0.0f) currentTime = 0.0f;
- }
- //Следим за состоянием канала
- if(channel)
- {
- if(!channel->IsLost(this))
- {
- if(channel->IsPlay())
- {
- //Обновим позицию 3D звука
- Update3DPosition(true);
- channel->SetLowPriority((states & s_outofrange) != 0);
- //Хот фикс зависшего канала
- if(currentTime > wave->playTime + 1.0f)
- {
- if(!channel->IsPause())
- {
- channel->FadeOut(1.0f);
- }else{
- StopNow();
- }
- }
- return;
- }else{
- StopNow();
- return;
- }
- }else{
- channel = null;
- }
- }
- //Время на доигрывание звука
- float tailTime = wave->playTime - currentTime;
- if(tailTime <= 0.0f)
- {
- StopNow();
- return;
- }
- //Решаем что делать с отсутствующим каналом
- Update3DPosition(false);
- if((states & s_outofrange) != 0)
- {
- //3D звук за пределами радиуса, ничего не делаем
- return;
- }
- //Смотрим сколько осталось доигрывать звуку
-
- Assert(wave->wave);
- if(!isLoop)
- {
- if(tailTime <= c_time_to_skip_lost_ms*0.001f || tailTime <= wave->wave->unimportantTime)
- {
- //Фэйковое доигрывание без попытки востановить канал
- return;
- }
- }
- //Встаём/обновляем очередь на востановление канала
- dword priority = sbfSound.setup.GetPriority();
- Assert(!channel);
- soundScene.SetToContinueQueue(this, tailTime, priority, isLoop);
- }
- //Написать в лог сообщение об неудалённом звуке
- void Sound::UnReleaseMessage(const char * sceneOvner)
- {
- if(!(states & att_isAutoDelete))
- {
- api->Trace("Unrelease sound: %s, (scene: \"%s\", cpp: %s, %i, sbank: %s)", sbfSound.name, sceneOvner, cppFile, cppLine, soundBankName);
- }
- }
- //Установить команду на исполнение
- __forceinline void Sound::SetCommand(States cmd)
- {
- if((states & cmd_mask) == cmd_none)
- {
- if(cmd != cmd_none)
- {
- //Если не пустая команда, то подпишемся на разовое исполнение
- soundScene.ExecuteSoundCommand(this);
- }
- }
- //Замещаем текущую команду новой
- states = (states & ~cmd_mask) | cmd;
- }
- //Запустить звук на проигрывание немедленно
- void Sound::PlayNow(bool isFadeIn)
- {
- Assert(!(states & s_play));
- //Канала активного быть не должно сейчас и играть не должны
- Assert(!channel);
- //Волна для проигрывания
- if((states & s_pause) == 0)
- {
- //Новая волна
- dword waveIndex = sbfSound.SelectWaveIndex();
- wave = &sbfSound.waves[waveIndex];
- phonemes = null;
- currentTime = 0.0f;
- pausePosition = 0;
- if(!wave->wave && wave->playTime < 1e-3f)
- {
- //Просто пропускаем проигрывание
- return;
- }
- //Проверяем очередь
- if(sbfSound.setup.maxCount > 0)
- {
- if(sbfSound.playSoundsCount >= sbfSound.setup.maxCount)
- {
- //Надо завершить самый давний звук в пользу текущего
- Sound * s = (Sound *)sbfSound.playSoundsList;
- Assert(s);
- for(; s->playNext; s = s->playNext);
- s->Replase();
- }
- }
- //Добавляемся в список проигрываемых
- playPrev = null;
- playNext = (Sound *)sbfSound.playSoundsList;
- sbfSound.playSoundsList = this;
- if(playNext)
- {
- playNext->playPrev = this;
- }
- }
- Assert(wave);
- Assert(wave->playTime > 0.0f);
- //Настраиваем флажки
- states |= s_play;
- states &= ~s_outofrange;
- //Скажем сцене обновлять звук
- soundScene.StartUpdate(this);
- //Проверяем дистанцию, если звук 3D
- Update3DPosition(false);
- if(states & s_outofrange)
- {
- //Пока нет необходимости заводить канал
- return;
- }
- //Создаём канал для волны
- channel = soundScene.GetSoundsEngine().GetSoundChannel(sbfSound, wave, pausePosition, soundScene.GetSceneMaster(), this);
- if(channel)
- {
- //Канал удалось создать, работаем в нормальном режиме
- UpdateVolume();
- Update3DPosition(true);
- if(isFadeIn)
- {
- channel->FadeIn(fadeTime);
- }else{
- channel->Play();
- }
- }
- }
- //Остановить звук немедленно
- void Sound::StopNow(bool noRelease)
- {
- wave = null;
- phonemes = null;
- pausePosition = 0;
- if(states & s_play)
- {
- //Исключаем из списка проигрываемых
- if(playPrev)
- {
- playPrev->playNext = playNext;
- }else{
- sbfSound.playSoundsList = playNext;
- }
- if(playNext)
- {
- playNext->playPrev = playPrev;
- }
- //Останавливаем обновление
- soundScene.StopUpdate(this);
- }
- //Устанавливаем текущее состояние
- states &= ~s_mask;
- //Освобождаем канал, если использовали
- if(channel)
- {
- soundScene.GetSoundsEngine().ReleaseSoundChannel(channel, this);
- channel = null;
- }
- soundScene.RemoveFromContinueQueue(this);
- //Смотрим атрибут самоудаления
- if(states & att_isAutoDelete)
- {
- if(!noRelease)
- {
- Release();
- }
- }
- }
- //Заместить этот звук новым
- void Sound::Replase()
- {
- //Удалим канал с быстрым фэйдом
- if(channel)
- {
- channel->FadeOut(SoundsEngine::c_replaceFadeTimeInMs*0.001f);
- channel = null;
- }
- StopNow();
- }
- //Обновить громкость звука
- __forceinline void Sound::UpdateVolume()
- {
- if(channel)
- {
- #ifndef NO_TOOLS
- if(wave)
- {
- channel->FixWaveVolume(wave->volume);
- }
- #endif
- if(sbfSound.setup.GetFxMode() != SoundBankFileSetup::mode_fx_music)
- {
- channel->SetVolume(currentVolume*soundScene.GetVolumeSounds());
- }else{
- channel->SetVolume(currentVolume*soundScene.GetVolumeMusic());
- }
- }
- }
- //Обновить позицию звука
- __forceinline float Sound::Update3DPosition(bool isUpdateChannel)
- {
- if(states & att_is3D)
- {
- //Квадрат дистанции до слушателя
- FxVoice::Locator loc;
- Vector localPos(0.0f);
- float dist2 = 0.0f;
- bool inRange = soundScene.ListenerTransfromPosition(globalPos, sbfSound.att.maxDist2, localPos, dist2);
- if(!inRange)
- {
- //Ничего не слышно, обрубаем звук
- if(isUpdateChannel)
- {
- Assert(channel);
- Assert(!channel->IsLost(this));
- channel->SetLocators(&loc, 1);
- }
- states |= s_outofrange;
- return 0.0f;
- }
- //Дистанция от слушателя до звука
- float distXZ = localPos.GetLengthXZ();
- //Прямой звук. Определяем затухание
- loc.attenuation = sbfSound.att.Attenuation(dist2);
- if(loc.attenuation < 1e-10f)
- {
- //Слишком тихо, отражения даже и не пытаемся считать
- loc.attenuation = 0.0f;
- if(isUpdateChannel)
- {
- Assert(channel);
- Assert(!channel->IsLost(this));
- channel->SetLocators(&loc, 1);
- }
- states |= s_outofrange;
- return 0.0f;
- }
- states &= ~s_outofrange;
- if(!isUpdateChannel) return loc.attenuation;
- Assert(channel);
- Assert(!channel->IsLost(this));
- //Определяем направление от слушателя до звука
- const float headRad = 1.0f;
- const float headDirThreshold = 0.35f;
- if(distXZ > headRad)
- {
- //За пределами головы направление указываем обычно
- float kNorm = 1.0f/distXZ;
- loc.dirFront = localPos.z*kNorm;
- loc.dirRight = localPos.x*kNorm;
- }else
- if(distXZ > headRad*headDirThreshold)
- {
- //Внутри головы начинаем терять направление
- float kLen = (distXZ - headDirThreshold)/(1.0f - headDirThreshold); //1 на внешнем радиусе и 0 на внутренем
- float kNorm = kLen*1.0f/distXZ;
- loc.dirFront = localPos.z*kNorm;
- loc.dirRight = localPos.x*kNorm;
- }else{
- //С какого то порога направления нет
- loc.dirFront = 0.0f;
- loc.dirRight = 0.0f;
- }
- channel->SetLocators(&loc, 1);
- return loc.attenuation;
- }
- return 0.0f;
- }
- #ifndef STOP_DEBUG
- #include "..\..\common_h\render.h"
- #endif
- //Отобразить отладочную информацию
- void Sound::DebugDraw(dword debugStates, long & line, const char * sceneOvner)
- {
- #ifndef STOP_DEBUG
- if(states & s_play)
- {
- if(states & att_is3D)
- {
- if(debugStates & SoundsEngine::dbg_draw3d)
- {
- DebugDraw3D(debugStates & SoundsEngine::dbg_drawlevel_mask, sceneOvner);
- }
- }else{
- if(debugStates & SoundsEngine::dbg_draw2d)
- {
- DebugDraw2D(debugStates & SoundsEngine::dbg_drawlevel_mask, line, sceneOvner);
- }
- }
- }
- #endif
- }
- //Нарисовать слушателя
- void Sound::DebugDrawListener(dword debugStates, const Matrix & listener, const char * sceneOvner)
- {
- #ifndef STOP_DEBUG
- if(debugStates & SoundsEngine::dbg_drawlistener)
- {
- dword drawLevel = debugStates & SoundsEngine::dbg_drawlevel_mask;
- //Рендер для вывода информации
- static IRender * render = null;
- if(!render)
- {
- render = (IRender *)api->GetService("DX9Render");
- if(!render) return;
- }
- //Рисуем слушателя
- if(drawLevel == SoundsEngine::dbg_drawlevel_max)
- {
- render->DrawCapsule(0.3f, 0.8f, 0x80808080, Matrix().RotateZ(PI*0.5f)*listener);
- render->DrawMatrix(listener);
- render->Print(listener.pos, 40.0f, 0.0f, 0xffffffff, "Sound listener");
- render->Print(listener.pos, 40.0f, 1.1f, 0xffffffff, "\"%s\"", sceneOvner);
- }else{
- render->DrawMatrix(listener);
- }
- }
- #endif
- }
- //Написать о параметрах эффекта среды окружения
- void Sound::DebugDrawEnvironment(dword debugStates, long & line, const char * sceneOvner, const FxScene::EnvParams & env)
- {
- #ifndef STOP_DEBUG
- if(debugStates & (SoundsEngine::dbg_drawlistener | SoundsEngine::dbg_draw2d | SoundsEngine::dbg_draw3d))
- {
- //Рендер для вывода информации
- static IRender * render = null;
- if(!render)
- {
- render = (IRender *)api->GetService("DX9Render");
- if(!render) return;
- }
- //Рисуем слушателя
- float eps = 0.001f;
- if(!((fabs(env.dry - 1.0f) < eps) && (fabs(env.wet) < eps)))
- {
- render->Print(10.0f, 30.0f + line*20.0f, 0xcfffffff, "* Env. Scene: \"%s\", params: dry=%f, wet=%f, predelay=%f, early=%f, damping=%f, dispersion=%f",
- sceneOvner,
- env.dry, env.wet, env.predelayTime, env.earlyTime, env.earlyAttenuation, env.damping, env.dispersion);
- line++;
- }
- }
- #endif
- }
- //Вывести глобальные параметры
- void Sound::DebugDrawGlobals(dword debugStates, SoundService & service)
- {
- #ifndef STOP_DEBUG
- SoundsEngine & engine = service.Engine();
- dword drawLevel = debugStates & SoundsEngine::dbg_drawlevel_mask;
- //Рендер для вывода информации
- static IRender * render = null;
- if(!render)
- {
- render = (IRender *)api->GetService("DX9Render");
- if(!render) return;
- }
- //Пишем общую статистику
- render->Print(10.0f, 10.0f, 0xcfffffff, "Play channels %3u of %3u, reserved play: %3u of %3u, continue waiting: %3u",
- engine.GetPlayChannels(), engine.GetMaxChannels(),
- engine.GetPlayReservedChannels(), engine.GetMaxReservedChannels(), service.GetContinueWaiting());
- #endif
- }
- #ifndef STOP_DEBUG
- //Вывести отладочную информацию для 3D звука
- void Sound::DebugDraw3D(dword drawLevel, const char * sceneOvner)
- {
- //Рендер для вывода информации
- static IRender * render = null;
- if(!render)
- {
- render = (IRender *)api->GetService("DX9Render");
- if(!render) return;
- }
- //Текущая реальная громкость
- char buf[64];
- if(channel)
- {
- if(!channel->IsPause())
- {
- crt_snprintf(buf, sizeof(buf) - 1, "vol = %2.3f", channel->DebugGetCurrentVolume());
- }else{
- crt_snprintf(buf, sizeof(buf) - 1, "channel on pause", channel->DebugGetCurrentVolume());
- }
- }else{
- crt_strcpy(buf, sizeof(buf) - 1, "silence mode");
- }
- //Общии параметры
- const float minDist = sqrtf(sbfSound.att.minDist2);
- const float maxDist = sqrtf(sbfSound.att.maxDist2);
- const float textViewDist = coremax(50.0f, maxDist + 10.0f);
- //Крестовина
- render->DrawLine(globalPos - Vector(minDist, 0.0f, 0.0f), 0xffff0000, globalPos + Vector(minDist, 0.0f, 0.0f), 0xffff0000);
- render->DrawLine(globalPos - Vector(minDist, 0.0f, 0.0f), 0xffff0000, globalPos - Vector(maxDist, 0.0f, 0.0f), 0xff0000ff);
- render->DrawLine(globalPos + Vector(minDist, 0.0f, 0.0f), 0xffff0000, globalPos + Vector(maxDist, 0.0f, 0.0f), 0xff0000ff);
- render->DrawLine(globalPos - Vector(0.0f, 0.0f, minDist), 0xffff0000, globalPos + Vector(0.0f, 0.0f, minDist), 0xffff0000);
- render->DrawLine(globalPos - Vector(0.0f, 0.0f, minDist), 0xffff0000, globalPos - Vector(0.0f, 0.0f, maxDist), 0xff0000ff);
- render->DrawLine(globalPos + Vector(0.0f, 0.0f, minDist), 0xffff0000, globalPos + Vector(0.0f, 0.0f, maxDist), 0xff0000ff);
- //Круги обозначающие границу в горизонтальной плоскости проходящей через позицию звука
- render->DrawXZCircle(globalPos, minDist, 0xffff0000);
- render->DrawXZCircle(globalPos, maxDist, 0xff0000ff);
- dword textColor = 0xffffffff;
- if(wave && currentTime > wave->playTime)
- {
- textColor = 0xffff2020;
- }
- if(drawLevel == SoundsEngine::dbg_drawlevel_max)
- {
- //Рисуем график затухания
- const float height = 4.0f;
- const dword color = 0xffc0ffc0;
- //Графики затухания
- for(long i = 0; i < 50; i++)
- {
- float k1 = i/50.0f;
- float k2 = (i + 1.0f)/50.0f;
- float d1 = minDist + (maxDist - minDist)*k1;
- float d2 = minDist + (maxDist - minDist)*k2;
- float y1 = sbfSound.att.Attenuation(d1*d1)*height;
- float y2 = sbfSound.att.Attenuation(d2*d2)*height;
- render->DrawLine(globalPos + Vector(0.0f, y1, d1), color, globalPos + Vector(0.0f, y2, d2), color);
- render->DrawLine(globalPos + Vector(d1, y1, 0.0f), color, globalPos + Vector(d2, y2, 0.0f), color);
- render->DrawLine(globalPos + Vector(0.0f, y1, -d1), color, globalPos + Vector(0.0f, y2, -d2), color);
- render->DrawLine(globalPos + Vector(-d1, y1, 0.0f), color, globalPos + Vector(-d2, y2, 0.0f), color);
- }
- //Кольца показывающие гравик в пространстве
- for(long i = 0; i < 10; i++)
- {
- float k = i/10.0f;
- float d = minDist + (maxDist - minDist)*k;
- float y = sbfSound.att.Attenuation(d*d)*height;
- render->DrawXZCircle(globalPos + Vector(0.0f, y, 0.0f), d, i ? 0x1fc0ffc0 : color);
- render->DrawXZCircle(globalPos, d, 0x1f0000ff);
- }
- //Текущая проекция позиции камеры на графике затухания
- Vector camPos = render->GetView().GetCamPos();
- Vector delta = globalPos - camPos;
- float d2 = delta.GetLength2();
- if(d2 <= sbfSound.att.maxDist2)
- {
- float y = sbfSound.att.Attenuation(d2)*height;
- float d = sqrtf(d2);
- render->DrawXZCircle(globalPos + Vector(0.0f, y, 0.0f), d, 0xff20ff20);
- render->DrawXZCircle(globalPos + Vector(0.0f, 0.0f, 0.0f), d, 0xff00cf00);
- }
- //Пишем расширенную информацию
- render->Print(globalPos, textViewDist, -2.0f, textColor, "%s", GetName());
- render->Print(globalPos, textViewDist, -1.0f, textColor, "scene: \"%s\"", sceneOvner);
- render->Print(globalPos, textViewDist, 0.0f, textColor, "%s", buf);
- render->Print(globalPos, textViewDist, 1.0f, textColor, "[%.1f of %.1f sec]", currentTime, wave ? wave->playTime : 0.0f);
- render->Print(globalPos, textViewDist, 2.0f, textColor, "prty = %i", sbfSound.setup.mode & SoundBankFileSetup::mode_priority_mask);
- render->Print(globalPos, textViewDist, 3.0f, textColor, "loop = %s", (states & att_isLoop) ? "true" : "false");
- }else{
- //Только подписываем некоторую текстовую информацию
- render->Print(globalPos, textViewDist, -1.0f, textColor, "%s", GetName());
- render->Print(globalPos, textViewDist, 0.0f, textColor, "%s", buf);
- render->Print(globalPos, textViewDist, 1.0f, textColor, "scene: \"%s\"", sceneOvner);
- }
- }
- //Вывести отладочную информацию для 2D звука
- void Sound::DebugDraw2D(dword drawLevel, long & line, const char * sceneOvner)
- {
- //Рендер для вывода информации
- static IRender * render = null;
- if(!render)
- {
- render = (IRender *)api->GetService("DX9Render");
- if(!render) return;
- }
- //Текущая реальная громкость
- char buf[64];
- if(channel)
- {
- if(!channel->IsPause())
- {
- crt_snprintf(buf, sizeof(buf) - 1, "vol = %2.3f", channel->DebugGetCurrentVolume());
- }else{
- crt_snprintf(buf, sizeof(buf) - 1, "channel on pause", channel->DebugGetCurrentVolume());
- }
- }else{
- crt_strcpy(buf, sizeof(buf) - 1, "silence mode");
- }
- //Вывод информации в зависимости от уровня
- dword textColor = 0xcfffffff;
- if(wave && currentTime > wave->playTime)
- {
- textColor = 0xcfff2020;
- }
- if(drawLevel == SoundsEngine::dbg_drawlevel_max)
- {
- render->Print(10.0f, 30.0f + line*20.0f, textColor, "S2d: %s, scene: \"%s\", [%.1f of %.1f sec], %s, prty = %i, loop = %s", GetName(), sceneOvner, currentTime, wave ? wave->playTime : 0.0f, buf, sbfSound.setup.mode & SoundBankFileSetup::mode_priority_mask, (states & att_isLoop) ? "true" : "false");
- }else{
- render->Print(10.0f, 30.0f + line*20.0f, textColor, "S2d: %s, scene: \"%s\", %s", GetName(), sceneOvner, buf);
- }
- line++;
- }
- #endif
|