SoundsEngine.cpp 43 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557
  1. #include "SoundsEngine.h"
  2. #include "..\..\common_h\corecmds.h"
  3. #ifdef _XBOX
  4. #include <xmp.h>
  5. #endif
  6. SoundsEngine * SoundsEngine::engine = null;
  7. //-----------------------------------------------------------------------------------------------
  8. //Мастер сцены, применяющий к её звукам эффекты
  9. //-----------------------------------------------------------------------------------------------
  10. SoundsEngine::SceneMaster::SceneMaster()
  11. {
  12. Assert(SoundsEngine::engine != null);
  13. voice = null;
  14. silence = null;
  15. flags = 0;
  16. }
  17. SoundsEngine::SceneMaster::~SceneMaster()
  18. {
  19. //Удаляем объекты
  20. if(silence)
  21. {
  22. silence->DestroyVoice();
  23. silence = null;
  24. }
  25. if(voice)
  26. {
  27. voice->DestroyVoice();
  28. voice = null;
  29. }
  30. }
  31. HRESULT SoundsEngine::SceneMaster::Init()
  32. {
  33. //Создать войс для применения эффектов сцены
  34. Assert(!voice);
  35. Assert(!silence);
  36. //Войс
  37. HRESULT hr;
  38. XAUDIO2_VOICE_SENDS sendList;
  39. sendList.SendCount = 0;
  40. sendList.pSends = null;
  41. hr = SoundsEngine::engine->pXAudio2->CreateSubmixVoice(&voice, 2, GetFxMixFreq(), 0, 15, &sendList, null);
  42. if(hr != S_OK) return hr;
  43. //Создаём источник тишины, чтобы эффект работал постоянно
  44. XAUDIO2_SEND_DESCRIPTOR sendDesc;
  45. sendDesc.Flags = 0;
  46. sendDesc.pOutputVoice = voice;
  47. sendList.SendCount = 1;
  48. sendList.pSends = &sendDesc;
  49. WAVEFORMATEX format;
  50. format.wFormatTag = WAVE_FORMAT_PCM;
  51. format.nChannels = 2;
  52. format.nSamplesPerSec = SoundsEngine::GetFxMixFreq();
  53. format.wBitsPerSample = 16;
  54. format.nBlockAlign = (format.nChannels*format.wBitsPerSample)/8;
  55. format.nAvgBytesPerSec = (format.nChannels*format.wBitsPerSample*format.nSamplesPerSec)/8;
  56. format.cbSize = 0;
  57. Assert(SoundsEngine::engine->pXAudio2);
  58. hr = SoundsEngine::engine->pXAudio2->CreateSourceVoice(&silence, &format, 0, XAUDIO2_DEFAULT_FREQ_RATIO, null, &sendList, null);
  59. if(hr != S_OK) return hr;
  60. Assert(silence);
  61. hr = silence->SubmitSourceBuffer(&SoundsEngine::engine->silenceBuffer, null);
  62. if(hr != S_OK) return hr;
  63. return hr;
  64. }
  65. //Использовать этот мастер сцены, если возможно
  66. bool SoundsEngine::SceneMaster::Alloc()
  67. {
  68. if(flags & flags_isActive)
  69. {
  70. return false;
  71. }
  72. flags |= flags_isActive;
  73. Assert(voice);
  74. XAUDIO2_SEND_DESCRIPTOR sendDesc;
  75. sendDesc.Flags = 0;
  76. sendDesc.pOutputVoice = SoundsEngine::engine->fxPremasteringVoice;
  77. XAUDIO2_VOICE_SENDS sendList;
  78. sendList.SendCount = 1;
  79. sendList.pSends = &sendDesc;
  80. voice->SetOutputVoices(&sendList);
  81. return true;
  82. }
  83. //Удалить
  84. void SoundsEngine::SceneMaster::Release()
  85. {
  86. if((flags & flags_isActive) == 0)
  87. {
  88. return;
  89. }
  90. //Сбрасываем параметры эффект-процессора сцены
  91. fxScene.Clear();
  92. //Остановим звук тишины
  93. if(silence)
  94. {
  95. silence->Stop();
  96. }
  97. //Остановим отсоединим мастер сцены
  98. if(voice)
  99. {
  100. XAUDIO2_VOICE_SENDS sends;
  101. sends.SendCount = 0;
  102. sends.pSends = null;
  103. voice->SetEffectChain(null);
  104. voice->SetOutputVoices(&sends);
  105. }
  106. //Сбрасываем флажки
  107. flags = 0;
  108. }
  109. //Запустить работу мастера
  110. void SoundsEngine::SceneMaster::Resume()
  111. {
  112. if((flags & flags_isPause) == 0)
  113. {
  114. return;
  115. }
  116. if(flags & flags_isInitFx)
  117. {
  118. Assert(silence);
  119. silence->Start();
  120. fxScene.Reset();
  121. }
  122. flags &= ~flags_isPause;
  123. }
  124. //Остановить работу мастера
  125. void SoundsEngine::SceneMaster::Stop()
  126. {
  127. if(flags & flags_isPause)
  128. {
  129. return;
  130. }
  131. if(flags & flags_isInitFx)
  132. {
  133. Assert(silence);
  134. silence->Stop();
  135. fxScene.Reset();
  136. }
  137. flags |= flags_isPause;
  138. }
  139. //Установить параметры серды окружения
  140. void SoundsEngine::SceneMaster::SetEnvironment(const FxScene::EnvParams & params)
  141. {
  142. if((flags & flags_isInitFx) == 0)
  143. {
  144. //Описание эффекта
  145. XAUDIO2_EFFECT_DESCRIPTOR fxDesc;
  146. fxDesc.pEffect = (IXAPO *)&fxScene;
  147. fxDesc.InitialState = true;
  148. fxDesc.OutputChannels = 2;
  149. XAUDIO2_EFFECT_CHAIN fxChain;
  150. fxChain.EffectCount = 1;
  151. fxChain.pEffectDescriptors = &fxDesc;
  152. voice->SetEffectChain(&fxChain);
  153. silence->Start();
  154. flags |= flags_isInitFx;
  155. }
  156. fxScene.SetParams(params);
  157. }
  158. //-----------------------------------------------------------------------------------------------
  159. //Источник звука
  160. //-----------------------------------------------------------------------------------------------
  161. SoundsEngine::SoundChannel::SoundChannel() : xWmaBuffer(_FL_, 1)
  162. {
  163. voice = null;
  164. fxVoice = null;
  165. states = 0;
  166. lowPrtCounter = 0;
  167. mode = 0;
  168. format = 0;
  169. waveVolume = 0.0f;
  170. time = 0;
  171. fadeOutTime = 0.0f;
  172. samplesCount = 0;
  173. startPlayPosition = 0;
  174. continuePosition = 0;
  175. currentUniqPtr = null;
  176. }
  177. SoundsEngine::SoundChannel::~SoundChannel()
  178. {
  179. Assert(!voice);
  180. Assert(!fxVoice);
  181. Assert(!currentUniqPtr);
  182. }
  183. void SoundsEngine::SoundChannel::Release()
  184. {
  185. if(voice)
  186. {
  187. voice->DestroyVoice();
  188. voice = null;
  189. }
  190. if(fxVoice)
  191. {
  192. fxVoice->DestroyVoice();
  193. fxVoice = null;
  194. }
  195. currentUniqPtr = null;
  196. }
  197. //Запустить источник звука на проигрывание
  198. void SoundsEngine::SoundChannel::Play()
  199. {
  200. if(!(states & state_isPlay))
  201. {
  202. Assert(SoundsEngine::engine);
  203. bool isNeedPause = (SoundsEngine::engine->isPause != 0);
  204. Assert(voice);
  205. XAUDIO2_VOICE_SENDS sendList;
  206. sendList.SendCount = 1;
  207. XAUDIO2_SEND_DESCRIPTOR sendDesc;
  208. sendDesc.Flags = 0;
  209. sendDesc.pOutputVoice = fxVoice;
  210. sendList.pSends = &sendDesc;
  211. voice->SetOutputVoices(&sendList);
  212. if((states & state_isPause) == 0 && !isNeedPause)
  213. {
  214. voice->Start(0);
  215. }
  216. lowPrtCounter = 0;
  217. states &= ~state_fadeoutProcess;
  218. states |= state_isPlay;
  219. if(isNeedPause)
  220. {
  221. Pause(true);
  222. }
  223. }
  224. }
  225. //Приостоновить буффер не освобождая канала
  226. void SoundsEngine::SoundChannel::Pause(bool isPause)
  227. {
  228. if(((states & state_isPause) != 0) == isPause)
  229. {
  230. return;
  231. }
  232. if(isPause)
  233. {
  234. states |= state_isPause;
  235. if((states & state_isPlay) != 0 && voice)
  236. {
  237. voice->Stop();
  238. }
  239. }else{
  240. states &= ~state_isPause;
  241. if((states & state_isPlay) != 0 && voice)
  242. {
  243. voice->Start(0);
  244. }
  245. }
  246. }
  247. //Плавно увеличить громкость с текущего значения до максимума
  248. void SoundsEngine::SoundChannel::FadeIn(float time)
  249. {
  250. if(!(states & state_isPlay))
  251. {
  252. Assert(voice);
  253. //Сколько надо шагов
  254. float steps = time*SoundsEngine::GetFxMixFreq();
  255. if(steps < 16)
  256. {
  257. //Очень мало шагов, сразу проигрываем
  258. Play();
  259. return;
  260. }
  261. //Шаг с которым надо увеличивать громкость с 0 до 1
  262. float fadeDelta = 1.0f/steps;
  263. fxProcessor.FadeIn(fadeDelta);
  264. Play();
  265. }
  266. }
  267. //Плавно уменьшить громкость с текущего значения до нуля
  268. void SoundsEngine::SoundChannel::FadeOut(float time)
  269. {
  270. if((states & state_isPlay) && voice)
  271. {
  272. states |= state_fadeoutProcess;
  273. //Сколько надо шагов
  274. float steps = time*SoundsEngine::GetFxMixFreq();
  275. if(steps < 16)
  276. {
  277. //Очень мало шагов, просто останавливаем
  278. Stop();
  279. return;
  280. }
  281. //Шаг с которым надо уменьшать громкость с 1 до 0
  282. float fadeDelta = -1.0f/steps;
  283. fxProcessor.FadeOut(fadeDelta);
  284. fadeOutTime = time;
  285. }
  286. }
  287. //Установить позицию в 3D (включает позиционирование звука)
  288. void SoundsEngine::SoundChannel::SetLocators(const FxVoice::Locator * locs, dword count)
  289. {
  290. fxProcessor.SetLocators(locs, count);
  291. }
  292. //Установить громкость канала
  293. void SoundsEngine::SoundChannel::SetVolume(float volume)
  294. {
  295. fxProcessor.SetVolume(waveVolume*volume);
  296. }
  297. //Установить режим низчайшего приоритета, при котором можно сразу вытеснять канал
  298. void SoundsEngine::SoundChannel::SetLowPriority(bool isLowPriority)
  299. {
  300. if(!isLowPriority)
  301. {
  302. lowPrtCounter = 0;
  303. }else{
  304. lowPrtCounter++;
  305. if(lowPrtCounter > 0x0fffffff)
  306. {
  307. lowPrtCounter = 0x0fffffff;
  308. }
  309. }
  310. }
  311. //Установить громкость волны
  312. void SoundsEngine::SoundChannel::FixWaveVolume(float volume)
  313. {
  314. waveVolume = volume;
  315. }
  316. //Получить текущую громкость канала
  317. float SoundsEngine::SoundChannel::DebugGetCurrentVolume()
  318. {
  319. return fxProcessor.GetCurrentVolume();
  320. }
  321. //Активен ли канал для данного владельца
  322. bool SoundsEngine::SoundChannel::IsLost(void * uniqPtr)
  323. {
  324. return (currentUniqPtr != uniqPtr);
  325. }
  326. //На паузе ли буфер
  327. bool SoundsEngine::SoundChannel::IsPause()
  328. {
  329. return (states & state_isPause) != 0;
  330. }
  331. //Играет ли звук
  332. bool SoundsEngine::SoundChannel::IsPlay()
  333. {
  334. if(states & state_isPlay)
  335. {
  336. if(voice)
  337. {
  338. XAUDIO2_VOICE_STATE vstate;
  339. voice->GetState(&vstate);
  340. if(vstate.BuffersQueued > (states & state_buffersForStopMask))
  341. {
  342. if(!(states & state_fadeoutProcess))
  343. {
  344. return true;
  345. }else{
  346. float vol = fxProcessor.GetFadeVolume();
  347. if(vol > (0.1f/65536.0f))
  348. {
  349. return true;
  350. }
  351. }
  352. }
  353. }
  354. Stop();
  355. }
  356. return false;
  357. }
  358. //Получить позицию проигрывания в сэмплах
  359. bool SoundsEngine::SoundChannel::GetPlayPosition(dword & playPosition)
  360. {
  361. if(states & state_isPlay)
  362. {
  363. if(voice)
  364. {
  365. XAUDIO2_VOICE_STATE vstate;
  366. voice->GetState(&vstate);
  367. if(vstate.BuffersQueued)
  368. {
  369. //Позиция проигрывания в текущем буфере
  370. UINT64 currentPlayPos = vstate.SamplesPlayed + continuePosition - startPlayPosition;
  371. if((mode & SoundBankFileSetup::mode_loop_mask) != SoundBankFileSetup::mode_loop_diasble)
  372. {
  373. Assert(samplesCount > 0);
  374. currentPlayPos %= (UINT64)samplesCount;
  375. }
  376. if(currentPlayPos > 0xffffffff)
  377. {
  378. currentPlayPos = 0xffffffff;
  379. }
  380. playPosition = (dword)currentPlayPos;
  381. return true;
  382. }
  383. }
  384. Stop();
  385. }
  386. return false;
  387. }
  388. //Остановить канал
  389. void SoundsEngine::SoundChannel::Stop()
  390. {
  391. if(states & state_isPlay)
  392. {
  393. if(voice)
  394. {
  395. XAUDIO2_VOICE_SENDS sends;
  396. sends.SendCount = 0;
  397. sends.pSends = null;
  398. voice->SetOutputVoices(&sends);
  399. fxVoice->SetOutputVoices(&sends);
  400. fxProcessor.Reset();
  401. samplesCount = 0;
  402. startPlayPosition = 0;
  403. voice->DestroyVoice();
  404. voice = null;
  405. }
  406. states &= ~(state_isPlay | state_fadeoutProcess | state_isPause);
  407. lowPrtCounter = 0;
  408. }
  409. }
  410. //Получить логическое время
  411. long SoundsEngine::SoundChannel::GetTime()
  412. {
  413. if(states & state_fadeoutProcess)
  414. {
  415. //Если идёт процесс фейда, то возвращаем эмпирическое значение, зависящее от текущей громкости
  416. float vol = fxProcessor.GetCurrentVolume();
  417. vol = 1.0f - Clampf(vol);
  418. return long(vol*-1000000.0f);
  419. }
  420. return time;
  421. }
  422. //-----------------------------------------------------------------------------------------------
  423. //SoundsEngine
  424. //-----------------------------------------------------------------------------------------------
  425. SoundsEngine::SoundsEngine() : sceneMasters(_FL_, 256)
  426. {
  427. Assert(!engine);
  428. engine = this;
  429. //Системное
  430. pXAudio2 = null;
  431. masteringVoice = null;
  432. fxPremasteringVoice = null;
  433. musicPremasteringVoice = null;
  434. FxVoice::StaticInit(GetFxMixFreq());
  435. isPause = 0;
  436. notificationListenerForXbox = null;
  437. //Буфер тишины
  438. memset(silenceLoop, 0, sizeof(silenceLoop));
  439. memset(&silenceBuffer, 0, sizeof(silenceBuffer));
  440. silenceBuffer.Flags = XAUDIO2_END_OF_STREAM;
  441. silenceBuffer.AudioBytes = sizeof(silenceBuffer);
  442. silenceBuffer.pAudioData = (BYTE *)silenceLoop;
  443. silenceBuffer.LoopCount = XAUDIO2_LOOP_INFINITE;
  444. //Звуки
  445. dword c = 0;
  446. for(dword i = 0; i < c_soundChannels; i++)
  447. {
  448. sound[i] = &soundChannels[c++];
  449. }
  450. soundCount = 0;
  451. for(dword i = 0; i < c_reserveChannels; i++)
  452. {
  453. reserved[i] = &soundChannels[c++];
  454. }
  455. reservedCount = 0;
  456. Assert(c == c_totalSoundChannels);
  457. Assert(ARRSIZE(soundChannels) == c_totalSoundChannels);
  458. creationCounter = 0;
  459. #ifndef _XBOX
  460. HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
  461. #endif
  462. #ifndef NO_TOOLS
  463. previewMaster = null;
  464. previewMasterVolume = 1.0f;
  465. previewVoice = null;
  466. previewVoiceMirror = null;
  467. previewUserId[0] = previewUserId[1] = previewUserId[2] = previewUserId[3] = 0;
  468. #endif
  469. }
  470. SoundsEngine::~SoundsEngine()
  471. {
  472. Release();
  473. #ifndef _XBOX
  474. CoUninitialize();
  475. #endif
  476. Assert(engine == this);
  477. engine = null;
  478. }
  479. //Инициализировать
  480. bool SoundsEngine::Init()
  481. {
  482. HRESULT hr;
  483. dword flags = 0;
  484. XAUDIO2_PROCESSOR processor = XAUDIO2_DEFAULT_PROCESSOR;
  485. #ifdef _DEBUG
  486. //flags = XAUDIO2_DEBUG_ENGINE;
  487. #endif
  488. #ifdef _XBOX
  489. processor = XboxThread4;
  490. notificationListenerForXbox = XNotifyCreateListener(XNOTIFY_XMP);
  491. if(notificationListenerForXbox == null)
  492. {
  493. api->Trace("SoundService error: Can't create XNotifyCreateListener object!");
  494. }
  495. #endif
  496. if(FAILED(hr = XAudio2Create(&pXAudio2, flags, processor)))
  497. {
  498. api->Trace("SoundService error: Can't create XAudio2 object, error code: 0x%x", hr);
  499. return false;
  500. }
  501. //Мастер
  502. if(FAILED(hr = pXAudio2->CreateMasteringVoice(&masteringVoice)))
  503. {
  504. api->Trace("SoundService error: Can't create mastering voice object, error code: 0x%x", hr);
  505. return false;
  506. }
  507. Assert(masteringVoice);
  508. XAUDIO2_VOICE_SENDS sendToMaster;
  509. sendToMaster.SendCount = 1;
  510. XAUDIO2_SEND_DESCRIPTOR sendDesc;
  511. sendDesc.Flags = 0;
  512. sendDesc.pOutputVoice = masteringVoice;
  513. sendToMaster.pSends = &sendDesc;
  514. XAUDIO2_EFFECT_DESCRIPTOR fxDesc;
  515. fxDesc.pEffect = (IXAPO *)&fxPremaster;
  516. fxDesc.InitialState = true;
  517. fxDesc.OutputChannels = 2;
  518. XAUDIO2_EFFECT_CHAIN fxChain;
  519. fxChain.EffectCount = 1;
  520. fxChain.pEffectDescriptors = &fxDesc;
  521. //Премастер канала эффектов
  522. if(FAILED(hr = pXAudio2->CreateSubmixVoice(&fxPremasteringVoice, 2, GetFxMixFreq(), 0, 20, &sendToMaster, &fxChain)))
  523. {
  524. api->Trace("SoundService error: Can't create fx premastering voice object, error code: 0x%x", hr);
  525. return false;
  526. }
  527. Assert(fxPremasteringVoice);
  528. api->ExecuteCoreCommand(CoreCommand_CheckMemory());
  529. // float output4to2[2][4] = {{1.0f, 1.0f, 1.0f, 1.0f},{1.0f, 1.0f, 1.0f, 1.0f}};
  530. // hr = fxPremasteringVoice->SetOutputMatrix(masteringVoice, 4, 2, (float *)output4to2);
  531. //Премастер музыкального канала
  532. if(FAILED(hr = pXAudio2->CreateSubmixVoice(&musicPremasteringVoice, 2, GetMusMixFreq(), 0, 20, &sendToMaster)))
  533. {
  534. api->Trace("SoundService error: Can't create music premastering voice object, error code: 0x%x", hr);
  535. return false;
  536. }
  537. Assert(musicPremasteringVoice);
  538. //Инициализация каналов
  539. for(dword i = 0; i < ARRSIZE(soundChannels); i++)
  540. {
  541. SoundChannel & channel = soundChannels[i];
  542. XAUDIO2_EFFECT_DESCRIPTOR fxDesc;
  543. fxDesc.pEffect = (IXAPO *)&channel.fxProcessor;
  544. fxDesc.InitialState = true;
  545. fxDesc.OutputChannels = 2;
  546. XAUDIO2_EFFECT_CHAIN fxChain;
  547. fxChain.EffectCount = 1;
  548. fxChain.pEffectDescriptors = &fxDesc;
  549. HRESULT hr = pXAudio2->CreateSubmixVoice(&channel.fxVoice, 2, GetFxMixFreq(), 0, 10, null, &fxChain);
  550. if(hr != S_OK)
  551. {
  552. api->Trace("SoundsEngine::Init() -> CreateSubmixVoice: result failed: hr = 0x%x", hr);
  553. return false;
  554. }
  555. Assert(channel.fxVoice);
  556. }
  557. //Запускаем звуковую библиотеку
  558. pXAudio2->StartEngine();
  559. UpdateMusicState();
  560. return true;
  561. }
  562. //Освободить ресурсы и перейди в неинициализированное состояние
  563. void SoundsEngine::Release()
  564. {
  565. for(dword i = 0; i < ARRSIZE(soundChannels); i++)
  566. {
  567. soundChannels[i].Release();
  568. }
  569. for(dword i = 0; i < sceneMasters.Size(); i++)
  570. {
  571. sceneMasters[i]->Release();
  572. }
  573. Sleep(100);
  574. #ifndef NO_TOOLS
  575. if(previewVoice)
  576. {
  577. previewVoice->DestroyVoice();
  578. previewVoice = null;
  579. }
  580. if(previewVoiceMirror)
  581. {
  582. previewVoiceMirror->DestroyVoice();
  583. previewVoiceMirror = null;
  584. }
  585. if(previewMaster)
  586. {
  587. previewMaster->DestroyVoice();
  588. previewMaster = null;
  589. }
  590. #endif
  591. for(dword i = 0; i < sceneMasters.Size(); i++)
  592. {
  593. delete sceneMasters[i];
  594. sceneMasters[i] = null;
  595. }
  596. sceneMasters.Empty();
  597. if(musicPremasteringVoice)
  598. {
  599. musicPremasteringVoice->DestroyVoice();
  600. musicPremasteringVoice = null;
  601. }
  602. if(fxPremasteringVoice)
  603. {
  604. fxPremasteringVoice->DestroyVoice();
  605. fxPremasteringVoice = null;
  606. }
  607. if(masteringVoice)
  608. {
  609. masteringVoice->DestroyVoice();
  610. masteringVoice = null;
  611. }
  612. if(pXAudio2)
  613. {
  614. pXAudio2->StopEngine();
  615. Sleep(100);
  616. pXAudio2->Release();
  617. pXAudio2 = null;
  618. }
  619. dword c = 0;
  620. for(dword i = 0; i < c_soundChannels; i++)
  621. {
  622. sound[i] = &soundChannels[c++];
  623. }
  624. soundCount = 0;
  625. for(dword i = 0; i < c_reserveChannels; i++)
  626. {
  627. reserved[i] = &soundChannels[c++];
  628. }
  629. reservedCount = 0;
  630. creationCounter = 0;
  631. #ifdef _XBOX
  632. if(notificationListenerForXbox != null)
  633. {
  634. XCloseHandle(notificationListenerForXbox);
  635. }
  636. #endif
  637. }
  638. //Обновить состояние
  639. void SoundsEngine::Update()
  640. {
  641. //Глушим доигрываемые каналы
  642. for(dword i = 0; i < reservedCount; i++)
  643. {
  644. if(!reserved[i]->IsPlay())
  645. {
  646. reserved[i]->Stop();
  647. ExchangeChannels(reserved[i], reserved[reservedCount - 1]);
  648. reservedCount--;
  649. }
  650. }
  651. //Глушим зависшие каналы (PCM fix)
  652. for(dword i = 0; i < soundCount; i++)
  653. {
  654. dword pos = 0;
  655. if(sound[i]->GetPlayPosition(pos))
  656. {
  657. if(pos > sound[i]->samplesCount*2)
  658. {
  659. //Принудительно останавливаем (1 канал за кадр)
  660. ReleaseSoundChannel(sound[i], sound[i]->currentUniqPtr);
  661. break;
  662. }
  663. }
  664. }
  665. #ifdef _XBOX
  666. if(notificationListenerForXbox)
  667. {
  668. //Смотрим состояние проигрывателя
  669. DWORD msgFilter;
  670. ULONG_PTR param;
  671. if(XNotifyGetNext(notificationListenerForXbox, 0, &msgFilter, &param))
  672. {
  673. if(msgFilter == XN_XMP_STATECHANGED)
  674. {
  675. UpdateMusicState();
  676. }
  677. }
  678. }
  679. #endif
  680. }
  681. //Приостановить проигрывание звуков
  682. void SoundsEngine::SetPause(bool isSetPause)
  683. {
  684. // api->Trace("SoundsEngine> Set pause: %s, current flag is %i", isSetPause ? "true" : "false", isSetPause);
  685. if((isPause != 0) == isSetPause)
  686. {
  687. return;
  688. }
  689. isSetPause ? 1 : 0;
  690. //Глушим доигрываемые каналы
  691. if(isSetPause)
  692. {
  693. // api->Trace("SoundsEngine> Set to pause");
  694. //Отмечаем, что на паузе
  695. isPause = 1;
  696. //Останавливаем хвосты
  697. for(dword i = 0; i < reservedCount; i++)
  698. {
  699. reserved[i]->Stop();
  700. }
  701. reservedCount = 0;
  702. //Останавливаем звуки
  703. for(dword i = 0; i < soundCount; i++)
  704. {
  705. sound[i]->Pause(true);
  706. }
  707. //Останавливаем мастера сцен
  708. for(dword i = 0; i < sceneMasters.Size(); i++)
  709. {
  710. sceneMasters[i]->Stop();
  711. }
  712. }else{
  713. // api->Trace("SoundsEngine> Resume from pause");
  714. //Отмечаем, что работаем
  715. isPause = 0;
  716. //Запускаем мастера сцен
  717. for(dword i = 0; i < sceneMasters.Size(); i++)
  718. {
  719. sceneMasters[i]->Resume();
  720. }
  721. //Востанавливаем звуки
  722. for(dword i = 0; i < soundCount; i++)
  723. {
  724. sound[i]->Pause(false);
  725. }
  726. }
  727. }
  728. //Создать мастер сцены
  729. SoundsEngine::SceneMaster * SoundsEngine::CreateSceneMaster()
  730. {
  731. //Пробуем выделить среди созданных
  732. for(dword i = 0; i < sceneMasters.Size(); i++)
  733. {
  734. if(sceneMasters[i]->Alloc())
  735. {
  736. return sceneMasters[i];
  737. }
  738. }
  739. //Добавляем объект эффекта окружения
  740. SceneMaster * sm = NEW SceneMaster();
  741. HRESULT hr = sm->Init();
  742. if(hr == S_OK)
  743. {
  744. Verify(sm->Alloc());
  745. sceneMasters.Add(sm);
  746. return sm;
  747. }
  748. delete sm;
  749. return null;
  750. }
  751. //Попытаться получить доступный звуковой канал
  752. SoundsEngine::SoundChannel * SoundsEngine::GetSoundChannel(SoundBankFileSound & sbfs, SoundBankFileWaveInfo * selWave, dword startPosition, SceneMaster & scene, void * uniqPtr)
  753. {
  754. //Получаем волну, которую будем проигрывать
  755. Assert(selWave);
  756. SoundBankFileWave * wave = selWave->wave;
  757. if(!wave)
  758. {
  759. //Проигрывание тишины
  760. return null;
  761. }
  762. //Контроль логического времени создания
  763. if(creationCounter > 0xfffffff)
  764. {
  765. for(dword i = 0; i < c_totalSoundChannels; i++)
  766. {
  767. soundChannels[i].time -= 0xff00000;
  768. if(soundChannels[i].time < 0)
  769. {
  770. soundChannels[i].time = 0;
  771. }
  772. }
  773. }
  774. //Если всё занято, пробуем освободить канал
  775. if(soundCount >= c_soundChannels)
  776. {
  777. //Надо освободить какой нибудь, поскольку свободных уже нет
  778. dword soundPriority = sbfs.setup.mode & SoundBankFileSetup::mode_priority_mask;
  779. long bestIndex = ChannelSelector(sound, soundCount, soundPriority, creationCounter);
  780. if(bestIndex < 0)
  781. {
  782. return null; //С текущим или более низким приоритетом каналов нет, поэтому ничего не можем сделать
  783. }
  784. //Освобождаем 1 канал в конце массива
  785. sound[bestIndex]->currentUniqPtr = null;
  786. soundCount = c_soundChannels - 1;
  787. ExchangeChannels(sound[bestIndex], sound[c_soundChannels - 1]);
  788. //Теперь решаем, отправить выбраный на фейд или убить сразу
  789. if(reservedCount < c_reserveChannels)
  790. {
  791. bestIndex = reservedCount++;
  792. }else{
  793. //Поступаем аналогично с доигрываемыми звуками
  794. bestIndex = ChannelSelector(reserved, reservedCount, soundPriority, sound[c_soundChannels - 1]->GetTime());
  795. }
  796. if(bestIndex >= 0)
  797. {
  798. //Есть резервные каналы, оставляем звук фейдиться
  799. sound[c_soundChannels - 1]->FadeOut(c_replaceFadeTimeInMs*0.001f);
  800. ExchangeChannels(sound[c_soundChannels - 1], reserved[bestIndex]);
  801. }
  802. }
  803. //Формат волны
  804. dword waveFormat = wave->format;
  805. if((sbfs.setup.mode & SoundBankFileSetup::mode_fx_mask) == SoundBankFileSetup::mode_fx_music)
  806. {
  807. waveFormat |= SoundBankFileWave::f_tmp_music;
  808. }
  809. //Смотрим канал с подходящим форматом
  810. Assert(soundCount < c_soundChannels);
  811. #ifndef STOP_DEBUG
  812. /*
  813. //!!! Проверка, что свободные каналы не играют
  814. for(dword i = soundCount; i < c_soundChannels; i++)
  815. {
  816. if(sound[i]->voice)
  817. {
  818. XAUDIO2_VOICE_STATE vstate;
  819. sound[i]->voice->GetState(&vstate);
  820. Assert(vstate.BuffersQueued == 0);
  821. }
  822. }
  823. //*/
  824. #endif
  825. /*
  826. for(dword i = soundCount; i < c_soundChannels; i++)
  827. {
  828. if(sound[i]->format == waveFormat)
  829. {
  830. //Есть нужный формат, поместим его в конец активных
  831. ExchangeChannels(sound[soundCount], sound[i]);
  832. break;
  833. }
  834. }
  835. */
  836. SoundChannel * channel = sound[soundCount];
  837. //Гарантированно останавливаем канал
  838. channel->Stop();
  839. channel->states = 0;
  840. //Подготавливаем канал к использованию
  841. XAUDIO2_VOICE_SENDS sendList;
  842. sendList.SendCount = 1;
  843. XAUDIO2_SEND_DESCRIPTOR sendDesc;
  844. sendDesc.Flags = 0;
  845. sendDesc.pOutputVoice = null;
  846. sendList.pSends = &sendDesc;
  847. //if(channel->format != waveFormat/* || ((channel->mode & SoundBankFileSetup::mode_loop_mask) != SoundBankFileSetup::mode_loop_diasble)*/)
  848. {
  849. //Необходимо пересоздать голос под нужный формат
  850. HRESULT hr;
  851. IXAudio2SourceVoice * sourceVoice = null;
  852. sendDesc.pOutputVoice = channel->fxVoice;
  853. dword workFreq = GetFxMixFreq();
  854. dword flags = XAUDIO2_VOICE_NOPITCH;
  855. if(workFreq == (waveFormat & SoundBankFileWave::f_freq_mask))
  856. {
  857. flags |= XAUDIO2_VOICE_NOSRC;
  858. }
  859. /*if(sbfs.setup.GetFxMode() == SoundBankFileSetup::mode_fx_music)
  860. {
  861. flags |= XAUDIO2_VOICE_MUSIC;
  862. }*/
  863. hr = pXAudio2->CreateSourceVoice(&sourceVoice, (const WAVEFORMATEX *)wave->waveFormatInfo, 0, XAUDIO2_DEFAULT_FREQ_RATIO, null, &sendList, null);
  864. if(hr != S_OK)
  865. {
  866. //Фига се, чегото не создалось... пока проскипаем
  867. api->Trace("SoundsEngine::GetSoundChannel -> CreateSourceVoice return error code 0x%x", hr);
  868. Assert(sourceVoice);
  869. return null;
  870. }
  871. Assert(sourceVoice);
  872. if(channel->voice)
  873. {
  874. channel->voice->DestroyVoice();
  875. }
  876. channel->voice = sourceVoice;
  877. channel->format = waveFormat;
  878. }/*else{
  879. channel->voice->Stop();
  880. }*/
  881. soundCount++;
  882. //Определяем куда подключать звук
  883. switch(sbfs.setup.GetFxMode())
  884. {
  885. case SoundBankFileSetup::mode_fx_full:
  886. Assert(scene.voice);
  887. sendDesc.pOutputVoice = scene.voice;
  888. channel->fxProcessor.EnableEnvironment(true);
  889. break;
  890. case SoundBankFileSetup::mode_fx_premaster:
  891. sendDesc.pOutputVoice = fxPremasteringVoice;
  892. channel->fxProcessor.EnableEnvironment(false);
  893. break;
  894. case SoundBankFileSetup::mode_fx_master:
  895. sendDesc.pOutputVoice = masteringVoice;
  896. channel->fxProcessor.EnableEnvironment(false);
  897. break;
  898. case SoundBankFileSetup::mode_fx_music:
  899. sendDesc.pOutputVoice = musicPremasteringVoice;
  900. channel->fxProcessor.EnableEnvironment(false);
  901. break;
  902. default:
  903. Assert(false);
  904. }
  905. channel->fxVoice->SetOutputVoices(&sendList);
  906. //Сохраняем атрибуты текущего звука
  907. channel->mode = sbfs.setup.mode;
  908. channel->currentUniqPtr = uniqPtr;
  909. channel->waveVolume = selWave->volume;
  910. channel->pickAmp = wave->maxNormalizedAmp;
  911. channel->tailTime = wave->unimportantTime;
  912. channel->fadeOutTime = 0.0f;
  913. channel->time = creationCounter++;
  914. channel->samplesCount = wave->samplesCount;
  915. //Фикс для незацикленных PCM, которые выходят за пределы буфера. Начало
  916. UINT32 flagsForMainBuffer = XAUDIO2_END_OF_STREAM;
  917. bool isPCM_fix_on = false;
  918. if((wave->format & SoundBankFileWave::f_format_mask) == SoundBankFileWave::f_format_pcm)
  919. {
  920. isPCM_fix_on = true;
  921. flagsForMainBuffer = 0;
  922. }
  923. //Заполняем буффер
  924. bool isLoop = sbfs.setup.GetModeLoop() != SoundBankFileSetup::mode_loop_diasble;
  925. XAUDIO2_BUFFER xbuffer;
  926. xbuffer.Flags = flagsForMainBuffer;
  927. xbuffer.AudioBytes = wave->dataSize;
  928. xbuffer.pAudioData = (BYTE *)wave->data;
  929. xbuffer.PlayBegin = startPosition & ~0x7f; //Для XMA надо выравнивать первый сэмпл по 128
  930. xbuffer.PlayLength = 0;
  931. //*
  932. xbuffer.PlayLength = wave->samplesCount - xbuffer.PlayBegin;
  933. if((waveFormat & SoundBankFileWave::f_format_mask) == SoundBankFileWave::f_format_xma)
  934. {
  935. Assert((xbuffer.PlayLength & 0x7f) == 0);
  936. }
  937. //*/
  938. xbuffer.LoopBegin = isLoop ? 0 : XAUDIO2_NO_LOOP_REGION;
  939. xbuffer.LoopLength = 0;
  940. xbuffer.LoopCount = isLoop ? XAUDIO2_LOOP_INFINITE : 0;
  941. xbuffer.pContext = null;
  942. //Устанавливаем буфер
  943. HRESULT hr = XAUDIO2_E_INVALID_CALL;
  944. if((waveFormat & SoundBankFileWave::f_format_mask) != SoundBankFileWave::f_format_xvma)
  945. {
  946. hr = channel->voice->SubmitSourceBuffer(&xbuffer, null);
  947. }else{
  948. //Дополнительные плюшки для xWMA
  949. const SoundBankFileWave::XWMAWAVEFORMAT * xwmaFormat = (const SoundBankFileWave::XWMAWAVEFORMAT *)wave->waveFormatInfo;
  950. if(channel->xWmaBuffer.Size() < xwmaFormat->tableCount)
  951. {
  952. channel->xWmaBuffer.AddElements(xwmaFormat->tableCount - channel->xWmaBuffer.Size());
  953. }
  954. memcpy(channel->xWmaBuffer.GetBuffer(), xwmaFormat->table, xwmaFormat->tableCount*sizeof(dword));
  955. XAUDIO2_BUFFER_WMA wma;
  956. wma.PacketCount = xwmaFormat->tableCount;
  957. wma.pDecodedPacketCumulativeBytes = channel->xWmaBuffer.GetBuffer();
  958. hr = channel->voice->SubmitSourceBuffer(&xbuffer, &wma);
  959. }
  960. if(hr != S_OK)
  961. {
  962. //Не получилось подписать данный буфер на проигрывание, похоже баг в формате
  963. ReleaseSoundChannel(channel, uniqPtr);
  964. api->Trace("SoundsEngine::GetSoundChannel -> SubmitSourceBuffer return error code 0x%x (for sound %s, wave: %i)", hr, sbfs.name, sbfs.waves - selWave);
  965. return null;
  966. }
  967. //Сохраняем стартовую позицию
  968. Assert(channel->samplesCount > 0);
  969. Assert(channel->voice);
  970. XAUDIO2_VOICE_STATE vstate;
  971. channel->voice->GetState(&vstate);
  972. Assert(vstate.BuffersQueued > 0);
  973. Assert(vstate.SamplesPlayed == 0);
  974. channel->startPlayPosition = vstate.SamplesPlayed;
  975. channel->continuePosition = xbuffer.PlayBegin;
  976. //Фикс для незацикленных PCM, которые выходят за пределы буфера. Окончание
  977. if(isPCM_fix_on)
  978. {
  979. hr = channel->voice->SubmitSourceBuffer(&silenceBuffer, null);
  980. if(hr != S_OK)
  981. {
  982. //Не получилось подписать данный буфер на проигрывание, похоже баг в формате
  983. ReleaseSoundChannel(channel, uniqPtr);
  984. 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);
  985. return null;
  986. }
  987. channel->states |= 1;
  988. }
  989. return channel;
  990. }
  991. //Освободить звуковой канал
  992. void SoundsEngine::ReleaseSoundChannel(SoundChannel * ch, void * uniqPtr)
  993. {
  994. if(ch->currentUniqPtr != uniqPtr) return;
  995. //Переводим канал к свободным
  996. for(dword i = 0; i < soundCount; i++)
  997. {
  998. if(sound[i] == ch)
  999. {
  1000. ch->Stop();
  1001. if(ch->voice)
  1002. {
  1003. ch->voice->DestroyVoice();
  1004. ch->voice = null;
  1005. }
  1006. ch->currentUniqPtr = null;
  1007. soundCount--;
  1008. ExchangeChannels(sound[i], sound[soundCount]);
  1009. return;
  1010. }
  1011. }
  1012. //Сюда попадать не должно
  1013. Assert(false);
  1014. }
  1015. //Получить количество активных каналов
  1016. dword SoundsEngine::GetPlayChannels()
  1017. {
  1018. return soundCount;
  1019. }
  1020. //Получить максимальное количество каналов
  1021. dword SoundsEngine::GetMaxChannels()
  1022. {
  1023. return c_soundChannels;
  1024. }
  1025. //Получить количество активных каналов для доигрывания
  1026. dword SoundsEngine::GetPlayReservedChannels()
  1027. {
  1028. return reservedCount;
  1029. }
  1030. //Получить максимальное количество каналов для доигрывания
  1031. dword SoundsEngine::GetMaxReservedChannels()
  1032. {
  1033. return c_reserveChannels;
  1034. }
  1035. #ifdef _XBOX
  1036. //Получить объект XAudio
  1037. IXAudio2 * SoundsEngine::GetXAudio()
  1038. {
  1039. return pXAudio2;
  1040. }
  1041. #endif
  1042. #ifndef NO_TOOLS
  1043. //Запустить волну на проигрывание 16бит (для звукового редактора)
  1044. bool SoundsEngine::EditPrewiewPlay(const dword userId[4], EditPrewiewWaveParams * mainWave, EditPrewiewWaveParams * mirrorWave, bool isMirror)
  1045. {
  1046. //-------------------------------------------------------------------
  1047. static IXAudio2SubmixVoice * testFxVoice = null;
  1048. //Отладка эффектов
  1049. #ifdef _DEBUG
  1050. if(false)
  1051. //if(!testFxVoice)
  1052. #else
  1053. if(false)
  1054. #endif
  1055. {
  1056. XAUDIO2_VOICE_SENDS sendList;
  1057. sendList.SendCount = 1;
  1058. XAUDIO2_SEND_DESCRIPTOR sendDesc;
  1059. sendDesc.Flags = 0;
  1060. sendDesc.pOutputVoice = masteringVoice;
  1061. sendList.pSends = &sendDesc;
  1062. static FxPremaster fxPremaster;
  1063. static FxScene fxScene;
  1064. XAUDIO2_EFFECT_DESCRIPTOR fxDesc[3];
  1065. fxDesc[0].pEffect = (IXAPO *)&fxScene;
  1066. fxDesc[0].InitialState = true;
  1067. fxDesc[0].OutputChannels = 2;
  1068. XAUDIO2_EFFECT_CHAIN fxChain;
  1069. fxChain.EffectCount = 1;
  1070. fxChain.pEffectDescriptors = &fxDesc[0];
  1071. HRESULT hr = pXAudio2->CreateSubmixVoice(&testFxVoice, 2, 44100, 0, 15, &sendList, &fxChain);
  1072. sendList.SendCount = 1;
  1073. sendDesc.Flags = 0;
  1074. sendDesc.pOutputVoice = testFxVoice;
  1075. WAVEFORMATEX format;
  1076. format.wFormatTag = WAVE_FORMAT_PCM;
  1077. format.nChannels = 2;
  1078. format.nSamplesPerSec = 44100/8;
  1079. format.wBitsPerSample = 16;
  1080. format.nBlockAlign = (format.nChannels*format.wBitsPerSample)/8;
  1081. format.nAvgBytesPerSec = (format.nChannels*format.wBitsPerSample*format.nSamplesPerSec)/8;
  1082. format.cbSize = 0;
  1083. Assert(pXAudio2);
  1084. hr = pXAudio2->CreateSourceVoice(&previewVoice, &format, 0, XAUDIO2_DEFAULT_FREQ_RATIO, null, &sendList, null);
  1085. Assert(hr == S_OK)
  1086. XAUDIO2_BUFFER xbuffer;
  1087. xbuffer.Flags = XAUDIO2_END_OF_STREAM;
  1088. static short buffer[4096];
  1089. memset(buffer, 0, ARRSIZE(buffer));
  1090. xbuffer.AudioBytes = 4096;
  1091. xbuffer.pAudioData = (BYTE *)buffer;
  1092. xbuffer.PlayBegin = 0;
  1093. xbuffer.PlayLength = 0;
  1094. xbuffer.LoopBegin = 0;
  1095. xbuffer.LoopLength = 0;
  1096. xbuffer.LoopCount = XAUDIO2_LOOP_INFINITE;
  1097. xbuffer.pContext = null;
  1098. hr = previewVoice->SubmitSourceBuffer(&xbuffer, null);
  1099. previewVoice->Start();
  1100. previewVoice = null;
  1101. }
  1102. //-------------------------------------------------------------------
  1103. if(!previewMaster)
  1104. {
  1105. XAUDIO2_VOICE_SENDS sendToMaster;
  1106. sendToMaster.SendCount = 1;
  1107. XAUDIO2_SEND_DESCRIPTOR sendDesc;
  1108. sendDesc.Flags = 0;
  1109. sendDesc.pOutputVoice = masteringVoice;
  1110. sendToMaster.pSends = &sendDesc;
  1111. if(pXAudio2->CreateSubmixVoice(&previewMaster, 2, GetMusMixFreq(), 0, 25, &sendToMaster) != S_OK)
  1112. {
  1113. previewMaster = null;
  1114. }
  1115. EditPrewiewSetMasterVolume(previewMasterVolume);
  1116. }
  1117. //Если играло, то надо остановить проигрывание
  1118. static dword stop_userId[4] = {0, 0, 0, 0};
  1119. EditPrewiewStop(stop_userId);
  1120. Assert(!previewVoice);
  1121. Assert(!previewVoiceMirror);
  1122. Assert((previewUserId[0] | previewUserId[1] | previewUserId[2] | previewUserId[3]) == 0);
  1123. //Идентификатор
  1124. Assert((userId[0] | userId[1] | userId[2] | userId[3]) != 0);
  1125. Assert(mainWave != null);
  1126. previewUserId[0] = userId[0];
  1127. previewUserId[1] = userId[1];
  1128. previewUserId[2] = userId[2];
  1129. previewUserId[3] = userId[3];
  1130. //Куда выводить звук
  1131. Assert(masteringVoice);
  1132. XAUDIO2_VOICE_SENDS sendList;
  1133. sendList.SendCount = 1;
  1134. XAUDIO2_SEND_DESCRIPTOR sendDesc;
  1135. sendDesc.Flags = 0;
  1136. if(testFxVoice)
  1137. {
  1138. sendDesc.pOutputVoice = testFxVoice;
  1139. }else{
  1140. if(!previewMaster)
  1141. {
  1142. sendDesc.pOutputVoice = masteringVoice;
  1143. }else{
  1144. sendDesc.pOutputVoice = previewMaster;
  1145. }
  1146. }
  1147. sendList.pSends = &sendDesc;
  1148. //Формат волны
  1149. WAVEFORMATEX format;
  1150. format.wFormatTag = WAVE_FORMAT_PCM;
  1151. format.nChannels = mainWave->isStereo ? 2 : 1;
  1152. format.nSamplesPerSec = mainWave->sampleRate;
  1153. format.wBitsPerSample = 16;
  1154. format.nBlockAlign = (format.nChannels*format.wBitsPerSample)/8;
  1155. format.nAvgBytesPerSec = (format.nChannels*format.wBitsPerSample*format.nSamplesPerSec)/8;
  1156. format.cbSize = 0;
  1157. //Создаём войс для воспроизведения
  1158. Assert(pXAudio2);
  1159. HRESULT hr = pXAudio2->CreateSourceVoice(&previewVoice, &format, 0, XAUDIO2_DEFAULT_FREQ_RATIO, null, &sendList, null);
  1160. if(hr != S_OK)
  1161. {
  1162. Assert(!previewVoice);
  1163. return false;
  1164. }
  1165. Assert(previewVoice);
  1166. XAUDIO2_BUFFER xbuffer;
  1167. xbuffer.Flags = XAUDIO2_END_OF_STREAM;
  1168. xbuffer.AudioBytes = mainWave->dataSize;
  1169. xbuffer.pAudioData = (BYTE *)mainWave->data;
  1170. xbuffer.PlayBegin = 0;
  1171. xbuffer.PlayLength = 0;
  1172. xbuffer.LoopBegin = 0;
  1173. xbuffer.LoopLength = 0;
  1174. xbuffer.LoopCount = 0;
  1175. xbuffer.pContext = null;
  1176. hr = previewVoice->SubmitSourceBuffer(&xbuffer, null);
  1177. if(hr != S_OK)
  1178. {
  1179. EditPrewiewStop(stop_userId);
  1180. return false;
  1181. }
  1182. if(mirrorWave)
  1183. {
  1184. format.nChannels = mirrorWave->isStereo ? 2 : 1;
  1185. format.nSamplesPerSec = mirrorWave->sampleRate;
  1186. format.nBlockAlign = (format.nChannels*format.wBitsPerSample)/8;
  1187. format.nAvgBytesPerSec = (format.nChannels*format.wBitsPerSample*format.nSamplesPerSec)/8;
  1188. HRESULT hr = pXAudio2->CreateSourceVoice(&previewVoiceMirror, &format, 0, XAUDIO2_DEFAULT_FREQ_RATIO, null, &sendList, null);
  1189. if(hr != S_OK)
  1190. {
  1191. Assert(!previewVoiceMirror);
  1192. EditPrewiewStop(stop_userId);
  1193. return false;
  1194. }
  1195. xbuffer.AudioBytes = mirrorWave->dataSize;
  1196. xbuffer.pAudioData = (BYTE *)mirrorWave->data;
  1197. hr = previewVoiceMirror->SubmitSourceBuffer(&xbuffer, null);
  1198. if(hr != S_OK)
  1199. {
  1200. EditPrewiewStop(stop_userId);
  1201. return false;
  1202. }
  1203. if(isMirror)
  1204. {
  1205. previewVoice->SetVolume(0.0f);
  1206. previewVoiceMirror->SetVolume(1.0f);
  1207. }else{
  1208. previewVoice->SetVolume(1.0f);
  1209. previewVoiceMirror->SetVolume(0.0f);
  1210. }
  1211. previewVoice->Start();
  1212. previewVoiceMirror->Start();
  1213. }else{
  1214. previewVoice->SetVolume(1.0f);
  1215. previewVoice->Start();
  1216. }
  1217. return true;
  1218. }
  1219. //Переключить волну на зеркальную или оригинальную
  1220. bool SoundsEngine::EditPrewiewSwitch(const dword userId[4], bool isMirror)
  1221. {
  1222. if(previewUserId != userId)
  1223. {
  1224. return false;
  1225. }
  1226. if(!EditPrewiewIsPlay(userId, null))
  1227. {
  1228. return false;
  1229. }
  1230. if(!previewVoice || !previewVoiceMirror)
  1231. {
  1232. return false;
  1233. }
  1234. if(!isMirror)
  1235. {
  1236. previewVoice->SetVolume(1.0f);
  1237. previewVoiceMirror->SetVolume(0.0f);
  1238. }else{
  1239. previewVoice->SetVolume(0.0f);
  1240. previewVoiceMirror->SetVolume(1.0f);
  1241. }
  1242. return true;
  1243. }
  1244. //Играет ли волна на прослушивании (для звукового редактора)
  1245. bool SoundsEngine::EditPrewiewIsPlay(const dword userId[4], dword * samplesCount, bool * playWithMirror)
  1246. {
  1247. static dword stop_userId[4] = {0, 0, 0, 0};
  1248. if(previewVoice)
  1249. {
  1250. if((userId[0] | userId[1] | userId[2] | userId[3]) != 0)
  1251. {
  1252. if(((previewUserId[0] ^ userId[0]) | (previewUserId[1] ^ userId[1]) | (previewUserId[2] ^ userId[2]) | (previewUserId[3] ^ userId[3])) != 0)
  1253. {
  1254. return false;
  1255. }
  1256. }
  1257. XAUDIO2_VOICE_STATE state;
  1258. previewVoice->GetState(&state);
  1259. if(state.BuffersQueued > 0)
  1260. {
  1261. if(samplesCount)
  1262. {
  1263. *samplesCount = (dword)state.SamplesPlayed;
  1264. }
  1265. if(playWithMirror)
  1266. {
  1267. *playWithMirror = (previewVoiceMirror != null);
  1268. }
  1269. return true;
  1270. }
  1271. EditPrewiewStop(stop_userId);
  1272. }else{
  1273. if(previewVoiceMirror)
  1274. {
  1275. EditPrewiewStop(stop_userId);
  1276. }
  1277. }
  1278. return false;
  1279. }
  1280. //Остановить прослушивание волны
  1281. void SoundsEngine::EditPrewiewStop(const dword userId[4])
  1282. {
  1283. if(previewVoice || previewVoiceMirror)
  1284. {
  1285. if((userId[0] | userId[1] | userId[2] | userId[3]) != 0)
  1286. {
  1287. if(((previewUserId[0] ^ userId[0]) | (previewUserId[1] ^ userId[1]) | (previewUserId[2] ^ userId[2]) | (previewUserId[3] ^ userId[3])) != 0)
  1288. {
  1289. return;
  1290. }
  1291. }
  1292. if(previewVoice)
  1293. {
  1294. previewVoice->DestroyVoice();
  1295. previewVoice = null;
  1296. }
  1297. if(previewVoiceMirror)
  1298. {
  1299. previewVoiceMirror->DestroyVoice();
  1300. previewVoiceMirror = null;
  1301. }
  1302. }
  1303. previewUserId[0] = previewUserId[1] = previewUserId[2] = previewUserId[3] = 0;
  1304. }
  1305. //Установить громкость прослушиваемой волны
  1306. void SoundsEngine::EditPrewiewSetVolume(float volume, const dword userId[4])
  1307. {
  1308. if(previewVoice)
  1309. {
  1310. if((userId[0] | userId[1] | userId[2] | userId[3]) != 0)
  1311. {
  1312. if(((previewUserId[0] ^ userId[0]) | (previewUserId[1] ^ userId[1]) | (previewUserId[2] ^ userId[2]) | (previewUserId[3] ^ userId[3])) != 0)
  1313. {
  1314. return;
  1315. }
  1316. }
  1317. float setVol = Clampf(volume, 0.0f, 1.0f);
  1318. previewVoice->SetVolume(volume);
  1319. if(previewVoiceMirror)
  1320. {
  1321. previewVoiceMirror->DestroyVoice();
  1322. previewVoiceMirror = null;
  1323. }
  1324. }
  1325. }
  1326. //Установить громкость мастера предпрослушивания
  1327. void SoundsEngine::EditPrewiewSetMasterVolume(float volume)
  1328. {
  1329. previewMasterVolume = volume;
  1330. if(previewMaster)
  1331. {
  1332. previewMaster->SetVolume(volume);
  1333. }
  1334. }
  1335. #endif
  1336. //Обновить состояние музыкального канала в зависимости от состояния проигрывателя
  1337. void SoundsEngine::UpdateMusicState()
  1338. {
  1339. #ifdef _XBOX
  1340. XMP_STATE state;
  1341. XMPGetStatus(&state);
  1342. if(state == XMP_STATE_IDLE)
  1343. {
  1344. musicPremasteringVoice->SetVolume(1.0f);
  1345. }else{
  1346. musicPremasteringVoice->SetVolume(0.0f);
  1347. }
  1348. #endif
  1349. }
  1350. //Выбрать канал для замещения
  1351. long SoundsEngine::ChannelSelector(SoundChannel ** ch, long count, long priority, long time)
  1352. {
  1353. long bestIndex = -1;
  1354. dword bestPriority = priority;
  1355. long bestTime = time;
  1356. dword bestLowPrt = 0;
  1357. bool bestIsLoop = false;
  1358. bool bestIsTail = false;
  1359. float bestTailTime = 1000000.0f;
  1360. float bestPickVolume = 1.0f;
  1361. for(long i = 0; i < count; i++)
  1362. {
  1363. SoundChannel * channel = ch[i];
  1364. bool isLoop = (channel->mode & SoundBankFileSetup::mode_loop_mask) != SoundBankFileSetup::mode_loop_diasble;
  1365. //Проверяем режим низкоприоритетной работы (3D звук за пределами радиуса)
  1366. if(channel->lowPrtCounter > 0)
  1367. {
  1368. //Если переход с зацикленного звука на незацикленный, то не смотрим остальное
  1369. if(channel->lowPrtCounter > bestLowPrt || (bestIsLoop && !isLoop))
  1370. {
  1371. bestIndex = i;
  1372. bestLowPrt = channel->lowPrtCounter;
  1373. bestIsLoop = isLoop;
  1374. continue;
  1375. }
  1376. //Возможно будут ещё условия
  1377. continue;
  1378. }else
  1379. if(bestLowPrt > 0)
  1380. {
  1381. continue;
  1382. }
  1383. //Пропускаем волны с большим приоритетом
  1384. dword channelPriority = channel->mode & SoundBankFileSetup::mode_priority_mask;
  1385. if(channelPriority > bestPriority)
  1386. {
  1387. continue;
  1388. }
  1389. //Расширеные параметры канала
  1390. float pickVolume = channel->waveVolume*channel->pickAmp;
  1391. float tailTime = 1000000.0f;
  1392. bool isTail = false;
  1393. if((channel->states & SoundChannel::state_fadeoutProcess) == 0)
  1394. {
  1395. if(!isLoop)
  1396. {
  1397. dword pos = 0;
  1398. if(!channel->GetPlayPosition(pos)) pos = 0;
  1399. dword tailSamples = channel->samplesCount - pos;
  1400. float freq = (float)(channel->format & SoundBankFileWave::f_freq_mask);
  1401. if(freq < 1.0f) freq = 1.0f;
  1402. tailTime = (float)tailSamples/freq;
  1403. isTail = (tailTime < channel->tailTime);
  1404. }
  1405. }else{
  1406. //Если идёт процесс фейда, то возвращаем эмпирическое значение, зависящее от текущей громкости
  1407. isLoop = false;
  1408. float vol = Clampf(channel->fxProcessor.GetCurrentVolume());
  1409. pickVolume *= vol;
  1410. tailTime = vol*channel->fadeOutTime;
  1411. }
  1412. if(pickVolume < 0.00001f) pickVolume = 0.00001f;
  1413. //Сначала проверияем приоритет
  1414. if(bestIndex >= 0 && channelPriority == priority)
  1415. {
  1416. //Среди звуков с одинаковым приоритетом просматриваем остальные критерии
  1417. if(bestIsTail == isTail)
  1418. {
  1419. if(bestTailTime*bestPickVolume < tailTime*pickVolume)
  1420. {
  1421. continue;
  1422. }
  1423. }else
  1424. if(!isTail)
  1425. {
  1426. continue;
  1427. }
  1428. }
  1429. //Звук с меньшим преоритетом всегда вытесняеться нисмотря на другие критерии
  1430. bestIndex = i;
  1431. bestPriority = channelPriority;
  1432. bestTime = channel->GetTime();
  1433. bestIsLoop = isLoop;
  1434. bestIsTail = isTail;
  1435. bestTailTime = tailTime;
  1436. bestPickVolume = pickVolume;
  1437. }
  1438. return bestIndex;
  1439. }
  1440. //Поменять местами каналы
  1441. __forceinline void SoundsEngine::ExchangeChannels(SoundChannel * & ch1, SoundChannel * & ch2)
  1442. {
  1443. SoundChannel * tmp = ch1;
  1444. ch1 = ch2;
  1445. ch2 = tmp;
  1446. }
  1447. //Получить частоту для канала эфектов
  1448. dword SoundsEngine::GetFxMixFreq()
  1449. {
  1450. #ifdef _XBOX
  1451. //static const dword fxSubMixFreq = dword(48000/XAUDIO2_QUANTUM_DENOMINATOR)*XAUDIO2_QUANTUM_DENOMINATOR;
  1452. static const dword fxSubMixFreq = dword(44100/XAUDIO2_QUANTUM_DENOMINATOR)*XAUDIO2_QUANTUM_DENOMINATOR;
  1453. #else
  1454. static const dword fxSubMixFreq = dword(44100/XAUDIO2_QUANTUM_DENOMINATOR)*XAUDIO2_QUANTUM_DENOMINATOR;
  1455. #endif
  1456. return fxSubMixFreq;
  1457. }
  1458. //Получить частоту для канала музыки
  1459. dword SoundsEngine::GetMusMixFreq()
  1460. {
  1461. #ifdef _XBOX
  1462. //static const dword musSubMixFreq = dword(48000/XAUDIO2_QUANTUM_DENOMINATOR)*XAUDIO2_QUANTUM_DENOMINATOR;
  1463. static const dword musSubMixFreq = dword(44100/XAUDIO2_QUANTUM_DENOMINATOR)*XAUDIO2_QUANTUM_DENOMINATOR;
  1464. #else
  1465. static const dword musSubMixFreq = dword(44100/XAUDIO2_QUANTUM_DENOMINATOR)*XAUDIO2_QUANTUM_DENOMINATOR;
  1466. #endif
  1467. return musSubMixFreq;
  1468. }