FxScene.cpp 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  1. #include "FxScene.h"
  2. #include "SoundsEngine.h"
  3. const float FxScene::timeEarly[18][2] = {
  4. {0.0143f, 0.841f}, //1
  5. {0.0215f, 0.504f}, //2
  6. {0.0225f, -0.491f}, //3
  7. {0.0268f, 0.379f}, //4
  8. {0.0270f, 0.380f}, //5
  9. {0.0298f, 0.346f}, //6
  10. {0.0458f, -0.289f}, //7
  11. {0.0485f, 0.272f}, //8
  12. {0.0572f, 0.192f}, //9
  13. {0.0587f, 0.193f}, //10
  14. {0.0595f, 0.217f}, //11
  15. {0.0612f, -0.181f}, //12
  16. {0.0707f, 0.180f}, //13
  17. {0.0708f, 0.181f}, //14
  18. {0.0726f, -0.176f}, //15
  19. {0.0741f, 0.142f}, //16
  20. {0.0753f, -0.167f}, //17
  21. {0.0797f, 0.134f} //18
  22. };
  23. __forceinline FxScene::Delay::Delay()
  24. {
  25. cur = null;
  26. buffer = null;
  27. endPrt = null;
  28. size = 0;
  29. damp = 0.0f;
  30. }
  31. __forceinline FxScene::Delay::~Delay()
  32. {
  33. Release();
  34. }
  35. __forceinline void FxScene::Delay::Release()
  36. {
  37. if(buffer) delete buffer;
  38. buffer = null;
  39. }
  40. __forceinline void FxScene::Delay::SetDelay(dword size)
  41. {
  42. Assert(!buffer);
  43. buffer = NEW float[size];
  44. endPrt = buffer + size;
  45. this->size = size;
  46. Reset();
  47. }
  48. __forceinline void FxScene::Delay::SetDelayMs(float timeInMs)
  49. {
  50. SetDelay(dword(SoundsEngine::GetFxMixFreq()*0.001f*timeInMs));
  51. }
  52. __forceinline void FxScene::Delay::Reset()
  53. {
  54. for(float * f = buffer; f < endPrt; f++) *f = 0.0f;
  55. cur = buffer;
  56. damp = 0.0f;
  57. }
  58. __forceinline void FxScene::Delay::Set(float v)
  59. {
  60. *cur = v;
  61. Next();
  62. }
  63. __forceinline float FxScene::Delay::Predelay(float timeInMs, float g)
  64. {
  65. dword delta = long(SoundsEngine::GetFxMixFreq()*0.001f*timeInMs);
  66. if(delta > size) delta = size;
  67. float * val = cur - delta;
  68. if(val < buffer) val += endPrt - buffer;
  69. Assert(val >= buffer && val < endPrt);
  70. return *val*g;
  71. }
  72. __forceinline float FxScene::Delay::Damp(float v, float kDamp)
  73. {
  74. damp = v*(1.0f - kDamp) + damp*kDamp;
  75. return damp;
  76. }
  77. __forceinline float FxScene::Delay::Comb(float v, float g, float kDamp)
  78. {
  79. damp = damp*kDamp + *cur*(1.0f - kDamp);
  80. float out = damp*g + v;
  81. Set(out);
  82. return out;
  83. }
  84. __forceinline float FxScene::Delay::AllPass(float v, float g, float kDamp)
  85. {
  86. damp = damp*kDamp + *cur*(1.0f - kDamp);
  87. float out = damp - g*v;
  88. *cur = v + out*g;
  89. Next();
  90. return out;
  91. }
  92. __forceinline void FxScene::Delay::Next()
  93. {
  94. cur++;
  95. if(cur >= endPrt) cur = buffer;
  96. }
  97. FxScene::FxScene()
  98. {
  99. FXRegistrationInfo(FxScene, L"Storm engine FxScene", L"Spirenkov Maxim");
  100. Clear(false);
  101. }
  102. FxScene::~FxScene()
  103. {
  104. }
  105. //Обсчитать полный буффер
  106. void STDMETHODCALLTYPE FxScene::Process(float * __restrict ptr, dword count)
  107. {
  108. if(flags & flag_isInit)
  109. {
  110. accessSync.Enter();
  111. while(count > 0)
  112. {
  113. dword c = coremin(count, c_processblock);
  114. WaveProcess(ptr, c);
  115. ptr += c << 1;
  116. count -= c;
  117. }
  118. accessSync.Leave();
  119. }
  120. }
  121. //Просчитать буфера звука
  122. void FxScene::WaveProcess(float * __restrict buffer, dword samples)
  123. {
  124. syncro.Enter();
  125. if(flags & flag_isUpdate)
  126. {
  127. //Расчёт новых параметров
  128. float damp = Clampf(params.damping);
  129. float dispersion = Clampf(params.dispersion);
  130. predelayTime = Clampf(params.predelayTime, 10.0f, (float)c_predelay_max_ms);
  131. earlyTime = Clampf(params.earlyTime, 10.0f, (float)c_early_max_ms)*normalizeEarlyTime;
  132. earlyFadeMin = 0.5f*Clampf(params.earlyAttenuation);
  133. earlyFadeDlt = 1.0f - earlyFadeMin;
  134. earlyDamp = 0.7f + 0.25f*damp;
  135. diffuseWeight = 0.2f + 0.7f*dispersion;
  136. earlyWeight = 1.0f - diffuseWeight;
  137. wet = params.wet;
  138. dry = params.dry;
  139. diffuseAllpassGain = Clampf(dispersion*0.3f + earlyTime*(0.7f/c_early_max_ms) + 0.2f, 0.1f, 0.85f);
  140. diffuseCombGain = diffuseAllpassGain*0.8f;
  141. diffuseCombDamp = damp*0.5f;
  142. diffuseAllpassDamp = damp*0.8f;
  143. envDampingKoef = damp*damp*0.99f;
  144. envDampingKoefRever = 1.0f - envDampingKoef;
  145. flags &= ~flag_isUpdate;
  146. }
  147. syncro.Leave();
  148. if(wet < 0.001f && fabsf(dry - 1.0f) < 1e-8f)
  149. {
  150. return;
  151. }
  152. dword count = samples << 1;
  153. for(dword i = 0; i < count; i += 2)
  154. {
  155. //Текущии значения
  156. float vR = buffer[i + 0];
  157. float vL = buffer[i + 1];
  158. //Предварительная задержка
  159. predelay.Set((vR + vL)*0.5f);
  160. float preVal = predelay.Predelay(predelayTime, 1.0f);
  161. //Вторичные отражения
  162. float earlyVal = preVal + RRnd(-0.0000001f, 0.0000001f);
  163. for(dword j = 0; j < ARRSIZE(timeEarly) - 1; j++)
  164. {
  165. float v = early.Predelay(timeEarly[j][0]*earlyTime, earlyFadeMin + earlyFadeDlt*timeEarly[j][1]);
  166. earlyVal += v;
  167. }
  168. earlyVal *= normalizeEarlyVolume;
  169. float continueVal = earlyVal*earlyFadeMin;
  170. continueVal = early.Damp(continueVal, earlyDamp);
  171. early.Set(preVal - continueVal);
  172. //Рассеивание
  173. float diffR = envDampingR*0.01f;
  174. float diffL = envDampingL*0.01f;
  175. for(dword j = 0; j < ARRSIZE(combR); j++)
  176. {
  177. diffR += combR[j].Comb(earlyVal, diffuseCombGain, diffuseCombDamp);
  178. diffL += combL[j].Comb(earlyVal, diffuseCombGain, diffuseCombDamp);
  179. }
  180. diffR = diffR*(0.8f/ARRSIZE(combR)) + diffL*(0.2f/ARRSIZE(combR));
  181. diffL = diffR*(0.2f/ARRSIZE(combR)) + diffL*(0.8f/ARRSIZE(combR));
  182. for(dword j = 0; j < ARRSIZE(allpassR); j++)
  183. {
  184. diffR = allpassR[j].AllPass(diffR, diffuseAllpassGain, diffuseAllpassDamp);
  185. diffL = allpassL[j].AllPass(diffL, diffuseAllpassGain, diffuseAllpassDamp);
  186. }
  187. float reverValR = earlyVal*earlyWeight + diffR*diffuseWeight;
  188. float reverValL = earlyVal*earlyWeight + diffL*diffuseWeight;
  189. envDampingR = reverValR*envDampingKoefRever + envDampingR*envDampingKoef;
  190. envDampingL = reverValL*envDampingKoefRever + envDampingL*envDampingKoef;
  191. //Результирующий сигнал
  192. buffer[i + 0] = vR*dry + reverValR*wet;
  193. buffer[i + 1] = vL*dry + reverValL*wet;
  194. }
  195. }
  196. //Установить параметры среды
  197. void FxScene::SetParams(const EnvParams & data)
  198. {
  199. syncro.Enter();
  200. if(flags & flag_isInit)
  201. {
  202. params = data;
  203. flags |= flag_isUpdate;
  204. syncro.Leave();
  205. }else{
  206. syncro.Leave();
  207. accessSync.Enter();
  208. predelay.SetDelayMs(c_predelay_max_ms);
  209. predelay.Reset();
  210. early.SetDelayMs(c_early_max_ms);
  211. early.Reset();
  212. const float kMin = 0.8f;
  213. const float kMax = 1.2f;
  214. for(dword i = 0; i < ARRSIZE(combR); i++)
  215. {
  216. float k = i*(1.0f/(ARRSIZE(combR) - 1.0f));
  217. float scale = powf(2, k) - 1.0f;
  218. float delayTime = 21.0f + scale*(30.0f + 2.0f*sinf(k*34.0f));
  219. combL[i].SetDelayMs(delayTime*((i & 1) ? kMax : kMin));
  220. combL[i].Reset();
  221. combR[i].SetDelayMs(delayTime*((i & 1) ? kMin + 0.1f : kMax + 0.1f));
  222. combR[i].Reset();
  223. }
  224. for(dword i = 0; i < ARRSIZE(allpassR); i++)
  225. {
  226. float k = i*(1.0f/(ARRSIZE(allpassR) - 1.0f));
  227. float scale = powf(2, 1.0f - k) - 1.0f;
  228. float delayTime = 15.0f + scale*20.0f;
  229. allpassL[i].SetDelayMs(delayTime*((i & 1) ? kMin + 0.01f : kMax + 0.01f));
  230. allpassL[i].Reset();
  231. allpassR[i].SetDelayMs(delayTime*((i & 1) ? kMax : kMin));
  232. allpassR[i].Reset();
  233. }
  234. accessSync.Leave();
  235. syncro.Enter();
  236. params = data;
  237. flags |= flag_isInit | flag_isUpdate;
  238. syncro.Leave();
  239. }
  240. }
  241. //Перевести эффект-процессор в исходное состояние
  242. void STDMETHODCALLTYPE FxScene::Reset()
  243. {
  244. accessSync.Enter();
  245. if((flags & flag_isInit) != 0)
  246. {
  247. predelay.Reset();
  248. early.Reset();
  249. for(dword i = 0; i < ARRSIZE(combR); i++)
  250. {
  251. combR[i].Reset();
  252. combL[i].Reset();
  253. }
  254. for(dword i = 0; i < ARRSIZE(allpassR); i++)
  255. {
  256. allpassR[i].Reset();
  257. allpassL[i].Reset();
  258. }
  259. }
  260. wet = 0.0f;
  261. dry = 1.0f;
  262. envDampingR = 0.0f;
  263. envDampingL = 0.0f;
  264. accessSync.Leave();
  265. syncro.Enter();
  266. memset(&params, 0, sizeof(params));
  267. params.dry = 1.0f;
  268. flags &= ~flag_isUpdate;
  269. syncro.Leave();
  270. }
  271. //Очистить буфера, и перейти в неактивное состояние
  272. void FxScene::Clear(bool isSync)
  273. {
  274. if(isSync)
  275. {
  276. accessSync.Enter();
  277. }
  278. flags = flag_init_value;
  279. predelay.Release();
  280. early.Release();
  281. for(dword i = 0; i < ARRSIZE(combR); i++)
  282. {
  283. combR[i].Release();
  284. combL[i].Release();
  285. }
  286. for(dword i = 0; i < ARRSIZE(allpassR); i++)
  287. {
  288. allpassR[i].Release();
  289. allpassL[i].Release();
  290. }
  291. predelayTime = 0.0f;
  292. earlyTime = 0.0f;
  293. earlyFadeMin = 0.0f;
  294. earlyFadeDlt = 0.0f;
  295. earlyDamp = 0.0f;
  296. earlyWeight = 0.0f;
  297. diffuseWeight = 0.0f;
  298. wet = 0.0f;
  299. dry = 1.0f;
  300. diffuseCombGain = 0.0f;
  301. diffuseCombDamp = 0.0f;
  302. diffuseAllpassGain = 0.0f;
  303. diffuseAllpassDamp = 0.0f;
  304. envDampingKoef = 0.0f;
  305. envDampingKoefRever = 0.0f;
  306. envDampingL = 0.0f;
  307. envDampingR = 0.0f;
  308. normalizeEarlyTime = 1.0f/timeEarly[ARRSIZE(timeEarly) - 1][0];
  309. normalizeEarlyVolume = 1.0f;
  310. for(dword j = 0; j < ARRSIZE(timeEarly); j++)
  311. {
  312. normalizeEarlyVolume += fabsf(timeEarly[j][1]);
  313. }
  314. normalizeEarlyVolume = 1.0f/normalizeEarlyVolume;
  315. if(isSync)
  316. {
  317. accessSync.Leave();
  318. }
  319. }