| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557 |
- #include "SoundsEngine.h"
- #include "..\..\common_h\corecmds.h"
- #ifdef _XBOX
- #include <xmp.h>
- #endif
- SoundsEngine * SoundsEngine::engine = null;
- //-----------------------------------------------------------------------------------------------
- //Мастер сцены, применяющий к её звукам эффекты
- //-----------------------------------------------------------------------------------------------
- SoundsEngine::SceneMaster::SceneMaster()
- {
- Assert(SoundsEngine::engine != null);
- voice = null;
- silence = null;
- flags = 0;
- }
- SoundsEngine::SceneMaster::~SceneMaster()
- {
- //Удаляем объекты
- if(silence)
- {
- silence->DestroyVoice();
- silence = null;
- }
- if(voice)
- {
- voice->DestroyVoice();
- voice = null;
- }
- }
- HRESULT SoundsEngine::SceneMaster::Init()
- {
- //Создать войс для применения эффектов сцены
- Assert(!voice);
- Assert(!silence);
- //Войс
- HRESULT hr;
- XAUDIO2_VOICE_SENDS sendList;
- sendList.SendCount = 0;
- sendList.pSends = null;
- hr = SoundsEngine::engine->pXAudio2->CreateSubmixVoice(&voice, 2, GetFxMixFreq(), 0, 15, &sendList, null);
- if(hr != S_OK) return hr;
- //Создаём источник тишины, чтобы эффект работал постоянно
- XAUDIO2_SEND_DESCRIPTOR sendDesc;
- sendDesc.Flags = 0;
- sendDesc.pOutputVoice = voice;
- sendList.SendCount = 1;
- sendList.pSends = &sendDesc;
- WAVEFORMATEX format;
- format.wFormatTag = WAVE_FORMAT_PCM;
- format.nChannels = 2;
- format.nSamplesPerSec = SoundsEngine::GetFxMixFreq();
- format.wBitsPerSample = 16;
- format.nBlockAlign = (format.nChannels*format.wBitsPerSample)/8;
- format.nAvgBytesPerSec = (format.nChannels*format.wBitsPerSample*format.nSamplesPerSec)/8;
- format.cbSize = 0;
- Assert(SoundsEngine::engine->pXAudio2);
- hr = SoundsEngine::engine->pXAudio2->CreateSourceVoice(&silence, &format, 0, XAUDIO2_DEFAULT_FREQ_RATIO, null, &sendList, null);
- if(hr != S_OK) return hr;
- Assert(silence);
- hr = silence->SubmitSourceBuffer(&SoundsEngine::engine->silenceBuffer, null);
- if(hr != S_OK) return hr;
- return hr;
- }
- //Использовать этот мастер сцены, если возможно
- bool SoundsEngine::SceneMaster::Alloc()
- {
- if(flags & flags_isActive)
- {
- return false;
- }
- flags |= flags_isActive;
- Assert(voice);
- XAUDIO2_SEND_DESCRIPTOR sendDesc;
- sendDesc.Flags = 0;
- sendDesc.pOutputVoice = SoundsEngine::engine->fxPremasteringVoice;
- XAUDIO2_VOICE_SENDS sendList;
- sendList.SendCount = 1;
- sendList.pSends = &sendDesc;
- voice->SetOutputVoices(&sendList);
- return true;
- }
- //Удалить
- void SoundsEngine::SceneMaster::Release()
- {
- if((flags & flags_isActive) == 0)
- {
- return;
- }
- //Сбрасываем параметры эффект-процессора сцены
- fxScene.Clear();
- //Остановим звук тишины
- if(silence)
- {
- silence->Stop();
- }
- //Остановим отсоединим мастер сцены
- if(voice)
- {
- XAUDIO2_VOICE_SENDS sends;
- sends.SendCount = 0;
- sends.pSends = null;
- voice->SetEffectChain(null);
- voice->SetOutputVoices(&sends);
- }
- //Сбрасываем флажки
- flags = 0;
- }
- //Запустить работу мастера
- void SoundsEngine::SceneMaster::Resume()
- {
- if((flags & flags_isPause) == 0)
- {
- return;
- }
- if(flags & flags_isInitFx)
- {
- Assert(silence);
- silence->Start();
- fxScene.Reset();
- }
- flags &= ~flags_isPause;
- }
- //Остановить работу мастера
- void SoundsEngine::SceneMaster::Stop()
- {
- if(flags & flags_isPause)
- {
- return;
- }
- if(flags & flags_isInitFx)
- {
- Assert(silence);
- silence->Stop();
- fxScene.Reset();
- }
-
- flags |= flags_isPause;
- }
- //Установить параметры серды окружения
- void SoundsEngine::SceneMaster::SetEnvironment(const FxScene::EnvParams & params)
- {
- if((flags & flags_isInitFx) == 0)
- {
- //Описание эффекта
- XAUDIO2_EFFECT_DESCRIPTOR fxDesc;
- fxDesc.pEffect = (IXAPO *)&fxScene;
- fxDesc.InitialState = true;
- fxDesc.OutputChannels = 2;
- XAUDIO2_EFFECT_CHAIN fxChain;
- fxChain.EffectCount = 1;
- fxChain.pEffectDescriptors = &fxDesc;
- voice->SetEffectChain(&fxChain);
- silence->Start();
- flags |= flags_isInitFx;
- }
- fxScene.SetParams(params);
- }
- //-----------------------------------------------------------------------------------------------
- //Источник звука
- //-----------------------------------------------------------------------------------------------
- SoundsEngine::SoundChannel::SoundChannel() : xWmaBuffer(_FL_, 1)
- {
- voice = null;
- fxVoice = null;
- states = 0;
- lowPrtCounter = 0;
- mode = 0;
- format = 0;
- waveVolume = 0.0f;
- time = 0;
- fadeOutTime = 0.0f;
- samplesCount = 0;
- startPlayPosition = 0;
- continuePosition = 0;
- currentUniqPtr = null;
- }
- SoundsEngine::SoundChannel::~SoundChannel()
- {
- Assert(!voice);
- Assert(!fxVoice);
- Assert(!currentUniqPtr);
- }
- void SoundsEngine::SoundChannel::Release()
- {
- if(voice)
- {
- voice->DestroyVoice();
- voice = null;
- }
- if(fxVoice)
- {
- fxVoice->DestroyVoice();
- fxVoice = null;
- }
- currentUniqPtr = null;
- }
- //Запустить источник звука на проигрывание
- void SoundsEngine::SoundChannel::Play()
- {
- if(!(states & state_isPlay))
- {
- Assert(SoundsEngine::engine);
- bool isNeedPause = (SoundsEngine::engine->isPause != 0);
- Assert(voice);
- XAUDIO2_VOICE_SENDS sendList;
- sendList.SendCount = 1;
- XAUDIO2_SEND_DESCRIPTOR sendDesc;
- sendDesc.Flags = 0;
- sendDesc.pOutputVoice = fxVoice;
- sendList.pSends = &sendDesc;
- voice->SetOutputVoices(&sendList);
- if((states & state_isPause) == 0 && !isNeedPause)
- {
- voice->Start(0);
- }
- lowPrtCounter = 0;
- states &= ~state_fadeoutProcess;
- states |= state_isPlay;
- if(isNeedPause)
- {
- Pause(true);
- }
- }
- }
- //Приостоновить буффер не освобождая канала
- void SoundsEngine::SoundChannel::Pause(bool isPause)
- {
- if(((states & state_isPause) != 0) == isPause)
- {
- return;
- }
- if(isPause)
- {
- states |= state_isPause;
- if((states & state_isPlay) != 0 && voice)
- {
- voice->Stop();
- }
- }else{
- states &= ~state_isPause;
- if((states & state_isPlay) != 0 && voice)
- {
- voice->Start(0);
- }
- }
- }
- //Плавно увеличить громкость с текущего значения до максимума
- void SoundsEngine::SoundChannel::FadeIn(float time)
- {
- if(!(states & state_isPlay))
- {
- Assert(voice);
- //Сколько надо шагов
- float steps = time*SoundsEngine::GetFxMixFreq();
- if(steps < 16)
- {
- //Очень мало шагов, сразу проигрываем
- Play();
- return;
- }
- //Шаг с которым надо увеличивать громкость с 0 до 1
- float fadeDelta = 1.0f/steps;
- fxProcessor.FadeIn(fadeDelta);
- Play();
- }
- }
- //Плавно уменьшить громкость с текущего значения до нуля
- void SoundsEngine::SoundChannel::FadeOut(float time)
- {
- if((states & state_isPlay) && voice)
- {
- states |= state_fadeoutProcess;
- //Сколько надо шагов
- float steps = time*SoundsEngine::GetFxMixFreq();
- if(steps < 16)
- {
- //Очень мало шагов, просто останавливаем
- Stop();
- return;
- }
- //Шаг с которым надо уменьшать громкость с 1 до 0
- float fadeDelta = -1.0f/steps;
- fxProcessor.FadeOut(fadeDelta);
- fadeOutTime = time;
- }
- }
- //Установить позицию в 3D (включает позиционирование звука)
- void SoundsEngine::SoundChannel::SetLocators(const FxVoice::Locator * locs, dword count)
- {
- fxProcessor.SetLocators(locs, count);
- }
- //Установить громкость канала
- void SoundsEngine::SoundChannel::SetVolume(float volume)
- {
- fxProcessor.SetVolume(waveVolume*volume);
- }
- //Установить режим низчайшего приоритета, при котором можно сразу вытеснять канал
- void SoundsEngine::SoundChannel::SetLowPriority(bool isLowPriority)
- {
- if(!isLowPriority)
- {
- lowPrtCounter = 0;
- }else{
- lowPrtCounter++;
- if(lowPrtCounter > 0x0fffffff)
- {
- lowPrtCounter = 0x0fffffff;
- }
- }
- }
- //Установить громкость волны
- void SoundsEngine::SoundChannel::FixWaveVolume(float volume)
- {
- waveVolume = volume;
- }
- //Получить текущую громкость канала
- float SoundsEngine::SoundChannel::DebugGetCurrentVolume()
- {
- return fxProcessor.GetCurrentVolume();
- }
- //Активен ли канал для данного владельца
- bool SoundsEngine::SoundChannel::IsLost(void * uniqPtr)
- {
- return (currentUniqPtr != uniqPtr);
- }
- //На паузе ли буфер
- bool SoundsEngine::SoundChannel::IsPause()
- {
- return (states & state_isPause) != 0;
- }
- //Играет ли звук
- bool SoundsEngine::SoundChannel::IsPlay()
- {
- if(states & state_isPlay)
- {
- if(voice)
- {
- XAUDIO2_VOICE_STATE vstate;
- voice->GetState(&vstate);
- if(vstate.BuffersQueued > (states & state_buffersForStopMask))
- {
- if(!(states & state_fadeoutProcess))
- {
- return true;
- }else{
- float vol = fxProcessor.GetFadeVolume();
- if(vol > (0.1f/65536.0f))
- {
- return true;
- }
- }
- }
- }
- Stop();
- }
- return false;
- }
- //Получить позицию проигрывания в сэмплах
- bool SoundsEngine::SoundChannel::GetPlayPosition(dword & playPosition)
- {
- if(states & state_isPlay)
- {
- if(voice)
- {
- XAUDIO2_VOICE_STATE vstate;
- voice->GetState(&vstate);
- if(vstate.BuffersQueued)
- {
- //Позиция проигрывания в текущем буфере
- UINT64 currentPlayPos = vstate.SamplesPlayed + continuePosition - startPlayPosition;
- if((mode & SoundBankFileSetup::mode_loop_mask) != SoundBankFileSetup::mode_loop_diasble)
- {
- Assert(samplesCount > 0);
- currentPlayPos %= (UINT64)samplesCount;
- }
- if(currentPlayPos > 0xffffffff)
- {
- currentPlayPos = 0xffffffff;
- }
- playPosition = (dword)currentPlayPos;
- return true;
- }
- }
- Stop();
- }
- return false;
- }
- //Остановить канал
- void SoundsEngine::SoundChannel::Stop()
- {
- if(states & state_isPlay)
- {
- if(voice)
- {
- XAUDIO2_VOICE_SENDS sends;
- sends.SendCount = 0;
- sends.pSends = null;
- voice->SetOutputVoices(&sends);
- fxVoice->SetOutputVoices(&sends);
- fxProcessor.Reset();
- samplesCount = 0;
- startPlayPosition = 0;
- voice->DestroyVoice();
- voice = null;
- }
- states &= ~(state_isPlay | state_fadeoutProcess | state_isPause);
- lowPrtCounter = 0;
- }
- }
- //Получить логическое время
- long SoundsEngine::SoundChannel::GetTime()
- {
- if(states & state_fadeoutProcess)
- {
- //Если идёт процесс фейда, то возвращаем эмпирическое значение, зависящее от текущей громкости
- float vol = fxProcessor.GetCurrentVolume();
- vol = 1.0f - Clampf(vol);
- return long(vol*-1000000.0f);
- }
- return time;
- }
- //-----------------------------------------------------------------------------------------------
- //SoundsEngine
- //-----------------------------------------------------------------------------------------------
- SoundsEngine::SoundsEngine() : sceneMasters(_FL_, 256)
- {
- Assert(!engine);
- engine = this;
- //Системное
- pXAudio2 = null;
- masteringVoice = null;
- fxPremasteringVoice = null;
- musicPremasteringVoice = null;
- FxVoice::StaticInit(GetFxMixFreq());
- isPause = 0;
- notificationListenerForXbox = null;
- //Буфер тишины
- memset(silenceLoop, 0, sizeof(silenceLoop));
- memset(&silenceBuffer, 0, sizeof(silenceBuffer));
- silenceBuffer.Flags = XAUDIO2_END_OF_STREAM;
- silenceBuffer.AudioBytes = sizeof(silenceBuffer);
- silenceBuffer.pAudioData = (BYTE *)silenceLoop;
- silenceBuffer.LoopCount = XAUDIO2_LOOP_INFINITE;
- //Звуки
- dword c = 0;
- for(dword i = 0; i < c_soundChannels; i++)
- {
- sound[i] = &soundChannels[c++];
- }
- soundCount = 0;
- for(dword i = 0; i < c_reserveChannels; i++)
- {
- reserved[i] = &soundChannels[c++];
- }
- reservedCount = 0;
- Assert(c == c_totalSoundChannels);
- Assert(ARRSIZE(soundChannels) == c_totalSoundChannels);
- creationCounter = 0;
- #ifndef _XBOX
- HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
- #endif
- #ifndef NO_TOOLS
- previewMaster = null;
- previewMasterVolume = 1.0f;
- previewVoice = null;
- previewVoiceMirror = null;
- previewUserId[0] = previewUserId[1] = previewUserId[2] = previewUserId[3] = 0;
- #endif
- }
- SoundsEngine::~SoundsEngine()
- {
- Release();
- #ifndef _XBOX
- CoUninitialize();
- #endif
- Assert(engine == this);
- engine = null;
- }
- //Инициализировать
- bool SoundsEngine::Init()
- {
- HRESULT hr;
- dword flags = 0;
- XAUDIO2_PROCESSOR processor = XAUDIO2_DEFAULT_PROCESSOR;
- #ifdef _DEBUG
- //flags = XAUDIO2_DEBUG_ENGINE;
- #endif
- #ifdef _XBOX
- processor = XboxThread4;
- notificationListenerForXbox = XNotifyCreateListener(XNOTIFY_XMP);
- if(notificationListenerForXbox == null)
- {
- api->Trace("SoundService error: Can't create XNotifyCreateListener object!");
- }
- #endif
- if(FAILED(hr = XAudio2Create(&pXAudio2, flags, processor)))
- {
- api->Trace("SoundService error: Can't create XAudio2 object, error code: 0x%x", hr);
- return false;
- }
- //Мастер
- if(FAILED(hr = pXAudio2->CreateMasteringVoice(&masteringVoice)))
- {
- api->Trace("SoundService error: Can't create mastering voice object, error code: 0x%x", hr);
- return false;
- }
- Assert(masteringVoice);
- XAUDIO2_VOICE_SENDS sendToMaster;
- sendToMaster.SendCount = 1;
- XAUDIO2_SEND_DESCRIPTOR sendDesc;
- sendDesc.Flags = 0;
- sendDesc.pOutputVoice = masteringVoice;
- sendToMaster.pSends = &sendDesc;
- XAUDIO2_EFFECT_DESCRIPTOR fxDesc;
- fxDesc.pEffect = (IXAPO *)&fxPremaster;
- fxDesc.InitialState = true;
- fxDesc.OutputChannels = 2;
- XAUDIO2_EFFECT_CHAIN fxChain;
- fxChain.EffectCount = 1;
- fxChain.pEffectDescriptors = &fxDesc;
- //Премастер канала эффектов
- if(FAILED(hr = pXAudio2->CreateSubmixVoice(&fxPremasteringVoice, 2, GetFxMixFreq(), 0, 20, &sendToMaster, &fxChain)))
- {
- api->Trace("SoundService error: Can't create fx premastering voice object, error code: 0x%x", hr);
- return false;
- }
- Assert(fxPremasteringVoice);
- api->ExecuteCoreCommand(CoreCommand_CheckMemory());
- // float output4to2[2][4] = {{1.0f, 1.0f, 1.0f, 1.0f},{1.0f, 1.0f, 1.0f, 1.0f}};
- // hr = fxPremasteringVoice->SetOutputMatrix(masteringVoice, 4, 2, (float *)output4to2);
- //Премастер музыкального канала
- if(FAILED(hr = pXAudio2->CreateSubmixVoice(&musicPremasteringVoice, 2, GetMusMixFreq(), 0, 20, &sendToMaster)))
- {
- api->Trace("SoundService error: Can't create music premastering voice object, error code: 0x%x", hr);
- return false;
- }
- Assert(musicPremasteringVoice);
- //Инициализация каналов
- for(dword i = 0; i < ARRSIZE(soundChannels); i++)
- {
- SoundChannel & channel = soundChannels[i];
- XAUDIO2_EFFECT_DESCRIPTOR fxDesc;
- fxDesc.pEffect = (IXAPO *)&channel.fxProcessor;
- fxDesc.InitialState = true;
- fxDesc.OutputChannels = 2;
- XAUDIO2_EFFECT_CHAIN fxChain;
- fxChain.EffectCount = 1;
- fxChain.pEffectDescriptors = &fxDesc;
- HRESULT hr = pXAudio2->CreateSubmixVoice(&channel.fxVoice, 2, GetFxMixFreq(), 0, 10, null, &fxChain);
- if(hr != S_OK)
- {
- api->Trace("SoundsEngine::Init() -> CreateSubmixVoice: result failed: hr = 0x%x", hr);
- return false;
- }
- Assert(channel.fxVoice);
- }
- //Запускаем звуковую библиотеку
- pXAudio2->StartEngine();
- UpdateMusicState();
- return true;
- }
- //Освободить ресурсы и перейди в неинициализированное состояние
- void SoundsEngine::Release()
- {
- for(dword i = 0; i < ARRSIZE(soundChannels); i++)
- {
- soundChannels[i].Release();
- }
- for(dword i = 0; i < sceneMasters.Size(); i++)
- {
- sceneMasters[i]->Release();
- }
- Sleep(100);
- #ifndef NO_TOOLS
- if(previewVoice)
- {
- previewVoice->DestroyVoice();
- previewVoice = null;
- }
- if(previewVoiceMirror)
- {
- previewVoiceMirror->DestroyVoice();
- previewVoiceMirror = null;
- }
- if(previewMaster)
- {
- previewMaster->DestroyVoice();
- previewMaster = null;
- }
- #endif
- for(dword i = 0; i < sceneMasters.Size(); i++)
- {
- delete sceneMasters[i];
- sceneMasters[i] = null;
- }
- sceneMasters.Empty();
- if(musicPremasteringVoice)
- {
- musicPremasteringVoice->DestroyVoice();
- musicPremasteringVoice = null;
- }
- if(fxPremasteringVoice)
- {
- fxPremasteringVoice->DestroyVoice();
- fxPremasteringVoice = null;
- }
- if(masteringVoice)
- {
- masteringVoice->DestroyVoice();
- masteringVoice = null;
- }
- if(pXAudio2)
- {
- pXAudio2->StopEngine();
- Sleep(100);
- pXAudio2->Release();
- pXAudio2 = null;
- }
- dword c = 0;
- for(dword i = 0; i < c_soundChannels; i++)
- {
- sound[i] = &soundChannels[c++];
- }
- soundCount = 0;
- for(dword i = 0; i < c_reserveChannels; i++)
- {
- reserved[i] = &soundChannels[c++];
- }
- reservedCount = 0;
- creationCounter = 0;
- #ifdef _XBOX
- if(notificationListenerForXbox != null)
- {
- XCloseHandle(notificationListenerForXbox);
- }
- #endif
- }
- //Обновить состояние
- void SoundsEngine::Update()
- {
- //Глушим доигрываемые каналы
- for(dword i = 0; i < reservedCount; i++)
- {
- if(!reserved[i]->IsPlay())
- {
- reserved[i]->Stop();
- ExchangeChannels(reserved[i], reserved[reservedCount - 1]);
- reservedCount--;
- }
- }
- //Глушим зависшие каналы (PCM fix)
- for(dword i = 0; i < soundCount; i++)
- {
- dword pos = 0;
- if(sound[i]->GetPlayPosition(pos))
- {
- if(pos > sound[i]->samplesCount*2)
- {
- //Принудительно останавливаем (1 канал за кадр)
- ReleaseSoundChannel(sound[i], sound[i]->currentUniqPtr);
- break;
- }
- }
- }
- #ifdef _XBOX
- if(notificationListenerForXbox)
- {
- //Смотрим состояние проигрывателя
- DWORD msgFilter;
- ULONG_PTR param;
- if(XNotifyGetNext(notificationListenerForXbox, 0, &msgFilter, ¶m))
- {
- if(msgFilter == XN_XMP_STATECHANGED)
- {
- UpdateMusicState();
- }
- }
- }
- #endif
- }
- //Приостановить проигрывание звуков
- void SoundsEngine::SetPause(bool isSetPause)
- {
- // api->Trace("SoundsEngine> Set pause: %s, current flag is %i", isSetPause ? "true" : "false", isSetPause);
- if((isPause != 0) == isSetPause)
- {
- return;
- }
- isSetPause ? 1 : 0;
- //Глушим доигрываемые каналы
- if(isSetPause)
- {
- // api->Trace("SoundsEngine> Set to pause");
- //Отмечаем, что на паузе
- isPause = 1;
- //Останавливаем хвосты
- for(dword i = 0; i < reservedCount; i++)
- {
- reserved[i]->Stop();
- }
- reservedCount = 0;
- //Останавливаем звуки
- for(dword i = 0; i < soundCount; i++)
- {
- sound[i]->Pause(true);
- }
- //Останавливаем мастера сцен
- for(dword i = 0; i < sceneMasters.Size(); i++)
- {
- sceneMasters[i]->Stop();
- }
- }else{
- // api->Trace("SoundsEngine> Resume from pause");
- //Отмечаем, что работаем
- isPause = 0;
- //Запускаем мастера сцен
- for(dword i = 0; i < sceneMasters.Size(); i++)
- {
- sceneMasters[i]->Resume();
- }
- //Востанавливаем звуки
- for(dword i = 0; i < soundCount; i++)
- {
- sound[i]->Pause(false);
- }
- }
- }
- //Создать мастер сцены
- SoundsEngine::SceneMaster * SoundsEngine::CreateSceneMaster()
- {
- //Пробуем выделить среди созданных
- for(dword i = 0; i < sceneMasters.Size(); i++)
- {
- if(sceneMasters[i]->Alloc())
- {
- return sceneMasters[i];
- }
- }
- //Добавляем объект эффекта окружения
- SceneMaster * sm = NEW SceneMaster();
- HRESULT hr = sm->Init();
- if(hr == S_OK)
- {
- Verify(sm->Alloc());
- sceneMasters.Add(sm);
- return sm;
- }
- delete sm;
- return null;
- }
- //Попытаться получить доступный звуковой канал
- SoundsEngine::SoundChannel * SoundsEngine::GetSoundChannel(SoundBankFileSound & sbfs, SoundBankFileWaveInfo * selWave, dword startPosition, SceneMaster & scene, void * uniqPtr)
- {
- //Получаем волну, которую будем проигрывать
- Assert(selWave);
- SoundBankFileWave * wave = selWave->wave;
- if(!wave)
- {
- //Проигрывание тишины
- return null;
- }
- //Контроль логического времени создания
- if(creationCounter > 0xfffffff)
- {
- for(dword i = 0; i < c_totalSoundChannels; i++)
- {
- soundChannels[i].time -= 0xff00000;
- if(soundChannels[i].time < 0)
- {
- soundChannels[i].time = 0;
- }
- }
- }
- //Если всё занято, пробуем освободить канал
- if(soundCount >= c_soundChannels)
- {
- //Надо освободить какой нибудь, поскольку свободных уже нет
- dword soundPriority = sbfs.setup.mode & SoundBankFileSetup::mode_priority_mask;
- long bestIndex = ChannelSelector(sound, soundCount, soundPriority, creationCounter);
- if(bestIndex < 0)
- {
- return null; //С текущим или более низким приоритетом каналов нет, поэтому ничего не можем сделать
- }
- //Освобождаем 1 канал в конце массива
- sound[bestIndex]->currentUniqPtr = null;
- soundCount = c_soundChannels - 1;
- ExchangeChannels(sound[bestIndex], sound[c_soundChannels - 1]);
- //Теперь решаем, отправить выбраный на фейд или убить сразу
- if(reservedCount < c_reserveChannels)
- {
- bestIndex = reservedCount++;
- }else{
- //Поступаем аналогично с доигрываемыми звуками
- bestIndex = ChannelSelector(reserved, reservedCount, soundPriority, sound[c_soundChannels - 1]->GetTime());
- }
- if(bestIndex >= 0)
- {
- //Есть резервные каналы, оставляем звук фейдиться
- sound[c_soundChannels - 1]->FadeOut(c_replaceFadeTimeInMs*0.001f);
- ExchangeChannels(sound[c_soundChannels - 1], reserved[bestIndex]);
- }
- }
- //Формат волны
- dword waveFormat = wave->format;
- if((sbfs.setup.mode & SoundBankFileSetup::mode_fx_mask) == SoundBankFileSetup::mode_fx_music)
- {
- waveFormat |= SoundBankFileWave::f_tmp_music;
- }
- //Смотрим канал с подходящим форматом
- Assert(soundCount < c_soundChannels);
- #ifndef STOP_DEBUG
- /*
- //!!! Проверка, что свободные каналы не играют
- for(dword i = soundCount; i < c_soundChannels; i++)
- {
- if(sound[i]->voice)
- {
- XAUDIO2_VOICE_STATE vstate;
- sound[i]->voice->GetState(&vstate);
- Assert(vstate.BuffersQueued == 0);
- }
- }
- //*/
- #endif
- /*
- for(dword i = soundCount; i < c_soundChannels; i++)
- {
- if(sound[i]->format == waveFormat)
- {
- //Есть нужный формат, поместим его в конец активных
- ExchangeChannels(sound[soundCount], sound[i]);
- break;
- }
- }
- */
- SoundChannel * channel = sound[soundCount];
- //Гарантированно останавливаем канал
- channel->Stop();
- channel->states = 0;
- //Подготавливаем канал к использованию
- XAUDIO2_VOICE_SENDS sendList;
- sendList.SendCount = 1;
- XAUDIO2_SEND_DESCRIPTOR sendDesc;
- sendDesc.Flags = 0;
- sendDesc.pOutputVoice = null;
- sendList.pSends = &sendDesc;
- //if(channel->format != waveFormat/* || ((channel->mode & SoundBankFileSetup::mode_loop_mask) != SoundBankFileSetup::mode_loop_diasble)*/)
- {
- //Необходимо пересоздать голос под нужный формат
- HRESULT hr;
- IXAudio2SourceVoice * sourceVoice = null;
- sendDesc.pOutputVoice = channel->fxVoice;
- dword workFreq = GetFxMixFreq();
- dword flags = XAUDIO2_VOICE_NOPITCH;
- if(workFreq == (waveFormat & SoundBankFileWave::f_freq_mask))
- {
- flags |= XAUDIO2_VOICE_NOSRC;
- }
- /*if(sbfs.setup.GetFxMode() == SoundBankFileSetup::mode_fx_music)
- {
- flags |= XAUDIO2_VOICE_MUSIC;
- }*/
- hr = pXAudio2->CreateSourceVoice(&sourceVoice, (const WAVEFORMATEX *)wave->waveFormatInfo, 0, XAUDIO2_DEFAULT_FREQ_RATIO, null, &sendList, null);
- if(hr != S_OK)
- {
- //Фига се, чегото не создалось... пока проскипаем
- api->Trace("SoundsEngine::GetSoundChannel -> CreateSourceVoice return error code 0x%x", hr);
- Assert(sourceVoice);
- return null;
- }
- Assert(sourceVoice);
- if(channel->voice)
- {
- channel->voice->DestroyVoice();
- }
- channel->voice = sourceVoice;
- channel->format = waveFormat;
- }/*else{
- channel->voice->Stop();
- }*/
- soundCount++;
- //Определяем куда подключать звук
- switch(sbfs.setup.GetFxMode())
- {
- case SoundBankFileSetup::mode_fx_full:
- Assert(scene.voice);
- sendDesc.pOutputVoice = scene.voice;
- channel->fxProcessor.EnableEnvironment(true);
- break;
- case SoundBankFileSetup::mode_fx_premaster:
- sendDesc.pOutputVoice = fxPremasteringVoice;
- channel->fxProcessor.EnableEnvironment(false);
- break;
- case SoundBankFileSetup::mode_fx_master:
- sendDesc.pOutputVoice = masteringVoice;
- channel->fxProcessor.EnableEnvironment(false);
- break;
- case SoundBankFileSetup::mode_fx_music:
- sendDesc.pOutputVoice = musicPremasteringVoice;
- channel->fxProcessor.EnableEnvironment(false);
- break;
- default:
- Assert(false);
- }
- channel->fxVoice->SetOutputVoices(&sendList);
- //Сохраняем атрибуты текущего звука
- channel->mode = sbfs.setup.mode;
- channel->currentUniqPtr = uniqPtr;
- channel->waveVolume = selWave->volume;
- channel->pickAmp = wave->maxNormalizedAmp;
- channel->tailTime = wave->unimportantTime;
- channel->fadeOutTime = 0.0f;
- channel->time = creationCounter++;
- channel->samplesCount = wave->samplesCount;
- //Фикс для незацикленных PCM, которые выходят за пределы буфера. Начало
- UINT32 flagsForMainBuffer = XAUDIO2_END_OF_STREAM;
- bool isPCM_fix_on = false;
- if((wave->format & SoundBankFileWave::f_format_mask) == SoundBankFileWave::f_format_pcm)
- {
- isPCM_fix_on = true;
- flagsForMainBuffer = 0;
- }
- //Заполняем буффер
- bool isLoop = sbfs.setup.GetModeLoop() != SoundBankFileSetup::mode_loop_diasble;
- XAUDIO2_BUFFER xbuffer;
- xbuffer.Flags = flagsForMainBuffer;
- xbuffer.AudioBytes = wave->dataSize;
- xbuffer.pAudioData = (BYTE *)wave->data;
- xbuffer.PlayBegin = startPosition & ~0x7f; //Для XMA надо выравнивать первый сэмпл по 128
- xbuffer.PlayLength = 0;
-
- //*
- xbuffer.PlayLength = wave->samplesCount - xbuffer.PlayBegin;
- if((waveFormat & SoundBankFileWave::f_format_mask) == SoundBankFileWave::f_format_xma)
- {
- Assert((xbuffer.PlayLength & 0x7f) == 0);
- }
- //*/
- xbuffer.LoopBegin = isLoop ? 0 : XAUDIO2_NO_LOOP_REGION;
- xbuffer.LoopLength = 0;
- xbuffer.LoopCount = isLoop ? XAUDIO2_LOOP_INFINITE : 0;
- xbuffer.pContext = null;
- //Устанавливаем буфер
- HRESULT hr = XAUDIO2_E_INVALID_CALL;
- if((waveFormat & SoundBankFileWave::f_format_mask) != SoundBankFileWave::f_format_xvma)
- {
- hr = channel->voice->SubmitSourceBuffer(&xbuffer, null);
- }else{
- //Дополнительные плюшки для xWMA
- const SoundBankFileWave::XWMAWAVEFORMAT * xwmaFormat = (const SoundBankFileWave::XWMAWAVEFORMAT *)wave->waveFormatInfo;
- if(channel->xWmaBuffer.Size() < xwmaFormat->tableCount)
- {
- channel->xWmaBuffer.AddElements(xwmaFormat->tableCount - channel->xWmaBuffer.Size());
- }
- memcpy(channel->xWmaBuffer.GetBuffer(), xwmaFormat->table, xwmaFormat->tableCount*sizeof(dword));
- XAUDIO2_BUFFER_WMA wma;
- wma.PacketCount = xwmaFormat->tableCount;
- wma.pDecodedPacketCumulativeBytes = channel->xWmaBuffer.GetBuffer();
- hr = channel->voice->SubmitSourceBuffer(&xbuffer, &wma);
- }
- if(hr != S_OK)
- {
- //Не получилось подписать данный буфер на проигрывание, похоже баг в формате
- ReleaseSoundChannel(channel, uniqPtr);
- api->Trace("SoundsEngine::GetSoundChannel -> SubmitSourceBuffer return error code 0x%x (for sound %s, wave: %i)", hr, sbfs.name, sbfs.waves - selWave);
- return null;
- }
- //Сохраняем стартовую позицию
- Assert(channel->samplesCount > 0);
- Assert(channel->voice);
- XAUDIO2_VOICE_STATE vstate;
- channel->voice->GetState(&vstate);
- Assert(vstate.BuffersQueued > 0);
- Assert(vstate.SamplesPlayed == 0);
- channel->startPlayPosition = vstate.SamplesPlayed;
- channel->continuePosition = xbuffer.PlayBegin;
- //Фикс для незацикленных PCM, которые выходят за пределы буфера. Окончание
- if(isPCM_fix_on)
- {
- hr = channel->voice->SubmitSourceBuffer(&silenceBuffer, null);
- if(hr != S_OK)
- {
- //Не получилось подписать данный буфер на проигрывание, похоже баг в формате
- ReleaseSoundChannel(channel, uniqPtr);
- api->Trace("SoundsEngine::GetSoundChannel -> SubmitSourceBuffer (PCM fix loop buffer) return error code 0x%x (for sound %s, wave: %i)", hr, sbfs.name, sbfs.waves - selWave);
- return null;
- }
- channel->states |= 1;
- }
- return channel;
- }
- //Освободить звуковой канал
- void SoundsEngine::ReleaseSoundChannel(SoundChannel * ch, void * uniqPtr)
- {
- if(ch->currentUniqPtr != uniqPtr) return;
- //Переводим канал к свободным
- for(dword i = 0; i < soundCount; i++)
- {
- if(sound[i] == ch)
- {
- ch->Stop();
- if(ch->voice)
- {
- ch->voice->DestroyVoice();
- ch->voice = null;
- }
- ch->currentUniqPtr = null;
- soundCount--;
- ExchangeChannels(sound[i], sound[soundCount]);
- return;
- }
- }
- //Сюда попадать не должно
- Assert(false);
- }
- //Получить количество активных каналов
- dword SoundsEngine::GetPlayChannels()
- {
- return soundCount;
- }
- //Получить максимальное количество каналов
- dword SoundsEngine::GetMaxChannels()
- {
- return c_soundChannels;
- }
- //Получить количество активных каналов для доигрывания
- dword SoundsEngine::GetPlayReservedChannels()
- {
- return reservedCount;
- }
- //Получить максимальное количество каналов для доигрывания
- dword SoundsEngine::GetMaxReservedChannels()
- {
- return c_reserveChannels;
- }
- #ifdef _XBOX
- //Получить объект XAudio
- IXAudio2 * SoundsEngine::GetXAudio()
- {
- return pXAudio2;
- }
- #endif
- #ifndef NO_TOOLS
- //Запустить волну на проигрывание 16бит (для звукового редактора)
- bool SoundsEngine::EditPrewiewPlay(const dword userId[4], EditPrewiewWaveParams * mainWave, EditPrewiewWaveParams * mirrorWave, bool isMirror)
- {
- //-------------------------------------------------------------------
- static IXAudio2SubmixVoice * testFxVoice = null;
- //Отладка эффектов
- #ifdef _DEBUG
- if(false)
- //if(!testFxVoice)
- #else
- if(false)
- #endif
- {
- XAUDIO2_VOICE_SENDS sendList;
- sendList.SendCount = 1;
- XAUDIO2_SEND_DESCRIPTOR sendDesc;
- sendDesc.Flags = 0;
- sendDesc.pOutputVoice = masteringVoice;
- sendList.pSends = &sendDesc;
- static FxPremaster fxPremaster;
- static FxScene fxScene;
- XAUDIO2_EFFECT_DESCRIPTOR fxDesc[3];
- fxDesc[0].pEffect = (IXAPO *)&fxScene;
- fxDesc[0].InitialState = true;
- fxDesc[0].OutputChannels = 2;
- XAUDIO2_EFFECT_CHAIN fxChain;
- fxChain.EffectCount = 1;
- fxChain.pEffectDescriptors = &fxDesc[0];
- HRESULT hr = pXAudio2->CreateSubmixVoice(&testFxVoice, 2, 44100, 0, 15, &sendList, &fxChain);
-
-
- sendList.SendCount = 1;
- sendDesc.Flags = 0;
- sendDesc.pOutputVoice = testFxVoice;
- WAVEFORMATEX format;
- format.wFormatTag = WAVE_FORMAT_PCM;
- format.nChannels = 2;
- format.nSamplesPerSec = 44100/8;
- format.wBitsPerSample = 16;
- format.nBlockAlign = (format.nChannels*format.wBitsPerSample)/8;
- format.nAvgBytesPerSec = (format.nChannels*format.wBitsPerSample*format.nSamplesPerSec)/8;
- format.cbSize = 0;
- Assert(pXAudio2);
- hr = pXAudio2->CreateSourceVoice(&previewVoice, &format, 0, XAUDIO2_DEFAULT_FREQ_RATIO, null, &sendList, null);
- Assert(hr == S_OK)
- XAUDIO2_BUFFER xbuffer;
- xbuffer.Flags = XAUDIO2_END_OF_STREAM;
- static short buffer[4096];
- memset(buffer, 0, ARRSIZE(buffer));
- xbuffer.AudioBytes = 4096;
- xbuffer.pAudioData = (BYTE *)buffer;
- xbuffer.PlayBegin = 0;
- xbuffer.PlayLength = 0;
- xbuffer.LoopBegin = 0;
- xbuffer.LoopLength = 0;
- xbuffer.LoopCount = XAUDIO2_LOOP_INFINITE;
- xbuffer.pContext = null;
- hr = previewVoice->SubmitSourceBuffer(&xbuffer, null);
- previewVoice->Start();
- previewVoice = null;
- }
- //-------------------------------------------------------------------
- if(!previewMaster)
- {
- XAUDIO2_VOICE_SENDS sendToMaster;
- sendToMaster.SendCount = 1;
- XAUDIO2_SEND_DESCRIPTOR sendDesc;
- sendDesc.Flags = 0;
- sendDesc.pOutputVoice = masteringVoice;
- sendToMaster.pSends = &sendDesc;
- if(pXAudio2->CreateSubmixVoice(&previewMaster, 2, GetMusMixFreq(), 0, 25, &sendToMaster) != S_OK)
- {
- previewMaster = null;
- }
- EditPrewiewSetMasterVolume(previewMasterVolume);
- }
- //Если играло, то надо остановить проигрывание
- static dword stop_userId[4] = {0, 0, 0, 0};
- EditPrewiewStop(stop_userId);
- Assert(!previewVoice);
- Assert(!previewVoiceMirror);
- Assert((previewUserId[0] | previewUserId[1] | previewUserId[2] | previewUserId[3]) == 0);
- //Идентификатор
- Assert((userId[0] | userId[1] | userId[2] | userId[3]) != 0);
- Assert(mainWave != null);
- previewUserId[0] = userId[0];
- previewUserId[1] = userId[1];
- previewUserId[2] = userId[2];
- previewUserId[3] = userId[3];
- //Куда выводить звук
- Assert(masteringVoice);
- XAUDIO2_VOICE_SENDS sendList;
- sendList.SendCount = 1;
- XAUDIO2_SEND_DESCRIPTOR sendDesc;
- sendDesc.Flags = 0;
- if(testFxVoice)
- {
- sendDesc.pOutputVoice = testFxVoice;
- }else{
- if(!previewMaster)
- {
- sendDesc.pOutputVoice = masteringVoice;
- }else{
- sendDesc.pOutputVoice = previewMaster;
- }
- }
- sendList.pSends = &sendDesc;
- //Формат волны
- WAVEFORMATEX format;
- format.wFormatTag = WAVE_FORMAT_PCM;
- format.nChannels = mainWave->isStereo ? 2 : 1;
- format.nSamplesPerSec = mainWave->sampleRate;
- format.wBitsPerSample = 16;
- format.nBlockAlign = (format.nChannels*format.wBitsPerSample)/8;
- format.nAvgBytesPerSec = (format.nChannels*format.wBitsPerSample*format.nSamplesPerSec)/8;
- format.cbSize = 0;
- //Создаём войс для воспроизведения
- Assert(pXAudio2);
- HRESULT hr = pXAudio2->CreateSourceVoice(&previewVoice, &format, 0, XAUDIO2_DEFAULT_FREQ_RATIO, null, &sendList, null);
- if(hr != S_OK)
- {
- Assert(!previewVoice);
- return false;
- }
- Assert(previewVoice);
- XAUDIO2_BUFFER xbuffer;
- xbuffer.Flags = XAUDIO2_END_OF_STREAM;
- xbuffer.AudioBytes = mainWave->dataSize;
- xbuffer.pAudioData = (BYTE *)mainWave->data;
- xbuffer.PlayBegin = 0;
- xbuffer.PlayLength = 0;
- xbuffer.LoopBegin = 0;
- xbuffer.LoopLength = 0;
- xbuffer.LoopCount = 0;
- xbuffer.pContext = null;
- hr = previewVoice->SubmitSourceBuffer(&xbuffer, null);
- if(hr != S_OK)
- {
- EditPrewiewStop(stop_userId);
- return false;
- }
- if(mirrorWave)
- {
- format.nChannels = mirrorWave->isStereo ? 2 : 1;
- format.nSamplesPerSec = mirrorWave->sampleRate;
- format.nBlockAlign = (format.nChannels*format.wBitsPerSample)/8;
- format.nAvgBytesPerSec = (format.nChannels*format.wBitsPerSample*format.nSamplesPerSec)/8;
- HRESULT hr = pXAudio2->CreateSourceVoice(&previewVoiceMirror, &format, 0, XAUDIO2_DEFAULT_FREQ_RATIO, null, &sendList, null);
- if(hr != S_OK)
- {
- Assert(!previewVoiceMirror);
- EditPrewiewStop(stop_userId);
- return false;
- }
- xbuffer.AudioBytes = mirrorWave->dataSize;
- xbuffer.pAudioData = (BYTE *)mirrorWave->data;
- hr = previewVoiceMirror->SubmitSourceBuffer(&xbuffer, null);
- if(hr != S_OK)
- {
- EditPrewiewStop(stop_userId);
- return false;
- }
- if(isMirror)
- {
- previewVoice->SetVolume(0.0f);
- previewVoiceMirror->SetVolume(1.0f);
- }else{
- previewVoice->SetVolume(1.0f);
- previewVoiceMirror->SetVolume(0.0f);
- }
- previewVoice->Start();
- previewVoiceMirror->Start();
- }else{
- previewVoice->SetVolume(1.0f);
- previewVoice->Start();
- }
- return true;
- }
- //Переключить волну на зеркальную или оригинальную
- bool SoundsEngine::EditPrewiewSwitch(const dword userId[4], bool isMirror)
- {
- if(previewUserId != userId)
- {
- return false;
- }
- if(!EditPrewiewIsPlay(userId, null))
- {
- return false;
- }
- if(!previewVoice || !previewVoiceMirror)
- {
- return false;
- }
- if(!isMirror)
- {
- previewVoice->SetVolume(1.0f);
- previewVoiceMirror->SetVolume(0.0f);
- }else{
- previewVoice->SetVolume(0.0f);
- previewVoiceMirror->SetVolume(1.0f);
- }
- return true;
- }
- //Играет ли волна на прослушивании (для звукового редактора)
- bool SoundsEngine::EditPrewiewIsPlay(const dword userId[4], dword * samplesCount, bool * playWithMirror)
- {
- static dword stop_userId[4] = {0, 0, 0, 0};
- if(previewVoice)
- {
- if((userId[0] | userId[1] | userId[2] | userId[3]) != 0)
- {
- if(((previewUserId[0] ^ userId[0]) | (previewUserId[1] ^ userId[1]) | (previewUserId[2] ^ userId[2]) | (previewUserId[3] ^ userId[3])) != 0)
- {
- return false;
- }
- }
- XAUDIO2_VOICE_STATE state;
- previewVoice->GetState(&state);
- if(state.BuffersQueued > 0)
- {
- if(samplesCount)
- {
- *samplesCount = (dword)state.SamplesPlayed;
- }
- if(playWithMirror)
- {
- *playWithMirror = (previewVoiceMirror != null);
- }
- return true;
- }
- EditPrewiewStop(stop_userId);
- }else{
- if(previewVoiceMirror)
- {
- EditPrewiewStop(stop_userId);
- }
- }
- return false;
- }
- //Остановить прослушивание волны
- void SoundsEngine::EditPrewiewStop(const dword userId[4])
- {
- if(previewVoice || previewVoiceMirror)
- {
- if((userId[0] | userId[1] | userId[2] | userId[3]) != 0)
- {
- if(((previewUserId[0] ^ userId[0]) | (previewUserId[1] ^ userId[1]) | (previewUserId[2] ^ userId[2]) | (previewUserId[3] ^ userId[3])) != 0)
- {
- return;
- }
- }
- if(previewVoice)
- {
- previewVoice->DestroyVoice();
- previewVoice = null;
- }
- if(previewVoiceMirror)
- {
- previewVoiceMirror->DestroyVoice();
- previewVoiceMirror = null;
- }
- }
- previewUserId[0] = previewUserId[1] = previewUserId[2] = previewUserId[3] = 0;
- }
- //Установить громкость прослушиваемой волны
- void SoundsEngine::EditPrewiewSetVolume(float volume, const dword userId[4])
- {
- if(previewVoice)
- {
- if((userId[0] | userId[1] | userId[2] | userId[3]) != 0)
- {
- if(((previewUserId[0] ^ userId[0]) | (previewUserId[1] ^ userId[1]) | (previewUserId[2] ^ userId[2]) | (previewUserId[3] ^ userId[3])) != 0)
- {
- return;
- }
- }
- float setVol = Clampf(volume, 0.0f, 1.0f);
- previewVoice->SetVolume(volume);
- if(previewVoiceMirror)
- {
- previewVoiceMirror->DestroyVoice();
- previewVoiceMirror = null;
- }
- }
- }
- //Установить громкость мастера предпрослушивания
- void SoundsEngine::EditPrewiewSetMasterVolume(float volume)
- {
- previewMasterVolume = volume;
- if(previewMaster)
- {
- previewMaster->SetVolume(volume);
- }
- }
- #endif
- //Обновить состояние музыкального канала в зависимости от состояния проигрывателя
- void SoundsEngine::UpdateMusicState()
- {
- #ifdef _XBOX
- XMP_STATE state;
- XMPGetStatus(&state);
- if(state == XMP_STATE_IDLE)
- {
- musicPremasteringVoice->SetVolume(1.0f);
- }else{
- musicPremasteringVoice->SetVolume(0.0f);
- }
- #endif
- }
- //Выбрать канал для замещения
- long SoundsEngine::ChannelSelector(SoundChannel ** ch, long count, long priority, long time)
- {
- long bestIndex = -1;
- dword bestPriority = priority;
- long bestTime = time;
- dword bestLowPrt = 0;
- bool bestIsLoop = false;
- bool bestIsTail = false;
- float bestTailTime = 1000000.0f;
- float bestPickVolume = 1.0f;
- for(long i = 0; i < count; i++)
- {
- SoundChannel * channel = ch[i];
- bool isLoop = (channel->mode & SoundBankFileSetup::mode_loop_mask) != SoundBankFileSetup::mode_loop_diasble;
- //Проверяем режим низкоприоритетной работы (3D звук за пределами радиуса)
- if(channel->lowPrtCounter > 0)
- {
- //Если переход с зацикленного звука на незацикленный, то не смотрим остальное
- if(channel->lowPrtCounter > bestLowPrt || (bestIsLoop && !isLoop))
- {
- bestIndex = i;
- bestLowPrt = channel->lowPrtCounter;
- bestIsLoop = isLoop;
- continue;
- }
- //Возможно будут ещё условия
- continue;
- }else
- if(bestLowPrt > 0)
- {
- continue;
- }
- //Пропускаем волны с большим приоритетом
- dword channelPriority = channel->mode & SoundBankFileSetup::mode_priority_mask;
- if(channelPriority > bestPriority)
- {
- continue;
- }
- //Расширеные параметры канала
- float pickVolume = channel->waveVolume*channel->pickAmp;
- float tailTime = 1000000.0f;
- bool isTail = false;
- if((channel->states & SoundChannel::state_fadeoutProcess) == 0)
- {
- if(!isLoop)
- {
- dword pos = 0;
- if(!channel->GetPlayPosition(pos)) pos = 0;
- dword tailSamples = channel->samplesCount - pos;
- float freq = (float)(channel->format & SoundBankFileWave::f_freq_mask);
- if(freq < 1.0f) freq = 1.0f;
- tailTime = (float)tailSamples/freq;
- isTail = (tailTime < channel->tailTime);
- }
- }else{
- //Если идёт процесс фейда, то возвращаем эмпирическое значение, зависящее от текущей громкости
- isLoop = false;
- float vol = Clampf(channel->fxProcessor.GetCurrentVolume());
- pickVolume *= vol;
- tailTime = vol*channel->fadeOutTime;
-
- }
- if(pickVolume < 0.00001f) pickVolume = 0.00001f;
- //Сначала проверияем приоритет
- if(bestIndex >= 0 && channelPriority == priority)
- {
- //Среди звуков с одинаковым приоритетом просматриваем остальные критерии
- if(bestIsTail == isTail)
- {
- if(bestTailTime*bestPickVolume < tailTime*pickVolume)
- {
- continue;
- }
- }else
- if(!isTail)
- {
- continue;
- }
- }
- //Звук с меньшим преоритетом всегда вытесняеться нисмотря на другие критерии
- bestIndex = i;
- bestPriority = channelPriority;
- bestTime = channel->GetTime();
- bestIsLoop = isLoop;
- bestIsTail = isTail;
- bestTailTime = tailTime;
- bestPickVolume = pickVolume;
- }
- return bestIndex;
- }
- //Поменять местами каналы
- __forceinline void SoundsEngine::ExchangeChannels(SoundChannel * & ch1, SoundChannel * & ch2)
- {
- SoundChannel * tmp = ch1;
- ch1 = ch2;
- ch2 = tmp;
- }
- //Получить частоту для канала эфектов
- dword SoundsEngine::GetFxMixFreq()
- {
- #ifdef _XBOX
- //static const dword fxSubMixFreq = dword(48000/XAUDIO2_QUANTUM_DENOMINATOR)*XAUDIO2_QUANTUM_DENOMINATOR;
- static const dword fxSubMixFreq = dword(44100/XAUDIO2_QUANTUM_DENOMINATOR)*XAUDIO2_QUANTUM_DENOMINATOR;
- #else
- static const dword fxSubMixFreq = dword(44100/XAUDIO2_QUANTUM_DENOMINATOR)*XAUDIO2_QUANTUM_DENOMINATOR;
- #endif
- return fxSubMixFreq;
- }
- //Получить частоту для канала музыки
- dword SoundsEngine::GetMusMixFreq()
- {
- #ifdef _XBOX
- //static const dword musSubMixFreq = dword(48000/XAUDIO2_QUANTUM_DENOMINATOR)*XAUDIO2_QUANTUM_DENOMINATOR;
- static const dword musSubMixFreq = dword(44100/XAUDIO2_QUANTUM_DENOMINATOR)*XAUDIO2_QUANTUM_DENOMINATOR;
- #else
- static const dword musSubMixFreq = dword(44100/XAUDIO2_QUANTUM_DENOMINATOR)*XAUDIO2_QUANTUM_DENOMINATOR;
- #endif
- return musSubMixFreq;
- }
|