FxVoice.cpp 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. #include "FxVoice.h"
  2. long FxVoice::earsSamples = 0;
  3. const float FxVoice::basicVolume = 0.8f; //Базовая громкость
  4. const float FxVoice::basicPanDelta = 0.4f; //Изменение громкости в зависимости от панарамы
  5. FxVoice::FxVoice()
  6. {
  7. FXRegistrationInfo(FxVoice, L"Storm engine FxVoice", L"Spirenkov Maxim");
  8. Reset();
  9. }
  10. FxVoice::~FxVoice()
  11. {
  12. }
  13. void STDMETHODCALLTYPE FxVoice::Process(float * __restrict ptr, dword count)
  14. {
  15. while(count > 0)
  16. {
  17. dword c = coremin(count, c_processblock);
  18. WaveProcess(ptr, c);
  19. ptr += c << 1;
  20. count -= c;
  21. }
  22. }
  23. //Просчитать буфера звука
  24. void FxVoice::WaveProcess(float * __restrict buffer, dword samples)
  25. {
  26. //Базовые параметры
  27. const dword mask = ARRSIZE(ringBuffer) - 1;
  28. dword count = samples << 1;
  29. //Подготавливаем параметры расчёта
  30. syncro.Enter();
  31. float currentVolume = processVolume;
  32. float currentFadeVolume = fadeVolume;
  33. float currentFadeDelta = fadeDelta;
  34. bool is3D = (locatorsCount > 0);
  35. if(is3D)
  36. {
  37. float dirFront = locators[0].dirFront;
  38. float dirRight = locators[0].dirRight;
  39. float att = locators[0].attenuation;
  40. syncro.Leave();
  41. //Громкость с учётом затухания
  42. currentVolume = Clampf(att)*currentVolume;
  43. if(currentVolume > 0.5f/65536.0f)
  44. {
  45. //Панорама
  46. float testPanR = Clampf(basicVolume - basicPanDelta*dirRight);
  47. float testPanL = Clampf(basicVolume + basicPanDelta*dirRight);
  48. //Смещение волны от центра
  49. long deltaPan = long(dirRight*earsSamples);
  50. long deltaPanR = -earsSamples - deltaPan;
  51. long deltaPanL = -earsSamples + deltaPan;
  52. //Коэфициент направления назад
  53. float dirK = coremax(-dirFront, 0.0f);
  54. float panK = 1.0f - coremin(dirK*3.0f, 1.0f)*0.05f;
  55. testPanR *= panK;
  56. testPanL *= panK;
  57. /*
  58. static const dword filterSize = 2;
  59. float fltK = dirK*0.8f;
  60. float nrmK = fltK*(1.0f/filterSize);
  61. float origK = 1.0f - fltK;
  62. */
  63. //Процессируем 3D звук
  64. for(dword i = 0; i < count; i += 2)
  65. {
  66. //Сохраняем сэмпл в буфере
  67. ringBuffer[ringBufferPos] = buffer[i];
  68. //Текущий сэмпл
  69. float currentSample = ringBuffer[(ringBufferPos - earsSamples) & c_hystorymask];
  70. //Считаем текущую статическую гроскость
  71. currentFadeVolume += currentFadeDelta;
  72. currentFadeVolume = Clampf(currentFadeVolume);
  73. float vol = currentVolume*currentFadeVolume;
  74. //Выбираем звук с учётом ориентации
  75. float curR = ringBuffer[(ringBufferPos + deltaPanL) & c_hystorymask];
  76. float curL = ringBuffer[(ringBufferPos + deltaPanR) & c_hystorymask];
  77. /*
  78. //Считаем приглушённую составляющую если звук находиться сзади
  79. float fltR = 0.0f;
  80. float fltL = 0.0f;
  81. for(dword j = 0; j < filterSize; j++)
  82. {
  83. fltR += ringBuffer[(ringBufferPos + deltaPanR - j*4) & c_hystorymask];
  84. fltL += ringBuffer[(ringBufferPos + deltaPanL - j*4) & c_hystorymask];
  85. }
  86. //Считаем текущее значение с учётом положения
  87. curR = curR*origK + fltR*nrmK;
  88. curL = curL*origK + fltL*nrmK;
  89. */
  90. //Подмешиваем смещённую, приглушенную волну в текущему значению
  91. curR = Lerp(currentSample, curR, 0.1f);
  92. curL = Lerp(currentSample, curL, 0.1f);
  93. //Сохраняем результат, применяя громкости панарамы и волны
  94. buffer[i + 0] = vol*testPanR*curR;
  95. buffer[i + 1] = vol*testPanL*curL;
  96. //Переводим указатель на следующий сэмпл
  97. ringBufferPos = (ringBufferPos + 1) & c_hystorymask;
  98. }
  99. }else{
  100. for(dword i = 0; i < count; i += 2)
  101. {
  102. buffer[i + 0] = 0.0f;
  103. buffer[i + 1] = 0.0f;
  104. }
  105. }
  106. }else{
  107. syncro.Leave();
  108. //Процессируем стерео звук
  109. if(currentVolume > 0.5f/65536.0f)
  110. {
  111. for(dword i = 0; i < count; i += 2)
  112. {
  113. //Считаем текущую статическую гроскость
  114. currentFadeVolume += currentFadeDelta;
  115. currentFadeVolume = Clampf(currentFadeVolume);
  116. float vol = currentVolume*currentFadeVolume;
  117. //Применяем на стерео канал
  118. buffer[i + 0] *= vol;
  119. buffer[i + 1] *= vol;
  120. }
  121. }else{
  122. for(dword i = 0; i < count; i += 2)
  123. {
  124. buffer[i + 0] = 0.0f;
  125. buffer[i + 1] = 0.0f;
  126. }
  127. }
  128. }
  129. syncro.Enter();
  130. //Возвращаемые параметры
  131. fadeVolume = currentFadeVolume;
  132. retFadeVolume = fadeVolume;
  133. retCurrVolume = currentVolume*currentFadeVolume;
  134. syncro.Leave();
  135. }
  136. //Перевести эффект-процессор в исходное состояние
  137. void STDMETHODCALLTYPE FxVoice::Reset()
  138. {
  139. syncro.Enter();
  140. processVolume = 1.0f;
  141. fadeVolume = 1.0f;
  142. fadeDelta = 0.0f;
  143. retFadeVolume = 1.0f;
  144. retCurrVolume = 1.0f;
  145. locatorsCount = 0;
  146. ringBufferPos = 0;
  147. for(long i = 0; i < c_hystorysize; i++)
  148. {
  149. ringBuffer[i] = 0.0f;
  150. }
  151. syncro.Leave();
  152. }
  153. //Начать процесс плавного наростания кромкости до нормальной
  154. void FxVoice::FadeIn(float stepFadeDelta)
  155. {
  156. syncro.Enter();
  157. fadeVolume = 0.0f;
  158. fadeDelta = stepFadeDelta;
  159. syncro.Leave();
  160. }
  161. //Начать процесс плавного уменьшения громкости
  162. void FxVoice::FadeOut(float stepFadeDelta)
  163. {
  164. syncro.Enter();
  165. fadeDelta = stepFadeDelta;
  166. syncro.Leave();
  167. }
  168. //Установить пространственное расположение звука
  169. void FxVoice::SetLocators(const Locator * locs, dword count)
  170. {
  171. Assert(count <= c_maxlocators);
  172. syncro.Enter();
  173. for(dword i = 0; i < count; i++)
  174. {
  175. locators[i] = locs[i];
  176. }
  177. locatorsCount = count;
  178. syncro.Leave();
  179. }
  180. //Установить текущую константную громкость
  181. void FxVoice::SetVolume(float volume)
  182. {
  183. syncro.Enter();
  184. processVolume = volume;
  185. syncro.Leave();
  186. }
  187. //Разрешить пространственные эффекты
  188. void FxVoice::EnableEnvironment(bool isEbable)
  189. {
  190. }
  191. //Получить действующую громкость
  192. float FxVoice::GetCurrentVolume()
  193. {
  194. syncro.Enter();
  195. float vol = retCurrVolume;
  196. syncro.Leave();
  197. return vol;
  198. }
  199. //Получить множитель фейда
  200. float FxVoice::GetFadeVolume()
  201. {
  202. syncro.Enter();
  203. float vol = retFadeVolume;
  204. syncro.Leave();
  205. return vol;
  206. }
  207. //Инициализировать константы
  208. void FxVoice::StaticInit(dword sampleRates)
  209. {
  210. float earsDistTime = c_eardist*0.001f/c_soundspeed;
  211. earsSamples = long(earsDistTime*sampleRates);
  212. }