🛠️🐜 Antkeeper superbuild with dependencies included https://antkeeper.com
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1994 lines
65 KiB

  1. #include "config.h"
  2. #include <cmath>
  3. #include "AL/al.h"
  4. #include "AL/efx.h"
  5. #include "alc/effects/base.h"
  6. #include "effects.h"
  7. #ifdef ALSOFT_EAX
  8. #include <cassert>
  9. #include "alnumeric.h"
  10. #include "AL/efx-presets.h"
  11. #include "al/eax/exception.h"
  12. #include "al/eax/utils.h"
  13. #endif // ALSOFT_EAX
  14. namespace {
  15. void Reverb_setParami(EffectProps *props, ALenum param, int val)
  16. {
  17. switch(param)
  18. {
  19. case AL_EAXREVERB_DECAY_HFLIMIT:
  20. if(!(val >= AL_EAXREVERB_MIN_DECAY_HFLIMIT && val <= AL_EAXREVERB_MAX_DECAY_HFLIMIT))
  21. throw effect_exception{AL_INVALID_VALUE, "EAX Reverb decay hflimit out of range"};
  22. props->Reverb.DecayHFLimit = val != AL_FALSE;
  23. break;
  24. default:
  25. throw effect_exception{AL_INVALID_ENUM, "Invalid EAX reverb integer property 0x%04x",
  26. param};
  27. }
  28. }
  29. void Reverb_setParamiv(EffectProps *props, ALenum param, const int *vals)
  30. { Reverb_setParami(props, param, vals[0]); }
  31. void Reverb_setParamf(EffectProps *props, ALenum param, float val)
  32. {
  33. switch(param)
  34. {
  35. case AL_EAXREVERB_DENSITY:
  36. if(!(val >= AL_EAXREVERB_MIN_DENSITY && val <= AL_EAXREVERB_MAX_DENSITY))
  37. throw effect_exception{AL_INVALID_VALUE, "EAX Reverb density out of range"};
  38. props->Reverb.Density = val;
  39. break;
  40. case AL_EAXREVERB_DIFFUSION:
  41. if(!(val >= AL_EAXREVERB_MIN_DIFFUSION && val <= AL_EAXREVERB_MAX_DIFFUSION))
  42. throw effect_exception{AL_INVALID_VALUE, "EAX Reverb diffusion out of range"};
  43. props->Reverb.Diffusion = val;
  44. break;
  45. case AL_EAXREVERB_GAIN:
  46. if(!(val >= AL_EAXREVERB_MIN_GAIN && val <= AL_EAXREVERB_MAX_GAIN))
  47. throw effect_exception{AL_INVALID_VALUE, "EAX Reverb gain out of range"};
  48. props->Reverb.Gain = val;
  49. break;
  50. case AL_EAXREVERB_GAINHF:
  51. if(!(val >= AL_EAXREVERB_MIN_GAINHF && val <= AL_EAXREVERB_MAX_GAINHF))
  52. throw effect_exception{AL_INVALID_VALUE, "EAX Reverb gainhf out of range"};
  53. props->Reverb.GainHF = val;
  54. break;
  55. case AL_EAXREVERB_GAINLF:
  56. if(!(val >= AL_EAXREVERB_MIN_GAINLF && val <= AL_EAXREVERB_MAX_GAINLF))
  57. throw effect_exception{AL_INVALID_VALUE, "EAX Reverb gainlf out of range"};
  58. props->Reverb.GainLF = val;
  59. break;
  60. case AL_EAXREVERB_DECAY_TIME:
  61. if(!(val >= AL_EAXREVERB_MIN_DECAY_TIME && val <= AL_EAXREVERB_MAX_DECAY_TIME))
  62. throw effect_exception{AL_INVALID_VALUE, "EAX Reverb decay time out of range"};
  63. props->Reverb.DecayTime = val;
  64. break;
  65. case AL_EAXREVERB_DECAY_HFRATIO:
  66. if(!(val >= AL_EAXREVERB_MIN_DECAY_HFRATIO && val <= AL_EAXREVERB_MAX_DECAY_HFRATIO))
  67. throw effect_exception{AL_INVALID_VALUE, "EAX Reverb decay hfratio out of range"};
  68. props->Reverb.DecayHFRatio = val;
  69. break;
  70. case AL_EAXREVERB_DECAY_LFRATIO:
  71. if(!(val >= AL_EAXREVERB_MIN_DECAY_LFRATIO && val <= AL_EAXREVERB_MAX_DECAY_LFRATIO))
  72. throw effect_exception{AL_INVALID_VALUE, "EAX Reverb decay lfratio out of range"};
  73. props->Reverb.DecayLFRatio = val;
  74. break;
  75. case AL_EAXREVERB_REFLECTIONS_GAIN:
  76. if(!(val >= AL_EAXREVERB_MIN_REFLECTIONS_GAIN && val <= AL_EAXREVERB_MAX_REFLECTIONS_GAIN))
  77. throw effect_exception{AL_INVALID_VALUE, "EAX Reverb reflections gain out of range"};
  78. props->Reverb.ReflectionsGain = val;
  79. break;
  80. case AL_EAXREVERB_REFLECTIONS_DELAY:
  81. if(!(val >= AL_EAXREVERB_MIN_REFLECTIONS_DELAY && val <= AL_EAXREVERB_MAX_REFLECTIONS_DELAY))
  82. throw effect_exception{AL_INVALID_VALUE, "EAX Reverb reflections delay out of range"};
  83. props->Reverb.ReflectionsDelay = val;
  84. break;
  85. case AL_EAXREVERB_LATE_REVERB_GAIN:
  86. if(!(val >= AL_EAXREVERB_MIN_LATE_REVERB_GAIN && val <= AL_EAXREVERB_MAX_LATE_REVERB_GAIN))
  87. throw effect_exception{AL_INVALID_VALUE, "EAX Reverb late reverb gain out of range"};
  88. props->Reverb.LateReverbGain = val;
  89. break;
  90. case AL_EAXREVERB_LATE_REVERB_DELAY:
  91. if(!(val >= AL_EAXREVERB_MIN_LATE_REVERB_DELAY && val <= AL_EAXREVERB_MAX_LATE_REVERB_DELAY))
  92. throw effect_exception{AL_INVALID_VALUE, "EAX Reverb late reverb delay out of range"};
  93. props->Reverb.LateReverbDelay = val;
  94. break;
  95. case AL_EAXREVERB_AIR_ABSORPTION_GAINHF:
  96. if(!(val >= AL_EAXREVERB_MIN_AIR_ABSORPTION_GAINHF && val <= AL_EAXREVERB_MAX_AIR_ABSORPTION_GAINHF))
  97. throw effect_exception{AL_INVALID_VALUE, "EAX Reverb air absorption gainhf out of range"};
  98. props->Reverb.AirAbsorptionGainHF = val;
  99. break;
  100. case AL_EAXREVERB_ECHO_TIME:
  101. if(!(val >= AL_EAXREVERB_MIN_ECHO_TIME && val <= AL_EAXREVERB_MAX_ECHO_TIME))
  102. throw effect_exception{AL_INVALID_VALUE, "EAX Reverb echo time out of range"};
  103. props->Reverb.EchoTime = val;
  104. break;
  105. case AL_EAXREVERB_ECHO_DEPTH:
  106. if(!(val >= AL_EAXREVERB_MIN_ECHO_DEPTH && val <= AL_EAXREVERB_MAX_ECHO_DEPTH))
  107. throw effect_exception{AL_INVALID_VALUE, "EAX Reverb echo depth out of range"};
  108. props->Reverb.EchoDepth = val;
  109. break;
  110. case AL_EAXREVERB_MODULATION_TIME:
  111. if(!(val >= AL_EAXREVERB_MIN_MODULATION_TIME && val <= AL_EAXREVERB_MAX_MODULATION_TIME))
  112. throw effect_exception{AL_INVALID_VALUE, "EAX Reverb modulation time out of range"};
  113. props->Reverb.ModulationTime = val;
  114. break;
  115. case AL_EAXREVERB_MODULATION_DEPTH:
  116. if(!(val >= AL_EAXREVERB_MIN_MODULATION_DEPTH && val <= AL_EAXREVERB_MAX_MODULATION_DEPTH))
  117. throw effect_exception{AL_INVALID_VALUE, "EAX Reverb modulation depth out of range"};
  118. props->Reverb.ModulationDepth = val;
  119. break;
  120. case AL_EAXREVERB_HFREFERENCE:
  121. if(!(val >= AL_EAXREVERB_MIN_HFREFERENCE && val <= AL_EAXREVERB_MAX_HFREFERENCE))
  122. throw effect_exception{AL_INVALID_VALUE, "EAX Reverb hfreference out of range"};
  123. props->Reverb.HFReference = val;
  124. break;
  125. case AL_EAXREVERB_LFREFERENCE:
  126. if(!(val >= AL_EAXREVERB_MIN_LFREFERENCE && val <= AL_EAXREVERB_MAX_LFREFERENCE))
  127. throw effect_exception{AL_INVALID_VALUE, "EAX Reverb lfreference out of range"};
  128. props->Reverb.LFReference = val;
  129. break;
  130. case AL_EAXREVERB_ROOM_ROLLOFF_FACTOR:
  131. if(!(val >= AL_EAXREVERB_MIN_ROOM_ROLLOFF_FACTOR && val <= AL_EAXREVERB_MAX_ROOM_ROLLOFF_FACTOR))
  132. throw effect_exception{AL_INVALID_VALUE, "EAX Reverb room rolloff factor out of range"};
  133. props->Reverb.RoomRolloffFactor = val;
  134. break;
  135. default:
  136. throw effect_exception{AL_INVALID_ENUM, "Invalid EAX reverb float property 0x%04x", param};
  137. }
  138. }
  139. void Reverb_setParamfv(EffectProps *props, ALenum param, const float *vals)
  140. {
  141. switch(param)
  142. {
  143. case AL_EAXREVERB_REFLECTIONS_PAN:
  144. if(!(std::isfinite(vals[0]) && std::isfinite(vals[1]) && std::isfinite(vals[2])))
  145. throw effect_exception{AL_INVALID_VALUE, "EAX Reverb reflections pan out of range"};
  146. props->Reverb.ReflectionsPan[0] = vals[0];
  147. props->Reverb.ReflectionsPan[1] = vals[1];
  148. props->Reverb.ReflectionsPan[2] = vals[2];
  149. break;
  150. case AL_EAXREVERB_LATE_REVERB_PAN:
  151. if(!(std::isfinite(vals[0]) && std::isfinite(vals[1]) && std::isfinite(vals[2])))
  152. throw effect_exception{AL_INVALID_VALUE, "EAX Reverb late reverb pan out of range"};
  153. props->Reverb.LateReverbPan[0] = vals[0];
  154. props->Reverb.LateReverbPan[1] = vals[1];
  155. props->Reverb.LateReverbPan[2] = vals[2];
  156. break;
  157. default:
  158. Reverb_setParamf(props, param, vals[0]);
  159. break;
  160. }
  161. }
  162. void Reverb_getParami(const EffectProps *props, ALenum param, int *val)
  163. {
  164. switch(param)
  165. {
  166. case AL_EAXREVERB_DECAY_HFLIMIT:
  167. *val = props->Reverb.DecayHFLimit;
  168. break;
  169. default:
  170. throw effect_exception{AL_INVALID_ENUM, "Invalid EAX reverb integer property 0x%04x",
  171. param};
  172. }
  173. }
  174. void Reverb_getParamiv(const EffectProps *props, ALenum param, int *vals)
  175. { Reverb_getParami(props, param, vals); }
  176. void Reverb_getParamf(const EffectProps *props, ALenum param, float *val)
  177. {
  178. switch(param)
  179. {
  180. case AL_EAXREVERB_DENSITY:
  181. *val = props->Reverb.Density;
  182. break;
  183. case AL_EAXREVERB_DIFFUSION:
  184. *val = props->Reverb.Diffusion;
  185. break;
  186. case AL_EAXREVERB_GAIN:
  187. *val = props->Reverb.Gain;
  188. break;
  189. case AL_EAXREVERB_GAINHF:
  190. *val = props->Reverb.GainHF;
  191. break;
  192. case AL_EAXREVERB_GAINLF:
  193. *val = props->Reverb.GainLF;
  194. break;
  195. case AL_EAXREVERB_DECAY_TIME:
  196. *val = props->Reverb.DecayTime;
  197. break;
  198. case AL_EAXREVERB_DECAY_HFRATIO:
  199. *val = props->Reverb.DecayHFRatio;
  200. break;
  201. case AL_EAXREVERB_DECAY_LFRATIO:
  202. *val = props->Reverb.DecayLFRatio;
  203. break;
  204. case AL_EAXREVERB_REFLECTIONS_GAIN:
  205. *val = props->Reverb.ReflectionsGain;
  206. break;
  207. case AL_EAXREVERB_REFLECTIONS_DELAY:
  208. *val = props->Reverb.ReflectionsDelay;
  209. break;
  210. case AL_EAXREVERB_LATE_REVERB_GAIN:
  211. *val = props->Reverb.LateReverbGain;
  212. break;
  213. case AL_EAXREVERB_LATE_REVERB_DELAY:
  214. *val = props->Reverb.LateReverbDelay;
  215. break;
  216. case AL_EAXREVERB_AIR_ABSORPTION_GAINHF:
  217. *val = props->Reverb.AirAbsorptionGainHF;
  218. break;
  219. case AL_EAXREVERB_ECHO_TIME:
  220. *val = props->Reverb.EchoTime;
  221. break;
  222. case AL_EAXREVERB_ECHO_DEPTH:
  223. *val = props->Reverb.EchoDepth;
  224. break;
  225. case AL_EAXREVERB_MODULATION_TIME:
  226. *val = props->Reverb.ModulationTime;
  227. break;
  228. case AL_EAXREVERB_MODULATION_DEPTH:
  229. *val = props->Reverb.ModulationDepth;
  230. break;
  231. case AL_EAXREVERB_HFREFERENCE:
  232. *val = props->Reverb.HFReference;
  233. break;
  234. case AL_EAXREVERB_LFREFERENCE:
  235. *val = props->Reverb.LFReference;
  236. break;
  237. case AL_EAXREVERB_ROOM_ROLLOFF_FACTOR:
  238. *val = props->Reverb.RoomRolloffFactor;
  239. break;
  240. default:
  241. throw effect_exception{AL_INVALID_ENUM, "Invalid EAX reverb float property 0x%04x", param};
  242. }
  243. }
  244. void Reverb_getParamfv(const EffectProps *props, ALenum param, float *vals)
  245. {
  246. switch(param)
  247. {
  248. case AL_EAXREVERB_REFLECTIONS_PAN:
  249. vals[0] = props->Reverb.ReflectionsPan[0];
  250. vals[1] = props->Reverb.ReflectionsPan[1];
  251. vals[2] = props->Reverb.ReflectionsPan[2];
  252. break;
  253. case AL_EAXREVERB_LATE_REVERB_PAN:
  254. vals[0] = props->Reverb.LateReverbPan[0];
  255. vals[1] = props->Reverb.LateReverbPan[1];
  256. vals[2] = props->Reverb.LateReverbPan[2];
  257. break;
  258. default:
  259. Reverb_getParamf(props, param, vals);
  260. break;
  261. }
  262. }
  263. EffectProps genDefaultProps() noexcept
  264. {
  265. EffectProps props{};
  266. props.Reverb.Density = AL_EAXREVERB_DEFAULT_DENSITY;
  267. props.Reverb.Diffusion = AL_EAXREVERB_DEFAULT_DIFFUSION;
  268. props.Reverb.Gain = AL_EAXREVERB_DEFAULT_GAIN;
  269. props.Reverb.GainHF = AL_EAXREVERB_DEFAULT_GAINHF;
  270. props.Reverb.GainLF = AL_EAXREVERB_DEFAULT_GAINLF;
  271. props.Reverb.DecayTime = AL_EAXREVERB_DEFAULT_DECAY_TIME;
  272. props.Reverb.DecayHFRatio = AL_EAXREVERB_DEFAULT_DECAY_HFRATIO;
  273. props.Reverb.DecayLFRatio = AL_EAXREVERB_DEFAULT_DECAY_LFRATIO;
  274. props.Reverb.ReflectionsGain = AL_EAXREVERB_DEFAULT_REFLECTIONS_GAIN;
  275. props.Reverb.ReflectionsDelay = AL_EAXREVERB_DEFAULT_REFLECTIONS_DELAY;
  276. props.Reverb.ReflectionsPan[0] = AL_EAXREVERB_DEFAULT_REFLECTIONS_PAN_XYZ;
  277. props.Reverb.ReflectionsPan[1] = AL_EAXREVERB_DEFAULT_REFLECTIONS_PAN_XYZ;
  278. props.Reverb.ReflectionsPan[2] = AL_EAXREVERB_DEFAULT_REFLECTIONS_PAN_XYZ;
  279. props.Reverb.LateReverbGain = AL_EAXREVERB_DEFAULT_LATE_REVERB_GAIN;
  280. props.Reverb.LateReverbDelay = AL_EAXREVERB_DEFAULT_LATE_REVERB_DELAY;
  281. props.Reverb.LateReverbPan[0] = AL_EAXREVERB_DEFAULT_LATE_REVERB_PAN_XYZ;
  282. props.Reverb.LateReverbPan[1] = AL_EAXREVERB_DEFAULT_LATE_REVERB_PAN_XYZ;
  283. props.Reverb.LateReverbPan[2] = AL_EAXREVERB_DEFAULT_LATE_REVERB_PAN_XYZ;
  284. props.Reverb.EchoTime = AL_EAXREVERB_DEFAULT_ECHO_TIME;
  285. props.Reverb.EchoDepth = AL_EAXREVERB_DEFAULT_ECHO_DEPTH;
  286. props.Reverb.ModulationTime = AL_EAXREVERB_DEFAULT_MODULATION_TIME;
  287. props.Reverb.ModulationDepth = AL_EAXREVERB_DEFAULT_MODULATION_DEPTH;
  288. props.Reverb.AirAbsorptionGainHF = AL_EAXREVERB_DEFAULT_AIR_ABSORPTION_GAINHF;
  289. props.Reverb.HFReference = AL_EAXREVERB_DEFAULT_HFREFERENCE;
  290. props.Reverb.LFReference = AL_EAXREVERB_DEFAULT_LFREFERENCE;
  291. props.Reverb.RoomRolloffFactor = AL_EAXREVERB_DEFAULT_ROOM_ROLLOFF_FACTOR;
  292. props.Reverb.DecayHFLimit = AL_EAXREVERB_DEFAULT_DECAY_HFLIMIT;
  293. return props;
  294. }
  295. void StdReverb_setParami(EffectProps *props, ALenum param, int val)
  296. {
  297. switch(param)
  298. {
  299. case AL_REVERB_DECAY_HFLIMIT:
  300. if(!(val >= AL_REVERB_MIN_DECAY_HFLIMIT && val <= AL_REVERB_MAX_DECAY_HFLIMIT))
  301. throw effect_exception{AL_INVALID_VALUE, "Reverb decay hflimit out of range"};
  302. props->Reverb.DecayHFLimit = val != AL_FALSE;
  303. break;
  304. default:
  305. throw effect_exception{AL_INVALID_ENUM, "Invalid reverb integer property 0x%04x", param};
  306. }
  307. }
  308. void StdReverb_setParamiv(EffectProps *props, ALenum param, const int *vals)
  309. { StdReverb_setParami(props, param, vals[0]); }
  310. void StdReverb_setParamf(EffectProps *props, ALenum param, float val)
  311. {
  312. switch(param)
  313. {
  314. case AL_REVERB_DENSITY:
  315. if(!(val >= AL_REVERB_MIN_DENSITY && val <= AL_REVERB_MAX_DENSITY))
  316. throw effect_exception{AL_INVALID_VALUE, "Reverb density out of range"};
  317. props->Reverb.Density = val;
  318. break;
  319. case AL_REVERB_DIFFUSION:
  320. if(!(val >= AL_REVERB_MIN_DIFFUSION && val <= AL_REVERB_MAX_DIFFUSION))
  321. throw effect_exception{AL_INVALID_VALUE, "Reverb diffusion out of range"};
  322. props->Reverb.Diffusion = val;
  323. break;
  324. case AL_REVERB_GAIN:
  325. if(!(val >= AL_REVERB_MIN_GAIN && val <= AL_REVERB_MAX_GAIN))
  326. throw effect_exception{AL_INVALID_VALUE, "Reverb gain out of range"};
  327. props->Reverb.Gain = val;
  328. break;
  329. case AL_REVERB_GAINHF:
  330. if(!(val >= AL_REVERB_MIN_GAINHF && val <= AL_REVERB_MAX_GAINHF))
  331. throw effect_exception{AL_INVALID_VALUE, "Reverb gainhf out of range"};
  332. props->Reverb.GainHF = val;
  333. break;
  334. case AL_REVERB_DECAY_TIME:
  335. if(!(val >= AL_REVERB_MIN_DECAY_TIME && val <= AL_REVERB_MAX_DECAY_TIME))
  336. throw effect_exception{AL_INVALID_VALUE, "Reverb decay time out of range"};
  337. props->Reverb.DecayTime = val;
  338. break;
  339. case AL_REVERB_DECAY_HFRATIO:
  340. if(!(val >= AL_REVERB_MIN_DECAY_HFRATIO && val <= AL_REVERB_MAX_DECAY_HFRATIO))
  341. throw effect_exception{AL_INVALID_VALUE, "Reverb decay hfratio out of range"};
  342. props->Reverb.DecayHFRatio = val;
  343. break;
  344. case AL_REVERB_REFLECTIONS_GAIN:
  345. if(!(val >= AL_REVERB_MIN_REFLECTIONS_GAIN && val <= AL_REVERB_MAX_REFLECTIONS_GAIN))
  346. throw effect_exception{AL_INVALID_VALUE, "Reverb reflections gain out of range"};
  347. props->Reverb.ReflectionsGain = val;
  348. break;
  349. case AL_REVERB_REFLECTIONS_DELAY:
  350. if(!(val >= AL_REVERB_MIN_REFLECTIONS_DELAY && val <= AL_REVERB_MAX_REFLECTIONS_DELAY))
  351. throw effect_exception{AL_INVALID_VALUE, "Reverb reflections delay out of range"};
  352. props->Reverb.ReflectionsDelay = val;
  353. break;
  354. case AL_REVERB_LATE_REVERB_GAIN:
  355. if(!(val >= AL_REVERB_MIN_LATE_REVERB_GAIN && val <= AL_REVERB_MAX_LATE_REVERB_GAIN))
  356. throw effect_exception{AL_INVALID_VALUE, "Reverb late reverb gain out of range"};
  357. props->Reverb.LateReverbGain = val;
  358. break;
  359. case AL_REVERB_LATE_REVERB_DELAY:
  360. if(!(val >= AL_REVERB_MIN_LATE_REVERB_DELAY && val <= AL_REVERB_MAX_LATE_REVERB_DELAY))
  361. throw effect_exception{AL_INVALID_VALUE, "Reverb late reverb delay out of range"};
  362. props->Reverb.LateReverbDelay = val;
  363. break;
  364. case AL_REVERB_AIR_ABSORPTION_GAINHF:
  365. if(!(val >= AL_REVERB_MIN_AIR_ABSORPTION_GAINHF && val <= AL_REVERB_MAX_AIR_ABSORPTION_GAINHF))
  366. throw effect_exception{AL_INVALID_VALUE, "Reverb air absorption gainhf out of range"};
  367. props->Reverb.AirAbsorptionGainHF = val;
  368. break;
  369. case AL_REVERB_ROOM_ROLLOFF_FACTOR:
  370. if(!(val >= AL_REVERB_MIN_ROOM_ROLLOFF_FACTOR && val <= AL_REVERB_MAX_ROOM_ROLLOFF_FACTOR))
  371. throw effect_exception{AL_INVALID_VALUE, "Reverb room rolloff factor out of range"};
  372. props->Reverb.RoomRolloffFactor = val;
  373. break;
  374. default:
  375. throw effect_exception{AL_INVALID_ENUM, "Invalid reverb float property 0x%04x", param};
  376. }
  377. }
  378. void StdReverb_setParamfv(EffectProps *props, ALenum param, const float *vals)
  379. { StdReverb_setParamf(props, param, vals[0]); }
  380. void StdReverb_getParami(const EffectProps *props, ALenum param, int *val)
  381. {
  382. switch(param)
  383. {
  384. case AL_REVERB_DECAY_HFLIMIT:
  385. *val = props->Reverb.DecayHFLimit;
  386. break;
  387. default:
  388. throw effect_exception{AL_INVALID_ENUM, "Invalid reverb integer property 0x%04x", param};
  389. }
  390. }
  391. void StdReverb_getParamiv(const EffectProps *props, ALenum param, int *vals)
  392. { StdReverb_getParami(props, param, vals); }
  393. void StdReverb_getParamf(const EffectProps *props, ALenum param, float *val)
  394. {
  395. switch(param)
  396. {
  397. case AL_REVERB_DENSITY:
  398. *val = props->Reverb.Density;
  399. break;
  400. case AL_REVERB_DIFFUSION:
  401. *val = props->Reverb.Diffusion;
  402. break;
  403. case AL_REVERB_GAIN:
  404. *val = props->Reverb.Gain;
  405. break;
  406. case AL_REVERB_GAINHF:
  407. *val = props->Reverb.GainHF;
  408. break;
  409. case AL_REVERB_DECAY_TIME:
  410. *val = props->Reverb.DecayTime;
  411. break;
  412. case AL_REVERB_DECAY_HFRATIO:
  413. *val = props->Reverb.DecayHFRatio;
  414. break;
  415. case AL_REVERB_REFLECTIONS_GAIN:
  416. *val = props->Reverb.ReflectionsGain;
  417. break;
  418. case AL_REVERB_REFLECTIONS_DELAY:
  419. *val = props->Reverb.ReflectionsDelay;
  420. break;
  421. case AL_REVERB_LATE_REVERB_GAIN:
  422. *val = props->Reverb.LateReverbGain;
  423. break;
  424. case AL_REVERB_LATE_REVERB_DELAY:
  425. *val = props->Reverb.LateReverbDelay;
  426. break;
  427. case AL_REVERB_AIR_ABSORPTION_GAINHF:
  428. *val = props->Reverb.AirAbsorptionGainHF;
  429. break;
  430. case AL_REVERB_ROOM_ROLLOFF_FACTOR:
  431. *val = props->Reverb.RoomRolloffFactor;
  432. break;
  433. default:
  434. throw effect_exception{AL_INVALID_ENUM, "Invalid reverb float property 0x%04x", param};
  435. }
  436. }
  437. void StdReverb_getParamfv(const EffectProps *props, ALenum param, float *vals)
  438. { StdReverb_getParamf(props, param, vals); }
  439. EffectProps genDefaultStdProps() noexcept
  440. {
  441. EffectProps props{};
  442. props.Reverb.Density = AL_REVERB_DEFAULT_DENSITY;
  443. props.Reverb.Diffusion = AL_REVERB_DEFAULT_DIFFUSION;
  444. props.Reverb.Gain = AL_REVERB_DEFAULT_GAIN;
  445. props.Reverb.GainHF = AL_REVERB_DEFAULT_GAINHF;
  446. props.Reverb.GainLF = 1.0f;
  447. props.Reverb.DecayTime = AL_REVERB_DEFAULT_DECAY_TIME;
  448. props.Reverb.DecayHFRatio = AL_REVERB_DEFAULT_DECAY_HFRATIO;
  449. props.Reverb.DecayLFRatio = 1.0f;
  450. props.Reverb.ReflectionsGain = AL_REVERB_DEFAULT_REFLECTIONS_GAIN;
  451. props.Reverb.ReflectionsDelay = AL_REVERB_DEFAULT_REFLECTIONS_DELAY;
  452. props.Reverb.ReflectionsPan[0] = 0.0f;
  453. props.Reverb.ReflectionsPan[1] = 0.0f;
  454. props.Reverb.ReflectionsPan[2] = 0.0f;
  455. props.Reverb.LateReverbGain = AL_REVERB_DEFAULT_LATE_REVERB_GAIN;
  456. props.Reverb.LateReverbDelay = AL_REVERB_DEFAULT_LATE_REVERB_DELAY;
  457. props.Reverb.LateReverbPan[0] = 0.0f;
  458. props.Reverb.LateReverbPan[1] = 0.0f;
  459. props.Reverb.LateReverbPan[2] = 0.0f;
  460. props.Reverb.EchoTime = 0.25f;
  461. props.Reverb.EchoDepth = 0.0f;
  462. props.Reverb.ModulationTime = 0.25f;
  463. props.Reverb.ModulationDepth = 0.0f;
  464. props.Reverb.AirAbsorptionGainHF = AL_REVERB_DEFAULT_AIR_ABSORPTION_GAINHF;
  465. props.Reverb.HFReference = 5000.0f;
  466. props.Reverb.LFReference = 250.0f;
  467. props.Reverb.RoomRolloffFactor = AL_REVERB_DEFAULT_ROOM_ROLLOFF_FACTOR;
  468. props.Reverb.DecayHFLimit = AL_REVERB_DEFAULT_DECAY_HFLIMIT;
  469. return props;
  470. }
  471. } // namespace
  472. DEFINE_ALEFFECT_VTABLE(Reverb);
  473. const EffectProps ReverbEffectProps{genDefaultProps()};
  474. DEFINE_ALEFFECT_VTABLE(StdReverb);
  475. const EffectProps StdReverbEffectProps{genDefaultStdProps()};
  476. #ifdef ALSOFT_EAX
  477. namespace {
  478. class EaxReverbEffectException : public EaxException
  479. {
  480. public:
  481. explicit EaxReverbEffectException(const char* message)
  482. : EaxException{"EAX_REVERB_EFFECT", message}
  483. {}
  484. }; // EaxReverbEffectException
  485. class EaxReverbEffect final : public EaxEffect
  486. {
  487. public:
  488. EaxReverbEffect(const EaxCall& call) noexcept;
  489. void dispatch(const EaxCall& call) override;
  490. /*[[nodiscard]]*/ bool commit() override;
  491. private:
  492. static constexpr auto initial_room2 = -10'000L;
  493. using Exception = EaxReverbEffectException;
  494. using Props1 = EAX_REVERBPROPERTIES;
  495. using Props2 = EAX20LISTENERPROPERTIES;
  496. using Props3 = EAXREVERBPROPERTIES;
  497. struct State1
  498. {
  499. Props1 i; // Immediate.
  500. Props1 d; // Deferred.
  501. }; // State1
  502. struct State2
  503. {
  504. Props2 i; // Immediate.
  505. Props2 d; // Deferred.
  506. }; // State2
  507. struct State3
  508. {
  509. Props3 i; // Immediate.
  510. Props3 d; // Deferred.
  511. }; // State3
  512. struct EnvironmentValidator1 {
  513. void operator()(unsigned long ulEnvironment) const
  514. {
  515. eax_validate_range<Exception>(
  516. "Environment",
  517. ulEnvironment,
  518. EAXREVERB_MINENVIRONMENT,
  519. EAX1REVERB_MAXENVIRONMENT);
  520. }
  521. }; // EnvironmentValidator1
  522. struct VolumeValidator {
  523. void operator()(float volume) const
  524. {
  525. eax_validate_range<Exception>(
  526. "Volume",
  527. volume,
  528. EAX1REVERB_MINVOLUME,
  529. EAX1REVERB_MAXVOLUME);
  530. }
  531. }; // VolumeValidator
  532. struct DecayTimeValidator {
  533. void operator()(float flDecayTime) const
  534. {
  535. eax_validate_range<Exception>(
  536. "Decay Time",
  537. flDecayTime,
  538. EAXREVERB_MINDECAYTIME,
  539. EAXREVERB_MAXDECAYTIME);
  540. }
  541. }; // DecayTimeValidator
  542. struct DampingValidator {
  543. void operator()(float damping) const
  544. {
  545. eax_validate_range<Exception>(
  546. "Damping",
  547. damping,
  548. EAX1REVERB_MINDAMPING,
  549. EAX1REVERB_MAXDAMPING);
  550. }
  551. }; // DampingValidator
  552. struct AllValidator1 {
  553. void operator()(const Props1& all) const
  554. {
  555. EnvironmentValidator1{}(all.environment);
  556. VolumeValidator{}(all.fVolume);
  557. DecayTimeValidator{}(all.fDecayTime_sec);
  558. DampingValidator{}(all.fDamping);
  559. }
  560. }; // AllValidator1
  561. struct RoomValidator {
  562. void operator()(long lRoom) const
  563. {
  564. eax_validate_range<Exception>(
  565. "Room",
  566. lRoom,
  567. EAXREVERB_MINROOM,
  568. EAXREVERB_MAXROOM);
  569. }
  570. }; // RoomValidator
  571. struct RoomHFValidator {
  572. void operator()(long lRoomHF) const
  573. {
  574. eax_validate_range<Exception>(
  575. "Room HF",
  576. lRoomHF,
  577. EAXREVERB_MINROOMHF,
  578. EAXREVERB_MAXROOMHF);
  579. }
  580. }; // RoomHFValidator
  581. struct RoomRolloffFactorValidator {
  582. void operator()(float flRoomRolloffFactor) const
  583. {
  584. eax_validate_range<Exception>(
  585. "Room Rolloff Factor",
  586. flRoomRolloffFactor,
  587. EAXREVERB_MINROOMROLLOFFFACTOR,
  588. EAXREVERB_MAXROOMROLLOFFFACTOR);
  589. }
  590. }; // RoomRolloffFactorValidator
  591. struct DecayHFRatioValidator {
  592. void operator()(float flDecayHFRatio) const
  593. {
  594. eax_validate_range<Exception>(
  595. "Decay HF Ratio",
  596. flDecayHFRatio,
  597. EAXREVERB_MINDECAYHFRATIO,
  598. EAXREVERB_MAXDECAYHFRATIO);
  599. }
  600. }; // DecayHFRatioValidator
  601. struct ReflectionsValidator {
  602. void operator()(long lReflections) const
  603. {
  604. eax_validate_range<Exception>(
  605. "Reflections",
  606. lReflections,
  607. EAXREVERB_MINREFLECTIONS,
  608. EAXREVERB_MAXREFLECTIONS);
  609. }
  610. }; // ReflectionsValidator
  611. struct ReflectionsDelayValidator {
  612. void operator()(float flReflectionsDelay) const
  613. {
  614. eax_validate_range<Exception>(
  615. "Reflections Delay",
  616. flReflectionsDelay,
  617. EAXREVERB_MINREFLECTIONSDELAY,
  618. EAXREVERB_MAXREFLECTIONSDELAY);
  619. }
  620. }; // ReflectionsDelayValidator
  621. struct ReverbValidator {
  622. void operator()(long lReverb) const
  623. {
  624. eax_validate_range<Exception>(
  625. "Reverb",
  626. lReverb,
  627. EAXREVERB_MINREVERB,
  628. EAXREVERB_MAXREVERB);
  629. }
  630. }; // ReverbValidator
  631. struct ReverbDelayValidator {
  632. void operator()(float flReverbDelay) const
  633. {
  634. eax_validate_range<Exception>(
  635. "Reverb Delay",
  636. flReverbDelay,
  637. EAXREVERB_MINREVERBDELAY,
  638. EAXREVERB_MAXREVERBDELAY);
  639. }
  640. }; // ReverbDelayValidator
  641. struct EnvironmentSizeValidator {
  642. void operator()(float flEnvironmentSize) const
  643. {
  644. eax_validate_range<Exception>(
  645. "Environment Size",
  646. flEnvironmentSize,
  647. EAXREVERB_MINENVIRONMENTSIZE,
  648. EAXREVERB_MAXENVIRONMENTSIZE);
  649. }
  650. }; // EnvironmentSizeValidator
  651. struct EnvironmentDiffusionValidator {
  652. void operator()(float flEnvironmentDiffusion) const
  653. {
  654. eax_validate_range<Exception>(
  655. "Environment Diffusion",
  656. flEnvironmentDiffusion,
  657. EAXREVERB_MINENVIRONMENTDIFFUSION,
  658. EAXREVERB_MAXENVIRONMENTDIFFUSION);
  659. }
  660. }; // EnvironmentDiffusionValidator
  661. struct AirAbsorptionHFValidator {
  662. void operator()(float flAirAbsorptionHF) const
  663. {
  664. eax_validate_range<Exception>(
  665. "Air Absorbtion HF",
  666. flAirAbsorptionHF,
  667. EAXREVERB_MINAIRABSORPTIONHF,
  668. EAXREVERB_MAXAIRABSORPTIONHF);
  669. }
  670. }; // AirAbsorptionHFValidator
  671. struct FlagsValidator2 {
  672. void operator()(unsigned long ulFlags) const
  673. {
  674. eax_validate_range<Exception>(
  675. "Flags",
  676. ulFlags,
  677. 0UL,
  678. ~EAX2LISTENERFLAGS_RESERVED);
  679. }
  680. }; // FlagsValidator2
  681. struct AllValidator2 {
  682. void operator()(const Props2& all) const
  683. {
  684. RoomValidator{}(all.lRoom);
  685. RoomHFValidator{}(all.lRoomHF);
  686. RoomRolloffFactorValidator{}(all.flRoomRolloffFactor);
  687. DecayTimeValidator{}(all.flDecayTime);
  688. DecayHFRatioValidator{}(all.flDecayHFRatio);
  689. ReflectionsValidator{}(all.lReflections);
  690. ReflectionsDelayValidator{}(all.flReflectionsDelay);
  691. ReverbValidator{}(all.lReverb);
  692. ReverbDelayValidator{}(all.flReverbDelay);
  693. EnvironmentValidator1{}(all.dwEnvironment);
  694. EnvironmentSizeValidator{}(all.flEnvironmentSize);
  695. EnvironmentDiffusionValidator{}(all.flEnvironmentDiffusion);
  696. AirAbsorptionHFValidator{}(all.flAirAbsorptionHF);
  697. FlagsValidator2{}(all.dwFlags);
  698. }
  699. }; // AllValidator2
  700. struct EnvironmentValidator3 {
  701. void operator()(unsigned long ulEnvironment) const
  702. {
  703. eax_validate_range<Exception>(
  704. "Environment",
  705. ulEnvironment,
  706. EAXREVERB_MINENVIRONMENT,
  707. EAX30REVERB_MAXENVIRONMENT);
  708. }
  709. }; // EnvironmentValidator1
  710. struct RoomLFValidator {
  711. void operator()(long lRoomLF) const
  712. {
  713. eax_validate_range<Exception>(
  714. "Room LF",
  715. lRoomLF,
  716. EAXREVERB_MINROOMLF,
  717. EAXREVERB_MAXROOMLF);
  718. }
  719. }; // RoomLFValidator
  720. struct DecayLFRatioValidator {
  721. void operator()(float flDecayLFRatio) const
  722. {
  723. eax_validate_range<Exception>(
  724. "Decay LF Ratio",
  725. flDecayLFRatio,
  726. EAXREVERB_MINDECAYLFRATIO,
  727. EAXREVERB_MAXDECAYLFRATIO);
  728. }
  729. }; // DecayLFRatioValidator
  730. struct VectorValidator {
  731. void operator()(const EAXVECTOR&) const
  732. {}
  733. }; // VectorValidator
  734. struct EchoTimeValidator {
  735. void operator()(float flEchoTime) const
  736. {
  737. eax_validate_range<Exception>(
  738. "Echo Time",
  739. flEchoTime,
  740. EAXREVERB_MINECHOTIME,
  741. EAXREVERB_MAXECHOTIME);
  742. }
  743. }; // EchoTimeValidator
  744. struct EchoDepthValidator {
  745. void operator()(float flEchoDepth) const
  746. {
  747. eax_validate_range<Exception>(
  748. "Echo Depth",
  749. flEchoDepth,
  750. EAXREVERB_MINECHODEPTH,
  751. EAXREVERB_MAXECHODEPTH);
  752. }
  753. }; // EchoDepthValidator
  754. struct ModulationTimeValidator {
  755. void operator()(float flModulationTime) const
  756. {
  757. eax_validate_range<Exception>(
  758. "Modulation Time",
  759. flModulationTime,
  760. EAXREVERB_MINMODULATIONTIME,
  761. EAXREVERB_MAXMODULATIONTIME);
  762. }
  763. }; // ModulationTimeValidator
  764. struct ModulationDepthValidator {
  765. void operator()(float flModulationDepth) const
  766. {
  767. eax_validate_range<Exception>(
  768. "Modulation Depth",
  769. flModulationDepth,
  770. EAXREVERB_MINMODULATIONDEPTH,
  771. EAXREVERB_MAXMODULATIONDEPTH);
  772. }
  773. }; // ModulationDepthValidator
  774. struct HFReferenceValidator {
  775. void operator()(float flHFReference) const
  776. {
  777. eax_validate_range<Exception>(
  778. "HF Reference",
  779. flHFReference,
  780. EAXREVERB_MINHFREFERENCE,
  781. EAXREVERB_MAXHFREFERENCE);
  782. }
  783. }; // HFReferenceValidator
  784. struct LFReferenceValidator {
  785. void operator()(float flLFReference) const
  786. {
  787. eax_validate_range<Exception>(
  788. "LF Reference",
  789. flLFReference,
  790. EAXREVERB_MINLFREFERENCE,
  791. EAXREVERB_MAXLFREFERENCE);
  792. }
  793. }; // LFReferenceValidator
  794. struct FlagsValidator3 {
  795. void operator()(unsigned long ulFlags) const
  796. {
  797. eax_validate_range<Exception>(
  798. "Flags",
  799. ulFlags,
  800. 0UL,
  801. ~EAXREVERBFLAGS_RESERVED);
  802. }
  803. }; // FlagsValidator3
  804. struct AllValidator3 {
  805. void operator()(const Props3& all) const
  806. {
  807. EnvironmentValidator3{}(all.ulEnvironment);
  808. EnvironmentSizeValidator{}(all.flEnvironmentSize);
  809. EnvironmentDiffusionValidator{}(all.flEnvironmentDiffusion);
  810. RoomValidator{}(all.lRoom);
  811. RoomHFValidator{}(all.lRoomHF);
  812. RoomLFValidator{}(all.lRoomLF);
  813. DecayTimeValidator{}(all.flDecayTime);
  814. DecayHFRatioValidator{}(all.flDecayHFRatio);
  815. DecayLFRatioValidator{}(all.flDecayLFRatio);
  816. ReflectionsValidator{}(all.lReflections);
  817. ReflectionsDelayValidator{}(all.flReflectionsDelay);
  818. VectorValidator{}(all.vReflectionsPan);
  819. ReverbValidator{}(all.lReverb);
  820. ReverbDelayValidator{}(all.flReverbDelay);
  821. VectorValidator{}(all.vReverbPan);
  822. EchoTimeValidator{}(all.flEchoTime);
  823. EchoDepthValidator{}(all.flEchoDepth);
  824. ModulationTimeValidator{}(all.flModulationTime);
  825. ModulationDepthValidator{}(all.flModulationDepth);
  826. AirAbsorptionHFValidator{}(all.flAirAbsorptionHF);
  827. HFReferenceValidator{}(all.flHFReference);
  828. LFReferenceValidator{}(all.flLFReference);
  829. RoomRolloffFactorValidator{}(all.flRoomRolloffFactor);
  830. FlagsValidator3{}(all.ulFlags);
  831. }
  832. }; // AllValidator3
  833. struct EnvironmentDeferrer2 {
  834. void operator()(Props2& props, unsigned long dwEnvironment) const
  835. {
  836. props = EAX2REVERB_PRESETS[dwEnvironment];
  837. }
  838. }; // EnvironmentDeferrer2
  839. struct EnvironmentSizeDeferrer2 {
  840. void operator()(Props2& props, float flEnvironmentSize) const
  841. {
  842. if (props.flEnvironmentSize == flEnvironmentSize)
  843. {
  844. return;
  845. }
  846. const auto scale = flEnvironmentSize / props.flEnvironmentSize;
  847. props.flEnvironmentSize = flEnvironmentSize;
  848. if ((props.dwFlags & EAX2LISTENERFLAGS_DECAYTIMESCALE) != 0)
  849. {
  850. props.flDecayTime = clamp(
  851. props.flDecayTime * scale,
  852. EAXREVERB_MINDECAYTIME,
  853. EAXREVERB_MAXDECAYTIME);
  854. }
  855. if ((props.dwFlags & EAX2LISTENERFLAGS_REFLECTIONSSCALE) != 0 &&
  856. (props.dwFlags & EAX2LISTENERFLAGS_REFLECTIONSDELAYSCALE) != 0)
  857. {
  858. props.lReflections = clamp(
  859. props.lReflections - static_cast<long>(gain_to_level_mb(scale)),
  860. EAXREVERB_MINREFLECTIONS,
  861. EAXREVERB_MAXREFLECTIONS);
  862. }
  863. if ((props.dwFlags & EAX2LISTENERFLAGS_REFLECTIONSDELAYSCALE) != 0)
  864. {
  865. props.flReflectionsDelay = clamp(
  866. props.flReflectionsDelay * scale,
  867. EAXREVERB_MINREFLECTIONSDELAY,
  868. EAXREVERB_MAXREFLECTIONSDELAY);
  869. }
  870. if ((props.dwFlags & EAX2LISTENERFLAGS_REVERBSCALE) != 0)
  871. {
  872. const auto log_scalar = ((props.dwFlags & EAXREVERBFLAGS_DECAYTIMESCALE) != 0) ? 2'000.0F : 3'000.0F;
  873. props.lReverb = clamp(
  874. props.lReverb - static_cast<long>(std::log10(scale) * log_scalar),
  875. EAXREVERB_MINREVERB,
  876. EAXREVERB_MAXREVERB);
  877. }
  878. if ((props.dwFlags & EAX2LISTENERFLAGS_REVERBDELAYSCALE) != 0)
  879. {
  880. props.flReverbDelay = clamp(
  881. props.flReverbDelay * scale,
  882. EAXREVERB_MINREVERBDELAY,
  883. EAXREVERB_MAXREVERBDELAY);
  884. }
  885. }
  886. }; // EnvironmentSizeDeferrer2
  887. struct EnvironmentDeferrer3 {
  888. void operator()(Props3& props, unsigned long ulEnvironment) const
  889. {
  890. if (ulEnvironment == EAX_ENVIRONMENT_UNDEFINED)
  891. {
  892. props.ulEnvironment = EAX_ENVIRONMENT_UNDEFINED;
  893. return;
  894. }
  895. props = EAXREVERB_PRESETS[ulEnvironment];
  896. }
  897. }; // EnvironmentDeferrer3
  898. struct EnvironmentSizeDeferrer3 {
  899. void operator()(Props3& props, float flEnvironmentSize) const
  900. {
  901. if (props.flEnvironmentSize == flEnvironmentSize)
  902. {
  903. return;
  904. }
  905. const auto scale = flEnvironmentSize / props.flEnvironmentSize;
  906. props.ulEnvironment = EAX_ENVIRONMENT_UNDEFINED;
  907. props.flEnvironmentSize = flEnvironmentSize;
  908. if ((props.ulFlags & EAXREVERBFLAGS_DECAYTIMESCALE) != 0)
  909. {
  910. props.flDecayTime = clamp(
  911. props.flDecayTime * scale,
  912. EAXREVERB_MINDECAYTIME,
  913. EAXREVERB_MAXDECAYTIME);
  914. }
  915. if ((props.ulFlags & EAXREVERBFLAGS_REFLECTIONSSCALE) != 0 &&
  916. (props.ulFlags & EAXREVERBFLAGS_REFLECTIONSDELAYSCALE) != 0)
  917. {
  918. props.lReflections = clamp(
  919. props.lReflections - static_cast<long>(gain_to_level_mb(scale)),
  920. EAXREVERB_MINREFLECTIONS,
  921. EAXREVERB_MAXREFLECTIONS);
  922. }
  923. if ((props.ulFlags & EAXREVERBFLAGS_REFLECTIONSDELAYSCALE) != 0)
  924. {
  925. props.flReflectionsDelay = clamp(
  926. props.flReflectionsDelay * scale,
  927. EAXREVERB_MINREFLECTIONSDELAY,
  928. EAXREVERB_MAXREFLECTIONSDELAY);
  929. }
  930. if ((props.ulFlags & EAXREVERBFLAGS_REVERBSCALE) != 0)
  931. {
  932. const auto log_scalar = ((props.ulFlags & EAXREVERBFLAGS_DECAYTIMESCALE) != 0) ? 2'000.0F : 3'000.0F;
  933. props.lReverb = clamp(
  934. props.lReverb - static_cast<long>(std::log10(scale) * log_scalar),
  935. EAXREVERB_MINREVERB,
  936. EAXREVERB_MAXREVERB);
  937. }
  938. if ((props.ulFlags & EAXREVERBFLAGS_REVERBDELAYSCALE) != 0)
  939. {
  940. props.flReverbDelay = clamp(
  941. props.flReverbDelay * scale,
  942. EAXREVERB_MINREVERBDELAY,
  943. EAXREVERB_MAXREVERBDELAY);
  944. }
  945. if ((props.ulFlags & EAXREVERBFLAGS_ECHOTIMESCALE) != 0)
  946. {
  947. props.flEchoTime = clamp(
  948. props.flEchoTime * scale,
  949. EAXREVERB_MINECHOTIME,
  950. EAXREVERB_MAXECHOTIME);
  951. }
  952. if ((props.ulFlags & EAXREVERBFLAGS_MODULATIONTIMESCALE) != 0)
  953. {
  954. props.flModulationTime = clamp(
  955. props.flModulationTime * scale,
  956. EAXREVERB_MINMODULATIONTIME,
  957. EAXREVERB_MAXMODULATIONTIME);
  958. }
  959. }
  960. }; // EnvironmentSizeDeferrer3
  961. int version_;
  962. bool changed_{};
  963. Props3 props_{};
  964. State1 state1_{};
  965. State2 state2_{};
  966. State3 state3_{};
  967. State3 state4_{};
  968. State3 state5_{};
  969. [[noreturn]] static void fail(const char* message);
  970. [[noreturn]] static void fail_unknown_property_id();
  971. [[noreturn]] static void fail_unknown_version();
  972. static void set_defaults(State1& state) noexcept;
  973. static void set_defaults(State2& state) noexcept;
  974. static void set_defaults(State3& state) noexcept;
  975. void set_defaults() noexcept;
  976. void set_current_defaults();
  977. void set_efx_density_from_environment_size() noexcept;
  978. void set_efx_diffusion() noexcept;
  979. void set_efx_gain() noexcept;
  980. void set_efx_gain_hf() noexcept;
  981. void set_efx_gain_lf() noexcept;
  982. void set_efx_decay_time() noexcept;
  983. void set_efx_decay_hf_ratio() noexcept;
  984. void set_efx_decay_lf_ratio() noexcept;
  985. void set_efx_reflections_gain() noexcept;
  986. void set_efx_reflections_delay() noexcept;
  987. void set_efx_reflections_pan() noexcept;
  988. void set_efx_late_reverb_gain() noexcept;
  989. void set_efx_late_reverb_delay() noexcept;
  990. void set_efx_late_reverb_pan() noexcept;
  991. void set_efx_echo_time() noexcept;
  992. void set_efx_echo_depth() noexcept;
  993. void set_efx_modulation_time() noexcept;
  994. void set_efx_modulation_depth() noexcept;
  995. void set_efx_air_absorption_gain_hf() noexcept;
  996. void set_efx_hf_reference() noexcept;
  997. void set_efx_lf_reference() noexcept;
  998. void set_efx_room_rolloff_factor() noexcept;
  999. void set_efx_flags() noexcept;
  1000. void set_efx_defaults() noexcept;
  1001. static void get1(const EaxCall& call, const Props1& props);
  1002. static void get2(const EaxCall& call, const Props2& props);
  1003. static void get3(const EaxCall& call, const Props3& props);
  1004. void get(const EaxCall& call);
  1005. template<typename TValidator, typename TProperty>
  1006. static void defer(const EaxCall& call, TProperty& property)
  1007. {
  1008. const auto& value = call.get_value<Exception, const TProperty>();
  1009. TValidator{}(value);
  1010. property = value;
  1011. }
  1012. template<typename TValidator, typename TDeferrer, typename TProperties, typename TProperty>
  1013. static void defer(const EaxCall& call, TProperties& properties, TProperty&)
  1014. {
  1015. const auto& value = call.get_value<Exception, const TProperty>();
  1016. TValidator{}(value);
  1017. TDeferrer{}(properties, value);
  1018. }
  1019. template<typename TValidator, typename TProperty>
  1020. static void defer3(const EaxCall& call, Props3& properties, TProperty& property)
  1021. {
  1022. const auto& value = call.get_value<Exception, const TProperty>();
  1023. TValidator{}(value);
  1024. if (value == property)
  1025. return;
  1026. property = value;
  1027. properties.ulEnvironment = EAX_ENVIRONMENT_UNDEFINED;
  1028. }
  1029. static void set1(const EaxCall& call, Props1& props);
  1030. static void set2(const EaxCall& call, Props2& props);
  1031. static void set3(const EaxCall& call, Props3& props);
  1032. void set(const EaxCall& call);
  1033. static void translate(const Props1& src, Props3& dst) noexcept;
  1034. static void translate(const Props2& src, Props3& dst) noexcept;
  1035. }; // EaxReverbEffect
  1036. EaxReverbEffect::EaxReverbEffect(const EaxCall& call) noexcept
  1037. : EaxEffect{AL_EFFECT_EAXREVERB}, version_{call.get_version()}
  1038. {
  1039. set_defaults();
  1040. set_current_defaults();
  1041. set_efx_defaults();
  1042. }
  1043. void EaxReverbEffect::dispatch(const EaxCall& call)
  1044. {
  1045. call.is_get() ? get(call) : set(call);
  1046. }
  1047. [[noreturn]] void EaxReverbEffect::fail(const char* message)
  1048. {
  1049. throw Exception{message};
  1050. }
  1051. [[noreturn]] void EaxReverbEffect::fail_unknown_property_id()
  1052. {
  1053. fail(EaxEffectErrorMessages::unknown_property_id());
  1054. }
  1055. [[noreturn]] void EaxReverbEffect::fail_unknown_version()
  1056. {
  1057. fail(EaxEffectErrorMessages::unknown_version());
  1058. }
  1059. void EaxReverbEffect::set_defaults(State1& state) noexcept
  1060. {
  1061. state.i = EAX1REVERB_PRESETS[EAX_ENVIRONMENT_GENERIC];
  1062. state.d = state.i;
  1063. }
  1064. void EaxReverbEffect::set_defaults(State2& state) noexcept
  1065. {
  1066. state.i = EAX2REVERB_PRESETS[EAX2_ENVIRONMENT_GENERIC];
  1067. state.i.lRoom = initial_room2;
  1068. state.d = state.i;
  1069. }
  1070. void EaxReverbEffect::set_defaults(State3& state) noexcept
  1071. {
  1072. state.i = EAXREVERB_PRESETS[EAX_ENVIRONMENT_GENERIC];
  1073. state.d = state.i;
  1074. }
  1075. void EaxReverbEffect::set_defaults() noexcept
  1076. {
  1077. set_defaults(state1_);
  1078. set_defaults(state2_);
  1079. set_defaults(state3_);
  1080. state4_ = state3_;
  1081. state5_ = state3_;
  1082. }
  1083. void EaxReverbEffect::set_current_defaults()
  1084. {
  1085. switch (version_)
  1086. {
  1087. case 1: translate(state1_.i, props_); break;
  1088. case 2: translate(state2_.i, props_); break;
  1089. case 3: props_ = state3_.i; break;
  1090. case 4: props_ = state4_.i; break;
  1091. case 5: props_ = state5_.i; break;
  1092. default: fail_unknown_version();
  1093. }
  1094. }
  1095. void EaxReverbEffect::set_efx_density_from_environment_size() noexcept
  1096. {
  1097. const auto size = props_.flEnvironmentSize;
  1098. const auto density = (size * size * size) / 16.0F;
  1099. al_effect_props_.Reverb.Density = clamp(
  1100. density,
  1101. AL_EAXREVERB_MIN_DENSITY,
  1102. AL_EAXREVERB_MAX_DENSITY);
  1103. }
  1104. void EaxReverbEffect::set_efx_diffusion() noexcept
  1105. {
  1106. al_effect_props_.Reverb.Diffusion = clamp(
  1107. props_.flEnvironmentDiffusion,
  1108. AL_EAXREVERB_MIN_DIFFUSION,
  1109. AL_EAXREVERB_MAX_DIFFUSION);
  1110. }
  1111. void EaxReverbEffect::set_efx_gain() noexcept
  1112. {
  1113. al_effect_props_.Reverb.Gain = clamp(
  1114. level_mb_to_gain(static_cast<float>(props_.lRoom)),
  1115. AL_EAXREVERB_MIN_GAIN,
  1116. AL_EAXREVERB_MAX_GAIN);
  1117. }
  1118. void EaxReverbEffect::set_efx_gain_hf() noexcept
  1119. {
  1120. al_effect_props_.Reverb.GainHF = clamp(
  1121. level_mb_to_gain(static_cast<float>(props_.lRoomHF)),
  1122. AL_EAXREVERB_MIN_GAINHF,
  1123. AL_EAXREVERB_MAX_GAINHF);
  1124. }
  1125. void EaxReverbEffect::set_efx_gain_lf() noexcept
  1126. {
  1127. al_effect_props_.Reverb.GainLF = clamp(
  1128. level_mb_to_gain(static_cast<float>(props_.lRoomLF)),
  1129. AL_EAXREVERB_MIN_GAINLF,
  1130. AL_EAXREVERB_MAX_GAINLF);
  1131. }
  1132. void EaxReverbEffect::set_efx_decay_time() noexcept
  1133. {
  1134. al_effect_props_.Reverb.DecayTime = clamp(
  1135. props_.flDecayTime,
  1136. AL_EAXREVERB_MIN_DECAY_TIME,
  1137. AL_EAXREVERB_MAX_DECAY_TIME);
  1138. }
  1139. void EaxReverbEffect::set_efx_decay_hf_ratio() noexcept
  1140. {
  1141. al_effect_props_.Reverb.DecayHFRatio = clamp(
  1142. props_.flDecayHFRatio,
  1143. AL_EAXREVERB_MIN_DECAY_HFRATIO,
  1144. AL_EAXREVERB_MAX_DECAY_HFRATIO);
  1145. }
  1146. void EaxReverbEffect::set_efx_decay_lf_ratio() noexcept
  1147. {
  1148. al_effect_props_.Reverb.DecayLFRatio = clamp(
  1149. props_.flDecayLFRatio,
  1150. AL_EAXREVERB_MIN_DECAY_LFRATIO,
  1151. AL_EAXREVERB_MAX_DECAY_LFRATIO);
  1152. }
  1153. void EaxReverbEffect::set_efx_reflections_gain() noexcept
  1154. {
  1155. al_effect_props_.Reverb.ReflectionsGain = clamp(
  1156. level_mb_to_gain(static_cast<float>(props_.lReflections)),
  1157. AL_EAXREVERB_MIN_REFLECTIONS_GAIN,
  1158. AL_EAXREVERB_MAX_REFLECTIONS_GAIN);
  1159. }
  1160. void EaxReverbEffect::set_efx_reflections_delay() noexcept
  1161. {
  1162. al_effect_props_.Reverb.ReflectionsDelay = clamp(
  1163. props_.flReflectionsDelay,
  1164. AL_EAXREVERB_MIN_REFLECTIONS_DELAY,
  1165. AL_EAXREVERB_MAX_REFLECTIONS_DELAY);
  1166. }
  1167. void EaxReverbEffect::set_efx_reflections_pan() noexcept
  1168. {
  1169. al_effect_props_.Reverb.ReflectionsPan[0] = props_.vReflectionsPan.x;
  1170. al_effect_props_.Reverb.ReflectionsPan[1] = props_.vReflectionsPan.y;
  1171. al_effect_props_.Reverb.ReflectionsPan[2] = props_.vReflectionsPan.z;
  1172. }
  1173. void EaxReverbEffect::set_efx_late_reverb_gain() noexcept
  1174. {
  1175. al_effect_props_.Reverb.LateReverbGain = clamp(
  1176. level_mb_to_gain(static_cast<float>(props_.lReverb)),
  1177. AL_EAXREVERB_MIN_LATE_REVERB_GAIN,
  1178. AL_EAXREVERB_MAX_LATE_REVERB_GAIN);
  1179. }
  1180. void EaxReverbEffect::set_efx_late_reverb_delay() noexcept
  1181. {
  1182. al_effect_props_.Reverb.LateReverbDelay = clamp(
  1183. props_.flReverbDelay,
  1184. AL_EAXREVERB_MIN_LATE_REVERB_DELAY,
  1185. AL_EAXREVERB_MAX_LATE_REVERB_DELAY);
  1186. }
  1187. void EaxReverbEffect::set_efx_late_reverb_pan() noexcept
  1188. {
  1189. al_effect_props_.Reverb.LateReverbPan[0] = props_.vReverbPan.x;
  1190. al_effect_props_.Reverb.LateReverbPan[1] = props_.vReverbPan.y;
  1191. al_effect_props_.Reverb.LateReverbPan[2] = props_.vReverbPan.z;
  1192. }
  1193. void EaxReverbEffect::set_efx_echo_time() noexcept
  1194. {
  1195. al_effect_props_.Reverb.EchoTime = clamp(
  1196. props_.flEchoTime,
  1197. AL_EAXREVERB_MIN_ECHO_TIME,
  1198. AL_EAXREVERB_MAX_ECHO_TIME);
  1199. }
  1200. void EaxReverbEffect::set_efx_echo_depth() noexcept
  1201. {
  1202. al_effect_props_.Reverb.EchoDepth = clamp(
  1203. props_.flEchoDepth,
  1204. AL_EAXREVERB_MIN_ECHO_DEPTH,
  1205. AL_EAXREVERB_MAX_ECHO_DEPTH);
  1206. }
  1207. void EaxReverbEffect::set_efx_modulation_time() noexcept
  1208. {
  1209. al_effect_props_.Reverb.ModulationTime = clamp(
  1210. props_.flModulationTime,
  1211. AL_EAXREVERB_MIN_MODULATION_TIME,
  1212. AL_EAXREVERB_MAX_MODULATION_TIME);
  1213. }
  1214. void EaxReverbEffect::set_efx_modulation_depth() noexcept
  1215. {
  1216. al_effect_props_.Reverb.ModulationDepth = clamp(
  1217. props_.flModulationDepth,
  1218. AL_EAXREVERB_MIN_MODULATION_DEPTH,
  1219. AL_EAXREVERB_MAX_MODULATION_DEPTH);
  1220. }
  1221. void EaxReverbEffect::set_efx_air_absorption_gain_hf() noexcept
  1222. {
  1223. al_effect_props_.Reverb.AirAbsorptionGainHF = clamp(
  1224. level_mb_to_gain(props_.flAirAbsorptionHF),
  1225. AL_EAXREVERB_MIN_AIR_ABSORPTION_GAINHF,
  1226. AL_EAXREVERB_MAX_AIR_ABSORPTION_GAINHF);
  1227. }
  1228. void EaxReverbEffect::set_efx_hf_reference() noexcept
  1229. {
  1230. al_effect_props_.Reverb.HFReference = clamp(
  1231. props_.flHFReference,
  1232. AL_EAXREVERB_MIN_HFREFERENCE,
  1233. AL_EAXREVERB_MAX_HFREFERENCE);
  1234. }
  1235. void EaxReverbEffect::set_efx_lf_reference() noexcept
  1236. {
  1237. al_effect_props_.Reverb.LFReference = clamp(
  1238. props_.flLFReference,
  1239. AL_EAXREVERB_MIN_LFREFERENCE,
  1240. AL_EAXREVERB_MAX_LFREFERENCE);
  1241. }
  1242. void EaxReverbEffect::set_efx_room_rolloff_factor() noexcept
  1243. {
  1244. al_effect_props_.Reverb.RoomRolloffFactor = clamp(
  1245. props_.flRoomRolloffFactor,
  1246. AL_EAXREVERB_MIN_ROOM_ROLLOFF_FACTOR,
  1247. AL_EAXREVERB_MAX_ROOM_ROLLOFF_FACTOR);
  1248. }
  1249. void EaxReverbEffect::set_efx_flags() noexcept
  1250. {
  1251. al_effect_props_.Reverb.DecayHFLimit = ((props_.ulFlags & EAXREVERBFLAGS_DECAYHFLIMIT) != 0);
  1252. }
  1253. void EaxReverbEffect::set_efx_defaults() noexcept
  1254. {
  1255. set_efx_density_from_environment_size();
  1256. set_efx_diffusion();
  1257. set_efx_gain();
  1258. set_efx_gain_hf();
  1259. set_efx_gain_lf();
  1260. set_efx_decay_time();
  1261. set_efx_decay_hf_ratio();
  1262. set_efx_decay_lf_ratio();
  1263. set_efx_reflections_gain();
  1264. set_efx_reflections_delay();
  1265. set_efx_reflections_pan();
  1266. set_efx_late_reverb_gain();
  1267. set_efx_late_reverb_delay();
  1268. set_efx_late_reverb_pan();
  1269. set_efx_echo_time();
  1270. set_efx_echo_depth();
  1271. set_efx_modulation_time();
  1272. set_efx_modulation_depth();
  1273. set_efx_air_absorption_gain_hf();
  1274. set_efx_hf_reference();
  1275. set_efx_lf_reference();
  1276. set_efx_room_rolloff_factor();
  1277. set_efx_flags();
  1278. }
  1279. void EaxReverbEffect::get1(const EaxCall& call, const Props1& props)
  1280. {
  1281. switch(call.get_property_id())
  1282. {
  1283. case DSPROPERTY_EAX_ALL: call.set_value<Exception>(props); break;
  1284. case DSPROPERTY_EAX_ENVIRONMENT: call.set_value<Exception>(props.environment); break;
  1285. case DSPROPERTY_EAX_VOLUME: call.set_value<Exception>(props.fVolume); break;
  1286. case DSPROPERTY_EAX_DECAYTIME: call.set_value<Exception>(props.fDecayTime_sec); break;
  1287. case DSPROPERTY_EAX_DAMPING: call.set_value<Exception>(props.fDamping); break;
  1288. default: fail_unknown_property_id();
  1289. }
  1290. }
  1291. void EaxReverbEffect::get2(const EaxCall& call, const Props2& props)
  1292. {
  1293. switch(call.get_property_id())
  1294. {
  1295. case DSPROPERTY_EAX20LISTENER_NONE: break;
  1296. case DSPROPERTY_EAX20LISTENER_ALLPARAMETERS: call.set_value<Exception>(props); break;
  1297. case DSPROPERTY_EAX20LISTENER_ROOM: call.set_value<Exception>(props.lRoom); break;
  1298. case DSPROPERTY_EAX20LISTENER_ROOMHF: call.set_value<Exception>(props.lRoomHF); break;
  1299. case DSPROPERTY_EAX20LISTENER_ROOMROLLOFFFACTOR: call.set_value<Exception>(props.flRoomRolloffFactor); break;
  1300. case DSPROPERTY_EAX20LISTENER_DECAYTIME: call.set_value<Exception>(props.flDecayTime); break;
  1301. case DSPROPERTY_EAX20LISTENER_DECAYHFRATIO: call.set_value<Exception>(props.flDecayHFRatio); break;
  1302. case DSPROPERTY_EAX20LISTENER_REFLECTIONS: call.set_value<Exception>(props.lReflections); break;
  1303. case DSPROPERTY_EAX20LISTENER_REFLECTIONSDELAY: call.set_value<Exception>(props.flReverbDelay); break;
  1304. case DSPROPERTY_EAX20LISTENER_REVERB: call.set_value<Exception>(props.lReverb); break;
  1305. case DSPROPERTY_EAX20LISTENER_REVERBDELAY: call.set_value<Exception>(props.flReverbDelay); break;
  1306. case DSPROPERTY_EAX20LISTENER_ENVIRONMENT: call.set_value<Exception>(props.dwEnvironment); break;
  1307. case DSPROPERTY_EAX20LISTENER_ENVIRONMENTSIZE: call.set_value<Exception>(props.flEnvironmentSize); break;
  1308. case DSPROPERTY_EAX20LISTENER_ENVIRONMENTDIFFUSION: call.set_value<Exception>(props.flEnvironmentDiffusion); break;
  1309. case DSPROPERTY_EAX20LISTENER_AIRABSORPTIONHF: call.set_value<Exception>(props.flAirAbsorptionHF); break;
  1310. case DSPROPERTY_EAX20LISTENER_FLAGS: call.set_value<Exception>(props.dwFlags); break;
  1311. default: fail_unknown_property_id();
  1312. }
  1313. }
  1314. void EaxReverbEffect::get3(const EaxCall& call, const Props3& props)
  1315. {
  1316. switch(call.get_property_id())
  1317. {
  1318. case EAXREVERB_NONE: break;
  1319. case EAXREVERB_ALLPARAMETERS: call.set_value<Exception>(props); break;
  1320. case EAXREVERB_ENVIRONMENT: call.set_value<Exception>(props.ulEnvironment); break;
  1321. case EAXREVERB_ENVIRONMENTSIZE: call.set_value<Exception>(props.flEnvironmentSize); break;
  1322. case EAXREVERB_ENVIRONMENTDIFFUSION: call.set_value<Exception>(props.flEnvironmentDiffusion); break;
  1323. case EAXREVERB_ROOM: call.set_value<Exception>(props.lRoom); break;
  1324. case EAXREVERB_ROOMHF: call.set_value<Exception>(props.lRoomHF); break;
  1325. case EAXREVERB_ROOMLF: call.set_value<Exception>(props.lRoomLF); break;
  1326. case EAXREVERB_DECAYTIME: call.set_value<Exception>(props.flDecayTime); break;
  1327. case EAXREVERB_DECAYHFRATIO: call.set_value<Exception>(props.flDecayHFRatio); break;
  1328. case EAXREVERB_DECAYLFRATIO: call.set_value<Exception>(props.flDecayLFRatio); break;
  1329. case EAXREVERB_REFLECTIONS: call.set_value<Exception>(props.lReflections); break;
  1330. case EAXREVERB_REFLECTIONSDELAY: call.set_value<Exception>(props.flReflectionsDelay); break;
  1331. case EAXREVERB_REFLECTIONSPAN: call.set_value<Exception>(props.vReflectionsPan); break;
  1332. case EAXREVERB_REVERB: call.set_value<Exception>(props.lReverb); break;
  1333. case EAXREVERB_REVERBDELAY: call.set_value<Exception>(props.flReverbDelay); break;
  1334. case EAXREVERB_REVERBPAN: call.set_value<Exception>(props.vReverbPan); break;
  1335. case EAXREVERB_ECHOTIME: call.set_value<Exception>(props.flEchoTime); break;
  1336. case EAXREVERB_ECHODEPTH: call.set_value<Exception>(props.flEchoDepth); break;
  1337. case EAXREVERB_MODULATIONTIME: call.set_value<Exception>(props.flModulationTime); break;
  1338. case EAXREVERB_MODULATIONDEPTH: call.set_value<Exception>(props.flModulationDepth); break;
  1339. case EAXREVERB_AIRABSORPTIONHF: call.set_value<Exception>(props.flAirAbsorptionHF); break;
  1340. case EAXREVERB_HFREFERENCE: call.set_value<Exception>(props.flHFReference); break;
  1341. case EAXREVERB_LFREFERENCE: call.set_value<Exception>(props.flLFReference); break;
  1342. case EAXREVERB_ROOMROLLOFFFACTOR: call.set_value<Exception>(props.flRoomRolloffFactor); break;
  1343. case EAXREVERB_FLAGS: call.set_value<Exception>(props.ulFlags); break;
  1344. default: fail_unknown_property_id();
  1345. }
  1346. }
  1347. void EaxReverbEffect::get(const EaxCall& call)
  1348. {
  1349. switch(call.get_version())
  1350. {
  1351. case 1: get1(call, state1_.i); break;
  1352. case 2: get2(call, state2_.i); break;
  1353. case 3: get3(call, state3_.i); break;
  1354. case 4: get3(call, state4_.i); break;
  1355. case 5: get3(call, state5_.i); break;
  1356. default: fail_unknown_version();
  1357. }
  1358. }
  1359. /*[[nodiscard]]*/ bool EaxReverbEffect::commit()
  1360. {
  1361. if(!changed_)
  1362. return false;
  1363. changed_ = false;
  1364. const auto props = props_;
  1365. switch(version_)
  1366. {
  1367. case 1:
  1368. state1_.i = state1_.d;
  1369. translate(state1_.d, props_);
  1370. break;
  1371. case 2:
  1372. state2_.i = state2_.d;
  1373. translate(state2_.d, props_);
  1374. break;
  1375. case 3:
  1376. state3_.i = state3_.d;
  1377. props_ = state3_.d;
  1378. break;
  1379. case 4:
  1380. state4_.i = state4_.d;
  1381. props_ = state4_.d;
  1382. break;
  1383. case 5:
  1384. state5_.i = state5_.d;
  1385. props_ = state5_.d;
  1386. break;
  1387. default:
  1388. fail_unknown_version();
  1389. }
  1390. auto is_dirty = false;
  1391. if (props_.flEnvironmentSize != props.flEnvironmentSize)
  1392. {
  1393. is_dirty = true;
  1394. set_efx_density_from_environment_size();
  1395. }
  1396. if (props_.flEnvironmentDiffusion != props.flEnvironmentDiffusion)
  1397. {
  1398. is_dirty = true;
  1399. set_efx_diffusion();
  1400. }
  1401. if (props_.lRoom != props.lRoom)
  1402. {
  1403. is_dirty = true;
  1404. set_efx_gain();
  1405. }
  1406. if (props_.lRoomHF != props.lRoomHF)
  1407. {
  1408. is_dirty = true;
  1409. set_efx_gain_hf();
  1410. }
  1411. if (props_.lRoomLF != props.lRoomLF)
  1412. {
  1413. is_dirty = true;
  1414. set_efx_gain_lf();
  1415. }
  1416. if (props_.flDecayTime != props.flDecayTime)
  1417. {
  1418. is_dirty = true;
  1419. set_efx_decay_time();
  1420. }
  1421. if (props_.flDecayHFRatio != props.flDecayHFRatio)
  1422. {
  1423. is_dirty = true;
  1424. set_efx_decay_hf_ratio();
  1425. }
  1426. if (props_.flDecayLFRatio != props.flDecayLFRatio)
  1427. {
  1428. is_dirty = true;
  1429. set_efx_decay_lf_ratio();
  1430. }
  1431. if (props_.lReflections != props.lReflections)
  1432. {
  1433. is_dirty = true;
  1434. set_efx_reflections_gain();
  1435. }
  1436. if (props_.flReflectionsDelay != props.flReflectionsDelay)
  1437. {
  1438. is_dirty = true;
  1439. set_efx_reflections_delay();
  1440. }
  1441. if (props_.vReflectionsPan != props.vReflectionsPan)
  1442. {
  1443. is_dirty = true;
  1444. set_efx_reflections_pan();
  1445. }
  1446. if (props_.lReverb != props.lReverb)
  1447. {
  1448. is_dirty = true;
  1449. set_efx_late_reverb_gain();
  1450. }
  1451. if (props_.flReverbDelay != props.flReverbDelay)
  1452. {
  1453. is_dirty = true;
  1454. set_efx_late_reverb_delay();
  1455. }
  1456. if (props_.vReverbPan != props.vReverbPan)
  1457. {
  1458. is_dirty = true;
  1459. set_efx_late_reverb_pan();
  1460. }
  1461. if (props_.flEchoTime != props.flEchoTime)
  1462. {
  1463. is_dirty = true;
  1464. set_efx_echo_time();
  1465. }
  1466. if (props_.flEchoDepth != props.flEchoDepth)
  1467. {
  1468. is_dirty = true;
  1469. set_efx_echo_depth();
  1470. }
  1471. if (props_.flModulationTime != props.flModulationTime)
  1472. {
  1473. is_dirty = true;
  1474. set_efx_modulation_time();
  1475. }
  1476. if (props_.flModulationDepth != props.flModulationDepth)
  1477. {
  1478. is_dirty = true;
  1479. set_efx_modulation_depth();
  1480. }
  1481. if (props_.flAirAbsorptionHF != props.flAirAbsorptionHF)
  1482. {
  1483. is_dirty = true;
  1484. set_efx_air_absorption_gain_hf();
  1485. }
  1486. if (props_.flHFReference != props.flHFReference)
  1487. {
  1488. is_dirty = true;
  1489. set_efx_hf_reference();
  1490. }
  1491. if (props_.flLFReference != props.flLFReference)
  1492. {
  1493. is_dirty = true;
  1494. set_efx_lf_reference();
  1495. }
  1496. if (props_.flRoomRolloffFactor != props.flRoomRolloffFactor)
  1497. {
  1498. is_dirty = true;
  1499. set_efx_room_rolloff_factor();
  1500. }
  1501. if (props_.ulFlags != props.ulFlags)
  1502. {
  1503. is_dirty = true;
  1504. set_efx_flags();
  1505. }
  1506. return is_dirty;
  1507. }
  1508. void EaxReverbEffect::set1(const EaxCall& call, Props1& props)
  1509. {
  1510. switch (call.get_property_id())
  1511. {
  1512. case DSPROPERTY_EAX_ALL: defer<AllValidator1>(call, props); break;
  1513. case DSPROPERTY_EAX_ENVIRONMENT: defer<EnvironmentValidator1>(call, props.environment); break;
  1514. case DSPROPERTY_EAX_VOLUME: defer<VolumeValidator>(call, props.fVolume); break;
  1515. case DSPROPERTY_EAX_DECAYTIME: defer<DecayTimeValidator>(call, props.fDecayTime_sec); break;
  1516. case DSPROPERTY_EAX_DAMPING: defer<DampingValidator>(call, props.fDamping); break;
  1517. default: fail_unknown_property_id();
  1518. }
  1519. }
  1520. void EaxReverbEffect::set2(const EaxCall& call, Props2& props)
  1521. {
  1522. switch (call.get_property_id())
  1523. {
  1524. case DSPROPERTY_EAX20LISTENER_NONE:
  1525. break;
  1526. case DSPROPERTY_EAX20LISTENER_ALLPARAMETERS:
  1527. defer<AllValidator2>(call, props);
  1528. break;
  1529. case DSPROPERTY_EAX20LISTENER_ROOM:
  1530. defer<RoomValidator>(call, props.lRoom);
  1531. break;
  1532. case DSPROPERTY_EAX20LISTENER_ROOMHF:
  1533. defer<RoomHFValidator>(call, props.lRoomHF);
  1534. break;
  1535. case DSPROPERTY_EAX20LISTENER_ROOMROLLOFFFACTOR:
  1536. defer<RoomRolloffFactorValidator>(call, props.flRoomRolloffFactor);
  1537. break;
  1538. case DSPROPERTY_EAX20LISTENER_DECAYTIME:
  1539. defer<DecayTimeValidator>(call, props.flDecayTime);
  1540. break;
  1541. case DSPROPERTY_EAX20LISTENER_DECAYHFRATIO:
  1542. defer<DecayHFRatioValidator>(call, props.flDecayHFRatio);
  1543. break;
  1544. case DSPROPERTY_EAX20LISTENER_REFLECTIONS:
  1545. defer<ReflectionsValidator>(call, props.lReflections);
  1546. break;
  1547. case DSPROPERTY_EAX20LISTENER_REFLECTIONSDELAY:
  1548. defer<ReflectionsDelayValidator>(call, props.flReverbDelay);
  1549. break;
  1550. case DSPROPERTY_EAX20LISTENER_REVERB:
  1551. defer<ReverbValidator>(call, props.lReverb);
  1552. break;
  1553. case DSPROPERTY_EAX20LISTENER_REVERBDELAY:
  1554. defer<ReverbDelayValidator>(call, props.flReverbDelay);
  1555. break;
  1556. case DSPROPERTY_EAX20LISTENER_ENVIRONMENT:
  1557. defer<EnvironmentValidator1, EnvironmentDeferrer2>(call, props, props.dwEnvironment);
  1558. break;
  1559. case DSPROPERTY_EAX20LISTENER_ENVIRONMENTSIZE:
  1560. defer<EnvironmentSizeValidator, EnvironmentSizeDeferrer2>(call, props, props.flEnvironmentSize);
  1561. break;
  1562. case DSPROPERTY_EAX20LISTENER_ENVIRONMENTDIFFUSION:
  1563. defer<EnvironmentDiffusionValidator>(call, props.flEnvironmentDiffusion);
  1564. break;
  1565. case DSPROPERTY_EAX20LISTENER_AIRABSORPTIONHF:
  1566. defer<AirAbsorptionHFValidator>(call, props.flAirAbsorptionHF);
  1567. break;
  1568. case DSPROPERTY_EAX20LISTENER_FLAGS:
  1569. defer<FlagsValidator2>(call, props.dwFlags);
  1570. break;
  1571. default:
  1572. fail_unknown_property_id();
  1573. }
  1574. }
  1575. void EaxReverbEffect::set3(const EaxCall& call, Props3& props)
  1576. {
  1577. switch(call.get_property_id())
  1578. {
  1579. case EAXREVERB_NONE:
  1580. break;
  1581. case EAXREVERB_ALLPARAMETERS:
  1582. defer<AllValidator3>(call, props);
  1583. break;
  1584. case EAXREVERB_ENVIRONMENT:
  1585. defer<EnvironmentValidator3, EnvironmentDeferrer3>(call, props, props.ulEnvironment);
  1586. break;
  1587. case EAXREVERB_ENVIRONMENTSIZE:
  1588. defer<EnvironmentSizeValidator, EnvironmentSizeDeferrer3>(call, props, props.flEnvironmentSize);
  1589. break;
  1590. case EAXREVERB_ENVIRONMENTDIFFUSION:
  1591. defer3<EnvironmentDiffusionValidator>(call, props, props.flEnvironmentDiffusion);
  1592. break;
  1593. case EAXREVERB_ROOM:
  1594. defer3<RoomValidator>(call, props, props.lRoom);
  1595. break;
  1596. case EAXREVERB_ROOMHF:
  1597. defer3<RoomHFValidator>(call, props, props.lRoomHF);
  1598. break;
  1599. case EAXREVERB_ROOMLF:
  1600. defer3<RoomLFValidator>(call, props, props.lRoomLF);
  1601. break;
  1602. case EAXREVERB_DECAYTIME:
  1603. defer3<DecayTimeValidator>(call, props, props.flDecayTime);
  1604. break;
  1605. case EAXREVERB_DECAYHFRATIO:
  1606. defer3<DecayHFRatioValidator>(call, props, props.flDecayHFRatio);
  1607. break;
  1608. case EAXREVERB_DECAYLFRATIO:
  1609. defer3<DecayLFRatioValidator>(call, props, props.flDecayLFRatio);
  1610. break;
  1611. case EAXREVERB_REFLECTIONS:
  1612. defer3<ReflectionsValidator>(call, props, props.lReflections);
  1613. break;
  1614. case EAXREVERB_REFLECTIONSDELAY:
  1615. defer3<ReflectionsDelayValidator>(call, props, props.flReflectionsDelay);
  1616. break;
  1617. case EAXREVERB_REFLECTIONSPAN:
  1618. defer3<VectorValidator>(call, props, props.vReflectionsPan);
  1619. break;
  1620. case EAXREVERB_REVERB:
  1621. defer3<ReverbValidator>(call, props, props.lReverb);
  1622. break;
  1623. case EAXREVERB_REVERBDELAY:
  1624. defer3<ReverbDelayValidator>(call, props, props.flReverbDelay);
  1625. break;
  1626. case EAXREVERB_REVERBPAN:
  1627. defer3<VectorValidator>(call, props, props.vReverbPan);
  1628. break;
  1629. case EAXREVERB_ECHOTIME:
  1630. defer3<EchoTimeValidator>(call, props, props.flEchoTime);
  1631. break;
  1632. case EAXREVERB_ECHODEPTH:
  1633. defer3<EchoDepthValidator>(call, props, props.flEchoDepth);
  1634. break;
  1635. case EAXREVERB_MODULATIONTIME:
  1636. defer3<ModulationTimeValidator>(call, props, props.flModulationTime);
  1637. break;
  1638. case EAXREVERB_MODULATIONDEPTH:
  1639. defer3<ModulationDepthValidator>(call, props, props.flModulationDepth);
  1640. break;
  1641. case EAXREVERB_AIRABSORPTIONHF:
  1642. defer3<AirAbsorptionHFValidator>(call, props, props.flAirAbsorptionHF);
  1643. break;
  1644. case EAXREVERB_HFREFERENCE:
  1645. defer3<HFReferenceValidator>(call, props, props.flHFReference);
  1646. break;
  1647. case EAXREVERB_LFREFERENCE:
  1648. defer3<LFReferenceValidator>(call, props, props.flLFReference);
  1649. break;
  1650. case EAXREVERB_ROOMROLLOFFFACTOR:
  1651. defer3<RoomRolloffFactorValidator>(call, props, props.flRoomRolloffFactor);
  1652. break;
  1653. case EAXREVERB_FLAGS:
  1654. defer3<FlagsValidator3>(call, props, props.ulFlags);
  1655. break;
  1656. default:
  1657. fail_unknown_property_id();
  1658. }
  1659. }
  1660. void EaxReverbEffect::set(const EaxCall& call)
  1661. {
  1662. const auto version = call.get_version();
  1663. switch(version)
  1664. {
  1665. case 1: set1(call, state1_.d); break;
  1666. case 2: set2(call, state2_.d); break;
  1667. case 3: set3(call, state3_.d); break;
  1668. case 4: set3(call, state4_.d); break;
  1669. case 5: set3(call, state5_.d); break;
  1670. default: fail_unknown_version();
  1671. }
  1672. changed_ = true;
  1673. version_ = version;
  1674. }
  1675. void EaxReverbEffect::translate(const Props1& src, Props3& dst) noexcept
  1676. {
  1677. assert(src.environment <= EAX1REVERB_MAXENVIRONMENT);
  1678. dst = EAXREVERB_PRESETS[src.environment];
  1679. dst.flDecayTime = src.fDecayTime_sec;
  1680. dst.flDecayHFRatio = src.fDamping;
  1681. dst.lReverb = mini(static_cast<int>(gain_to_level_mb(src.fVolume)), 0);
  1682. }
  1683. void EaxReverbEffect::translate(const Props2& src, Props3& dst) noexcept
  1684. {
  1685. assert(src.dwEnvironment <= EAX1REVERB_MAXENVIRONMENT);
  1686. const auto& env = EAXREVERB_PRESETS[src.dwEnvironment];
  1687. dst.ulEnvironment = src.dwEnvironment;
  1688. dst.flEnvironmentSize = src.flEnvironmentSize;
  1689. dst.flEnvironmentDiffusion = src.flEnvironmentDiffusion;
  1690. dst.lRoom = src.lRoom;
  1691. dst.lRoomHF = src.lRoomHF;
  1692. dst.lRoomLF = env.lRoomLF;
  1693. dst.flDecayTime = src.flDecayTime;
  1694. dst.flDecayHFRatio = src.flDecayHFRatio;
  1695. dst.flDecayLFRatio = env.flDecayLFRatio;
  1696. dst.lReflections = src.lReflections;
  1697. dst.flReflectionsDelay = src.flReflectionsDelay;
  1698. dst.vReflectionsPan = env.vReflectionsPan;
  1699. dst.lReverb = src.lReverb;
  1700. dst.flReverbDelay = src.flReverbDelay;
  1701. dst.vReverbPan = env.vReverbPan;
  1702. dst.flEchoTime = env.flEchoTime;
  1703. dst.flEchoDepth = env.flEchoDepth;
  1704. dst.flModulationTime = env.flModulationTime;
  1705. dst.flModulationDepth = env.flModulationDepth;
  1706. dst.flAirAbsorptionHF = src.flAirAbsorptionHF;
  1707. dst.flHFReference = env.flHFReference;
  1708. dst.flLFReference = env.flLFReference;
  1709. dst.flRoomRolloffFactor = src.flRoomRolloffFactor;
  1710. dst.ulFlags = src.dwFlags;
  1711. }
  1712. } // namespace
  1713. EaxEffectUPtr eax_create_eax_reverb_effect(const EaxCall& call)
  1714. {
  1715. return std::make_unique<EaxReverbEffect>(call);
  1716. }
  1717. #endif // ALSOFT_EAX