🛠️🐜 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.

921 lines
25 KiB

  1. #include "config.h"
  2. #include "AL/al.h"
  3. #include "AL/efx.h"
  4. #include "alc/effects/base.h"
  5. #include "effects.h"
  6. #ifdef ALSOFT_EAX
  7. #include "alnumeric.h"
  8. #include "al/eax_exception.h"
  9. #include "al/eax_utils.h"
  10. #endif // ALSOFT_EAX
  11. namespace {
  12. void Equalizer_setParami(EffectProps*, ALenum param, int)
  13. { throw effect_exception{AL_INVALID_ENUM, "Invalid equalizer integer property 0x%04x", param}; }
  14. void Equalizer_setParamiv(EffectProps*, ALenum param, const int*)
  15. {
  16. throw effect_exception{AL_INVALID_ENUM, "Invalid equalizer integer-vector property 0x%04x",
  17. param};
  18. }
  19. void Equalizer_setParamf(EffectProps *props, ALenum param, float val)
  20. {
  21. switch(param)
  22. {
  23. case AL_EQUALIZER_LOW_GAIN:
  24. if(!(val >= AL_EQUALIZER_MIN_LOW_GAIN && val <= AL_EQUALIZER_MAX_LOW_GAIN))
  25. throw effect_exception{AL_INVALID_VALUE, "Equalizer low-band gain out of range"};
  26. props->Equalizer.LowGain = val;
  27. break;
  28. case AL_EQUALIZER_LOW_CUTOFF:
  29. if(!(val >= AL_EQUALIZER_MIN_LOW_CUTOFF && val <= AL_EQUALIZER_MAX_LOW_CUTOFF))
  30. throw effect_exception{AL_INVALID_VALUE, "Equalizer low-band cutoff out of range"};
  31. props->Equalizer.LowCutoff = val;
  32. break;
  33. case AL_EQUALIZER_MID1_GAIN:
  34. if(!(val >= AL_EQUALIZER_MIN_MID1_GAIN && val <= AL_EQUALIZER_MAX_MID1_GAIN))
  35. throw effect_exception{AL_INVALID_VALUE, "Equalizer mid1-band gain out of range"};
  36. props->Equalizer.Mid1Gain = val;
  37. break;
  38. case AL_EQUALIZER_MID1_CENTER:
  39. if(!(val >= AL_EQUALIZER_MIN_MID1_CENTER && val <= AL_EQUALIZER_MAX_MID1_CENTER))
  40. throw effect_exception{AL_INVALID_VALUE, "Equalizer mid1-band center out of range"};
  41. props->Equalizer.Mid1Center = val;
  42. break;
  43. case AL_EQUALIZER_MID1_WIDTH:
  44. if(!(val >= AL_EQUALIZER_MIN_MID1_WIDTH && val <= AL_EQUALIZER_MAX_MID1_WIDTH))
  45. throw effect_exception{AL_INVALID_VALUE, "Equalizer mid1-band width out of range"};
  46. props->Equalizer.Mid1Width = val;
  47. break;
  48. case AL_EQUALIZER_MID2_GAIN:
  49. if(!(val >= AL_EQUALIZER_MIN_MID2_GAIN && val <= AL_EQUALIZER_MAX_MID2_GAIN))
  50. throw effect_exception{AL_INVALID_VALUE, "Equalizer mid2-band gain out of range"};
  51. props->Equalizer.Mid2Gain = val;
  52. break;
  53. case AL_EQUALIZER_MID2_CENTER:
  54. if(!(val >= AL_EQUALIZER_MIN_MID2_CENTER && val <= AL_EQUALIZER_MAX_MID2_CENTER))
  55. throw effect_exception{AL_INVALID_VALUE, "Equalizer mid2-band center out of range"};
  56. props->Equalizer.Mid2Center = val;
  57. break;
  58. case AL_EQUALIZER_MID2_WIDTH:
  59. if(!(val >= AL_EQUALIZER_MIN_MID2_WIDTH && val <= AL_EQUALIZER_MAX_MID2_WIDTH))
  60. throw effect_exception{AL_INVALID_VALUE, "Equalizer mid2-band width out of range"};
  61. props->Equalizer.Mid2Width = val;
  62. break;
  63. case AL_EQUALIZER_HIGH_GAIN:
  64. if(!(val >= AL_EQUALIZER_MIN_HIGH_GAIN && val <= AL_EQUALIZER_MAX_HIGH_GAIN))
  65. throw effect_exception{AL_INVALID_VALUE, "Equalizer high-band gain out of range"};
  66. props->Equalizer.HighGain = val;
  67. break;
  68. case AL_EQUALIZER_HIGH_CUTOFF:
  69. if(!(val >= AL_EQUALIZER_MIN_HIGH_CUTOFF && val <= AL_EQUALIZER_MAX_HIGH_CUTOFF))
  70. throw effect_exception{AL_INVALID_VALUE, "Equalizer high-band cutoff out of range"};
  71. props->Equalizer.HighCutoff = val;
  72. break;
  73. default:
  74. throw effect_exception{AL_INVALID_ENUM, "Invalid equalizer float property 0x%04x", param};
  75. }
  76. }
  77. void Equalizer_setParamfv(EffectProps *props, ALenum param, const float *vals)
  78. { Equalizer_setParamf(props, param, vals[0]); }
  79. void Equalizer_getParami(const EffectProps*, ALenum param, int*)
  80. { throw effect_exception{AL_INVALID_ENUM, "Invalid equalizer integer property 0x%04x", param}; }
  81. void Equalizer_getParamiv(const EffectProps*, ALenum param, int*)
  82. {
  83. throw effect_exception{AL_INVALID_ENUM, "Invalid equalizer integer-vector property 0x%04x",
  84. param};
  85. }
  86. void Equalizer_getParamf(const EffectProps *props, ALenum param, float *val)
  87. {
  88. switch(param)
  89. {
  90. case AL_EQUALIZER_LOW_GAIN:
  91. *val = props->Equalizer.LowGain;
  92. break;
  93. case AL_EQUALIZER_LOW_CUTOFF:
  94. *val = props->Equalizer.LowCutoff;
  95. break;
  96. case AL_EQUALIZER_MID1_GAIN:
  97. *val = props->Equalizer.Mid1Gain;
  98. break;
  99. case AL_EQUALIZER_MID1_CENTER:
  100. *val = props->Equalizer.Mid1Center;
  101. break;
  102. case AL_EQUALIZER_MID1_WIDTH:
  103. *val = props->Equalizer.Mid1Width;
  104. break;
  105. case AL_EQUALIZER_MID2_GAIN:
  106. *val = props->Equalizer.Mid2Gain;
  107. break;
  108. case AL_EQUALIZER_MID2_CENTER:
  109. *val = props->Equalizer.Mid2Center;
  110. break;
  111. case AL_EQUALIZER_MID2_WIDTH:
  112. *val = props->Equalizer.Mid2Width;
  113. break;
  114. case AL_EQUALIZER_HIGH_GAIN:
  115. *val = props->Equalizer.HighGain;
  116. break;
  117. case AL_EQUALIZER_HIGH_CUTOFF:
  118. *val = props->Equalizer.HighCutoff;
  119. break;
  120. default:
  121. throw effect_exception{AL_INVALID_ENUM, "Invalid equalizer float property 0x%04x", param};
  122. }
  123. }
  124. void Equalizer_getParamfv(const EffectProps *props, ALenum param, float *vals)
  125. { Equalizer_getParamf(props, param, vals); }
  126. EffectProps genDefaultProps() noexcept
  127. {
  128. EffectProps props{};
  129. props.Equalizer.LowCutoff = AL_EQUALIZER_DEFAULT_LOW_CUTOFF;
  130. props.Equalizer.LowGain = AL_EQUALIZER_DEFAULT_LOW_GAIN;
  131. props.Equalizer.Mid1Center = AL_EQUALIZER_DEFAULT_MID1_CENTER;
  132. props.Equalizer.Mid1Gain = AL_EQUALIZER_DEFAULT_MID1_GAIN;
  133. props.Equalizer.Mid1Width = AL_EQUALIZER_DEFAULT_MID1_WIDTH;
  134. props.Equalizer.Mid2Center = AL_EQUALIZER_DEFAULT_MID2_CENTER;
  135. props.Equalizer.Mid2Gain = AL_EQUALIZER_DEFAULT_MID2_GAIN;
  136. props.Equalizer.Mid2Width = AL_EQUALIZER_DEFAULT_MID2_WIDTH;
  137. props.Equalizer.HighCutoff = AL_EQUALIZER_DEFAULT_HIGH_CUTOFF;
  138. props.Equalizer.HighGain = AL_EQUALIZER_DEFAULT_HIGH_GAIN;
  139. return props;
  140. }
  141. } // namespace
  142. DEFINE_ALEFFECT_VTABLE(Equalizer);
  143. const EffectProps EqualizerEffectProps{genDefaultProps()};
  144. #ifdef ALSOFT_EAX
  145. namespace {
  146. using EaxEqualizerEffectDirtyFlagsValue = std::uint_least16_t;
  147. struct EaxEqualizerEffectDirtyFlags
  148. {
  149. using EaxIsBitFieldStruct = bool;
  150. EaxEqualizerEffectDirtyFlagsValue lLowGain : 1;
  151. EaxEqualizerEffectDirtyFlagsValue flLowCutOff : 1;
  152. EaxEqualizerEffectDirtyFlagsValue lMid1Gain : 1;
  153. EaxEqualizerEffectDirtyFlagsValue flMid1Center : 1;
  154. EaxEqualizerEffectDirtyFlagsValue flMid1Width : 1;
  155. EaxEqualizerEffectDirtyFlagsValue lMid2Gain : 1;
  156. EaxEqualizerEffectDirtyFlagsValue flMid2Center : 1;
  157. EaxEqualizerEffectDirtyFlagsValue flMid2Width : 1;
  158. EaxEqualizerEffectDirtyFlagsValue lHighGain : 1;
  159. EaxEqualizerEffectDirtyFlagsValue flHighCutOff : 1;
  160. }; // EaxEqualizerEffectDirtyFlags
  161. class EaxEqualizerEffect final :
  162. public EaxEffect
  163. {
  164. public:
  165. EaxEqualizerEffect();
  166. void dispatch(const EaxEaxCall& eax_call) override;
  167. // [[nodiscard]]
  168. bool apply_deferred() override;
  169. private:
  170. EAXEQUALIZERPROPERTIES eax_{};
  171. EAXEQUALIZERPROPERTIES eax_d_{};
  172. EaxEqualizerEffectDirtyFlags eax_dirty_flags_{};
  173. void set_eax_defaults();
  174. void set_efx_low_gain();
  175. void set_efx_low_cutoff();
  176. void set_efx_mid1_gain();
  177. void set_efx_mid1_center();
  178. void set_efx_mid1_width();
  179. void set_efx_mid2_gain();
  180. void set_efx_mid2_center();
  181. void set_efx_mid2_width();
  182. void set_efx_high_gain();
  183. void set_efx_high_cutoff();
  184. void set_efx_defaults();
  185. void get(const EaxEaxCall& eax_call);
  186. void validate_low_gain(long lLowGain);
  187. void validate_low_cutoff(float flLowCutOff);
  188. void validate_mid1_gain(long lMid1Gain);
  189. void validate_mid1_center(float flMid1Center);
  190. void validate_mid1_width(float flMid1Width);
  191. void validate_mid2_gain(long lMid2Gain);
  192. void validate_mid2_center(float flMid2Center);
  193. void validate_mid2_width(float flMid2Width);
  194. void validate_high_gain(long lHighGain);
  195. void validate_high_cutoff(float flHighCutOff);
  196. void validate_all(const EAXEQUALIZERPROPERTIES& all);
  197. void defer_low_gain(long lLowGain);
  198. void defer_low_cutoff(float flLowCutOff);
  199. void defer_mid1_gain(long lMid1Gain);
  200. void defer_mid1_center(float flMid1Center);
  201. void defer_mid1_width(float flMid1Width);
  202. void defer_mid2_gain(long lMid2Gain);
  203. void defer_mid2_center(float flMid2Center);
  204. void defer_mid2_width(float flMid2Width);
  205. void defer_high_gain(long lHighGain);
  206. void defer_high_cutoff(float flHighCutOff);
  207. void defer_all(const EAXEQUALIZERPROPERTIES& all);
  208. void defer_low_gain(const EaxEaxCall& eax_call);
  209. void defer_low_cutoff(const EaxEaxCall& eax_call);
  210. void defer_mid1_gain(const EaxEaxCall& eax_call);
  211. void defer_mid1_center(const EaxEaxCall& eax_call);
  212. void defer_mid1_width(const EaxEaxCall& eax_call);
  213. void defer_mid2_gain(const EaxEaxCall& eax_call);
  214. void defer_mid2_center(const EaxEaxCall& eax_call);
  215. void defer_mid2_width(const EaxEaxCall& eax_call);
  216. void defer_high_gain(const EaxEaxCall& eax_call);
  217. void defer_high_cutoff(const EaxEaxCall& eax_call);
  218. void defer_all(const EaxEaxCall& eax_call);
  219. void set(const EaxEaxCall& eax_call);
  220. }; // EaxEqualizerEffect
  221. class EaxEqualizerEffectException :
  222. public EaxException
  223. {
  224. public:
  225. explicit EaxEqualizerEffectException(
  226. const char* message)
  227. :
  228. EaxException{"EAX_EQUALIZER_EFFECT", message}
  229. {
  230. }
  231. }; // EaxEqualizerEffectException
  232. EaxEqualizerEffect::EaxEqualizerEffect()
  233. : EaxEffect{AL_EFFECT_EQUALIZER}
  234. {
  235. set_eax_defaults();
  236. set_efx_defaults();
  237. }
  238. void EaxEqualizerEffect::dispatch(const EaxEaxCall& eax_call)
  239. {
  240. eax_call.is_get() ? get(eax_call) : set(eax_call);
  241. }
  242. void EaxEqualizerEffect::set_eax_defaults()
  243. {
  244. eax_.lLowGain = EAXEQUALIZER_DEFAULTLOWGAIN;
  245. eax_.flLowCutOff = EAXEQUALIZER_DEFAULTLOWCUTOFF;
  246. eax_.lMid1Gain = EAXEQUALIZER_DEFAULTMID1GAIN;
  247. eax_.flMid1Center = EAXEQUALIZER_DEFAULTMID1CENTER;
  248. eax_.flMid1Width = EAXEQUALIZER_DEFAULTMID1WIDTH;
  249. eax_.lMid2Gain = EAXEQUALIZER_DEFAULTMID2GAIN;
  250. eax_.flMid2Center = EAXEQUALIZER_DEFAULTMID2CENTER;
  251. eax_.flMid2Width = EAXEQUALIZER_DEFAULTMID2WIDTH;
  252. eax_.lHighGain = EAXEQUALIZER_DEFAULTHIGHGAIN;
  253. eax_.flHighCutOff = EAXEQUALIZER_DEFAULTHIGHCUTOFF;
  254. eax_d_ = eax_;
  255. }
  256. void EaxEqualizerEffect::set_efx_low_gain()
  257. {
  258. const auto low_gain = clamp(
  259. level_mb_to_gain(static_cast<float>(eax_.lLowGain)),
  260. AL_EQUALIZER_MIN_LOW_GAIN,
  261. AL_EQUALIZER_MAX_LOW_GAIN);
  262. al_effect_props_.Equalizer.LowGain = low_gain;
  263. }
  264. void EaxEqualizerEffect::set_efx_low_cutoff()
  265. {
  266. const auto low_cutoff = clamp(
  267. eax_.flLowCutOff,
  268. AL_EQUALIZER_MIN_LOW_CUTOFF,
  269. AL_EQUALIZER_MAX_LOW_CUTOFF);
  270. al_effect_props_.Equalizer.LowCutoff = low_cutoff;
  271. }
  272. void EaxEqualizerEffect::set_efx_mid1_gain()
  273. {
  274. const auto mid1_gain = clamp(
  275. level_mb_to_gain(static_cast<float>(eax_.lMid1Gain)),
  276. AL_EQUALIZER_MIN_MID1_GAIN,
  277. AL_EQUALIZER_MAX_MID1_GAIN);
  278. al_effect_props_.Equalizer.Mid1Gain = mid1_gain;
  279. }
  280. void EaxEqualizerEffect::set_efx_mid1_center()
  281. {
  282. const auto mid1_center = clamp(
  283. eax_.flMid1Center,
  284. AL_EQUALIZER_MIN_MID1_CENTER,
  285. AL_EQUALIZER_MAX_MID1_CENTER);
  286. al_effect_props_.Equalizer.Mid1Center = mid1_center;
  287. }
  288. void EaxEqualizerEffect::set_efx_mid1_width()
  289. {
  290. const auto mid1_width = clamp(
  291. eax_.flMid1Width,
  292. AL_EQUALIZER_MIN_MID1_WIDTH,
  293. AL_EQUALIZER_MAX_MID1_WIDTH);
  294. al_effect_props_.Equalizer.Mid1Width = mid1_width;
  295. }
  296. void EaxEqualizerEffect::set_efx_mid2_gain()
  297. {
  298. const auto mid2_gain = clamp(
  299. level_mb_to_gain(static_cast<float>(eax_.lMid2Gain)),
  300. AL_EQUALIZER_MIN_MID2_GAIN,
  301. AL_EQUALIZER_MAX_MID2_GAIN);
  302. al_effect_props_.Equalizer.Mid2Gain = mid2_gain;
  303. }
  304. void EaxEqualizerEffect::set_efx_mid2_center()
  305. {
  306. const auto mid2_center = clamp(
  307. eax_.flMid2Center,
  308. AL_EQUALIZER_MIN_MID2_CENTER,
  309. AL_EQUALIZER_MAX_MID2_CENTER);
  310. al_effect_props_.Equalizer.Mid2Center = mid2_center;
  311. }
  312. void EaxEqualizerEffect::set_efx_mid2_width()
  313. {
  314. const auto mid2_width = clamp(
  315. eax_.flMid2Width,
  316. AL_EQUALIZER_MIN_MID2_WIDTH,
  317. AL_EQUALIZER_MAX_MID2_WIDTH);
  318. al_effect_props_.Equalizer.Mid2Width = mid2_width;
  319. }
  320. void EaxEqualizerEffect::set_efx_high_gain()
  321. {
  322. const auto high_gain = clamp(
  323. level_mb_to_gain(static_cast<float>(eax_.lHighGain)),
  324. AL_EQUALIZER_MIN_HIGH_GAIN,
  325. AL_EQUALIZER_MAX_HIGH_GAIN);
  326. al_effect_props_.Equalizer.HighGain = high_gain;
  327. }
  328. void EaxEqualizerEffect::set_efx_high_cutoff()
  329. {
  330. const auto high_cutoff = clamp(
  331. eax_.flHighCutOff,
  332. AL_EQUALIZER_MIN_HIGH_CUTOFF,
  333. AL_EQUALIZER_MAX_HIGH_CUTOFF);
  334. al_effect_props_.Equalizer.HighCutoff = high_cutoff;
  335. }
  336. void EaxEqualizerEffect::set_efx_defaults()
  337. {
  338. set_efx_low_gain();
  339. set_efx_low_cutoff();
  340. set_efx_mid1_gain();
  341. set_efx_mid1_center();
  342. set_efx_mid1_width();
  343. set_efx_mid2_gain();
  344. set_efx_mid2_center();
  345. set_efx_mid2_width();
  346. set_efx_high_gain();
  347. set_efx_high_cutoff();
  348. }
  349. void EaxEqualizerEffect::get(const EaxEaxCall& eax_call)
  350. {
  351. switch(eax_call.get_property_id())
  352. {
  353. case EAXEQUALIZER_NONE:
  354. break;
  355. case EAXEQUALIZER_ALLPARAMETERS:
  356. eax_call.set_value<EaxEqualizerEffectException>(eax_);
  357. break;
  358. case EAXEQUALIZER_LOWGAIN:
  359. eax_call.set_value<EaxEqualizerEffectException>(eax_.lLowGain);
  360. break;
  361. case EAXEQUALIZER_LOWCUTOFF:
  362. eax_call.set_value<EaxEqualizerEffectException>(eax_.flLowCutOff);
  363. break;
  364. case EAXEQUALIZER_MID1GAIN:
  365. eax_call.set_value<EaxEqualizerEffectException>(eax_.lMid1Gain);
  366. break;
  367. case EAXEQUALIZER_MID1CENTER:
  368. eax_call.set_value<EaxEqualizerEffectException>(eax_.flMid1Center);
  369. break;
  370. case EAXEQUALIZER_MID1WIDTH:
  371. eax_call.set_value<EaxEqualizerEffectException>(eax_.flMid1Width);
  372. break;
  373. case EAXEQUALIZER_MID2GAIN:
  374. eax_call.set_value<EaxEqualizerEffectException>(eax_.lMid2Gain);
  375. break;
  376. case EAXEQUALIZER_MID2CENTER:
  377. eax_call.set_value<EaxEqualizerEffectException>(eax_.flMid2Center);
  378. break;
  379. case EAXEQUALIZER_MID2WIDTH:
  380. eax_call.set_value<EaxEqualizerEffectException>(eax_.flMid2Width);
  381. break;
  382. case EAXEQUALIZER_HIGHGAIN:
  383. eax_call.set_value<EaxEqualizerEffectException>(eax_.lHighGain);
  384. break;
  385. case EAXEQUALIZER_HIGHCUTOFF:
  386. eax_call.set_value<EaxEqualizerEffectException>(eax_.flHighCutOff);
  387. break;
  388. default:
  389. throw EaxEqualizerEffectException{"Unsupported property id."};
  390. }
  391. }
  392. void EaxEqualizerEffect::validate_low_gain(
  393. long lLowGain)
  394. {
  395. eax_validate_range<EaxEqualizerEffectException>(
  396. "Low Gain",
  397. lLowGain,
  398. EAXEQUALIZER_MINLOWGAIN,
  399. EAXEQUALIZER_MAXLOWGAIN);
  400. }
  401. void EaxEqualizerEffect::validate_low_cutoff(
  402. float flLowCutOff)
  403. {
  404. eax_validate_range<EaxEqualizerEffectException>(
  405. "Low Cutoff",
  406. flLowCutOff,
  407. EAXEQUALIZER_MINLOWCUTOFF,
  408. EAXEQUALIZER_MAXLOWCUTOFF);
  409. }
  410. void EaxEqualizerEffect::validate_mid1_gain(
  411. long lMid1Gain)
  412. {
  413. eax_validate_range<EaxEqualizerEffectException>(
  414. "Mid1 Gain",
  415. lMid1Gain,
  416. EAXEQUALIZER_MINMID1GAIN,
  417. EAXEQUALIZER_MAXMID1GAIN);
  418. }
  419. void EaxEqualizerEffect::validate_mid1_center(
  420. float flMid1Center)
  421. {
  422. eax_validate_range<EaxEqualizerEffectException>(
  423. "Mid1 Center",
  424. flMid1Center,
  425. EAXEQUALIZER_MINMID1CENTER,
  426. EAXEQUALIZER_MAXMID1CENTER);
  427. }
  428. void EaxEqualizerEffect::validate_mid1_width(
  429. float flMid1Width)
  430. {
  431. eax_validate_range<EaxEqualizerEffectException>(
  432. "Mid1 Width",
  433. flMid1Width,
  434. EAXEQUALIZER_MINMID1WIDTH,
  435. EAXEQUALIZER_MAXMID1WIDTH);
  436. }
  437. void EaxEqualizerEffect::validate_mid2_gain(
  438. long lMid2Gain)
  439. {
  440. eax_validate_range<EaxEqualizerEffectException>(
  441. "Mid2 Gain",
  442. lMid2Gain,
  443. EAXEQUALIZER_MINMID2GAIN,
  444. EAXEQUALIZER_MAXMID2GAIN);
  445. }
  446. void EaxEqualizerEffect::validate_mid2_center(
  447. float flMid2Center)
  448. {
  449. eax_validate_range<EaxEqualizerEffectException>(
  450. "Mid2 Center",
  451. flMid2Center,
  452. EAXEQUALIZER_MINMID2CENTER,
  453. EAXEQUALIZER_MAXMID2CENTER);
  454. }
  455. void EaxEqualizerEffect::validate_mid2_width(
  456. float flMid2Width)
  457. {
  458. eax_validate_range<EaxEqualizerEffectException>(
  459. "Mid2 Width",
  460. flMid2Width,
  461. EAXEQUALIZER_MINMID2WIDTH,
  462. EAXEQUALIZER_MAXMID2WIDTH);
  463. }
  464. void EaxEqualizerEffect::validate_high_gain(
  465. long lHighGain)
  466. {
  467. eax_validate_range<EaxEqualizerEffectException>(
  468. "High Gain",
  469. lHighGain,
  470. EAXEQUALIZER_MINHIGHGAIN,
  471. EAXEQUALIZER_MAXHIGHGAIN);
  472. }
  473. void EaxEqualizerEffect::validate_high_cutoff(
  474. float flHighCutOff)
  475. {
  476. eax_validate_range<EaxEqualizerEffectException>(
  477. "High Cutoff",
  478. flHighCutOff,
  479. EAXEQUALIZER_MINHIGHCUTOFF,
  480. EAXEQUALIZER_MAXHIGHCUTOFF);
  481. }
  482. void EaxEqualizerEffect::validate_all(
  483. const EAXEQUALIZERPROPERTIES& all)
  484. {
  485. validate_low_gain(all.lLowGain);
  486. validate_low_cutoff(all.flLowCutOff);
  487. validate_mid1_gain(all.lMid1Gain);
  488. validate_mid1_center(all.flMid1Center);
  489. validate_mid1_width(all.flMid1Width);
  490. validate_mid2_gain(all.lMid2Gain);
  491. validate_mid2_center(all.flMid2Center);
  492. validate_mid2_width(all.flMid2Width);
  493. validate_high_gain(all.lHighGain);
  494. validate_high_cutoff(all.flHighCutOff);
  495. }
  496. void EaxEqualizerEffect::defer_low_gain(
  497. long lLowGain)
  498. {
  499. eax_d_.lLowGain = lLowGain;
  500. eax_dirty_flags_.lLowGain = (eax_.lLowGain != eax_d_.lLowGain);
  501. }
  502. void EaxEqualizerEffect::defer_low_cutoff(
  503. float flLowCutOff)
  504. {
  505. eax_d_.flLowCutOff = flLowCutOff;
  506. eax_dirty_flags_.flLowCutOff = (eax_.flLowCutOff != eax_d_.flLowCutOff);
  507. }
  508. void EaxEqualizerEffect::defer_mid1_gain(
  509. long lMid1Gain)
  510. {
  511. eax_d_.lMid1Gain = lMid1Gain;
  512. eax_dirty_flags_.lMid1Gain = (eax_.lMid1Gain != eax_d_.lMid1Gain);
  513. }
  514. void EaxEqualizerEffect::defer_mid1_center(
  515. float flMid1Center)
  516. {
  517. eax_d_.flMid1Center = flMid1Center;
  518. eax_dirty_flags_.flMid1Center = (eax_.flMid1Center != eax_d_.flMid1Center);
  519. }
  520. void EaxEqualizerEffect::defer_mid1_width(
  521. float flMid1Width)
  522. {
  523. eax_d_.flMid1Width = flMid1Width;
  524. eax_dirty_flags_.flMid1Width = (eax_.flMid1Width != eax_d_.flMid1Width);
  525. }
  526. void EaxEqualizerEffect::defer_mid2_gain(
  527. long lMid2Gain)
  528. {
  529. eax_d_.lMid2Gain = lMid2Gain;
  530. eax_dirty_flags_.lMid2Gain = (eax_.lMid2Gain != eax_d_.lMid2Gain);
  531. }
  532. void EaxEqualizerEffect::defer_mid2_center(
  533. float flMid2Center)
  534. {
  535. eax_d_.flMid2Center = flMid2Center;
  536. eax_dirty_flags_.flMid2Center = (eax_.flMid2Center != eax_d_.flMid2Center);
  537. }
  538. void EaxEqualizerEffect::defer_mid2_width(
  539. float flMid2Width)
  540. {
  541. eax_d_.flMid2Width = flMid2Width;
  542. eax_dirty_flags_.flMid2Width = (eax_.flMid2Width != eax_d_.flMid2Width);
  543. }
  544. void EaxEqualizerEffect::defer_high_gain(
  545. long lHighGain)
  546. {
  547. eax_d_.lHighGain = lHighGain;
  548. eax_dirty_flags_.lHighGain = (eax_.lHighGain != eax_d_.lHighGain);
  549. }
  550. void EaxEqualizerEffect::defer_high_cutoff(
  551. float flHighCutOff)
  552. {
  553. eax_d_.flHighCutOff = flHighCutOff;
  554. eax_dirty_flags_.flHighCutOff = (eax_.flHighCutOff != eax_d_.flHighCutOff);
  555. }
  556. void EaxEqualizerEffect::defer_all(
  557. const EAXEQUALIZERPROPERTIES& all)
  558. {
  559. defer_low_gain(all.lLowGain);
  560. defer_low_cutoff(all.flLowCutOff);
  561. defer_mid1_gain(all.lMid1Gain);
  562. defer_mid1_center(all.flMid1Center);
  563. defer_mid1_width(all.flMid1Width);
  564. defer_mid2_gain(all.lMid2Gain);
  565. defer_mid2_center(all.flMid2Center);
  566. defer_mid2_width(all.flMid2Width);
  567. defer_high_gain(all.lHighGain);
  568. defer_high_cutoff(all.flHighCutOff);
  569. }
  570. void EaxEqualizerEffect::defer_low_gain(
  571. const EaxEaxCall& eax_call)
  572. {
  573. const auto& low_gain =
  574. eax_call.get_value<EaxEqualizerEffectException, const decltype(EAXEQUALIZERPROPERTIES::lLowGain)>();
  575. validate_low_gain(low_gain);
  576. defer_low_gain(low_gain);
  577. }
  578. void EaxEqualizerEffect::defer_low_cutoff(
  579. const EaxEaxCall& eax_call)
  580. {
  581. const auto& low_cutoff =
  582. eax_call.get_value<EaxEqualizerEffectException, const decltype(EAXEQUALIZERPROPERTIES::flLowCutOff)>();
  583. validate_low_cutoff(low_cutoff);
  584. defer_low_cutoff(low_cutoff);
  585. }
  586. void EaxEqualizerEffect::defer_mid1_gain(
  587. const EaxEaxCall& eax_call)
  588. {
  589. const auto& mid1_gain =
  590. eax_call.get_value<EaxEqualizerEffectException, const decltype(EAXEQUALIZERPROPERTIES::lMid1Gain)>();
  591. validate_mid1_gain(mid1_gain);
  592. defer_mid1_gain(mid1_gain);
  593. }
  594. void EaxEqualizerEffect::defer_mid1_center(
  595. const EaxEaxCall& eax_call)
  596. {
  597. const auto& mid1_center =
  598. eax_call.get_value<EaxEqualizerEffectException, const decltype(EAXEQUALIZERPROPERTIES::flMid1Center)>();
  599. validate_mid1_center(mid1_center);
  600. defer_mid1_center(mid1_center);
  601. }
  602. void EaxEqualizerEffect::defer_mid1_width(
  603. const EaxEaxCall& eax_call)
  604. {
  605. const auto& mid1_width =
  606. eax_call.get_value<EaxEqualizerEffectException, const decltype(EAXEQUALIZERPROPERTIES::flMid1Width)>();
  607. validate_mid1_width(mid1_width);
  608. defer_mid1_width(mid1_width);
  609. }
  610. void EaxEqualizerEffect::defer_mid2_gain(
  611. const EaxEaxCall& eax_call)
  612. {
  613. const auto& mid2_gain =
  614. eax_call.get_value<EaxEqualizerEffectException, const decltype(EAXEQUALIZERPROPERTIES::lMid2Gain)>();
  615. validate_mid2_gain(mid2_gain);
  616. defer_mid2_gain(mid2_gain);
  617. }
  618. void EaxEqualizerEffect::defer_mid2_center(
  619. const EaxEaxCall& eax_call)
  620. {
  621. const auto& mid2_center =
  622. eax_call.get_value<EaxEqualizerEffectException, const decltype(EAXEQUALIZERPROPERTIES::flMid2Center)>();
  623. validate_mid2_center(mid2_center);
  624. defer_mid2_center(mid2_center);
  625. }
  626. void EaxEqualizerEffect::defer_mid2_width(
  627. const EaxEaxCall& eax_call)
  628. {
  629. const auto& mid2_width =
  630. eax_call.get_value<EaxEqualizerEffectException, const decltype(EAXEQUALIZERPROPERTIES::flMid2Width)>();
  631. validate_mid2_width(mid2_width);
  632. defer_mid2_width(mid2_width);
  633. }
  634. void EaxEqualizerEffect::defer_high_gain(
  635. const EaxEaxCall& eax_call)
  636. {
  637. const auto& high_gain =
  638. eax_call.get_value<EaxEqualizerEffectException, const decltype(EAXEQUALIZERPROPERTIES::lHighGain)>();
  639. validate_high_gain(high_gain);
  640. defer_high_gain(high_gain);
  641. }
  642. void EaxEqualizerEffect::defer_high_cutoff(
  643. const EaxEaxCall& eax_call)
  644. {
  645. const auto& high_cutoff =
  646. eax_call.get_value<EaxEqualizerEffectException, const decltype(EAXEQUALIZERPROPERTIES::flHighCutOff)>();
  647. validate_high_cutoff(high_cutoff);
  648. defer_high_cutoff(high_cutoff);
  649. }
  650. void EaxEqualizerEffect::defer_all(
  651. const EaxEaxCall& eax_call)
  652. {
  653. const auto& all =
  654. eax_call.get_value<EaxEqualizerEffectException, const EAXEQUALIZERPROPERTIES>();
  655. validate_all(all);
  656. defer_all(all);
  657. }
  658. // [[nodiscard]]
  659. bool EaxEqualizerEffect::apply_deferred()
  660. {
  661. if (eax_dirty_flags_ == EaxEqualizerEffectDirtyFlags{})
  662. {
  663. return false;
  664. }
  665. eax_ = eax_d_;
  666. if (eax_dirty_flags_.lLowGain)
  667. {
  668. set_efx_low_gain();
  669. }
  670. if (eax_dirty_flags_.flLowCutOff)
  671. {
  672. set_efx_low_cutoff();
  673. }
  674. if (eax_dirty_flags_.lMid1Gain)
  675. {
  676. set_efx_mid1_gain();
  677. }
  678. if (eax_dirty_flags_.flMid1Center)
  679. {
  680. set_efx_mid1_center();
  681. }
  682. if (eax_dirty_flags_.flMid1Width)
  683. {
  684. set_efx_mid1_width();
  685. }
  686. if (eax_dirty_flags_.lMid2Gain)
  687. {
  688. set_efx_mid2_gain();
  689. }
  690. if (eax_dirty_flags_.flMid2Center)
  691. {
  692. set_efx_mid2_center();
  693. }
  694. if (eax_dirty_flags_.flMid2Width)
  695. {
  696. set_efx_mid2_width();
  697. }
  698. if (eax_dirty_flags_.lHighGain)
  699. {
  700. set_efx_high_gain();
  701. }
  702. if (eax_dirty_flags_.flHighCutOff)
  703. {
  704. set_efx_high_cutoff();
  705. }
  706. eax_dirty_flags_ = EaxEqualizerEffectDirtyFlags{};
  707. return true;
  708. }
  709. void EaxEqualizerEffect::set(const EaxEaxCall& eax_call)
  710. {
  711. switch(eax_call.get_property_id())
  712. {
  713. case EAXEQUALIZER_NONE:
  714. break;
  715. case EAXEQUALIZER_ALLPARAMETERS:
  716. defer_all(eax_call);
  717. break;
  718. case EAXEQUALIZER_LOWGAIN:
  719. defer_low_gain(eax_call);
  720. break;
  721. case EAXEQUALIZER_LOWCUTOFF:
  722. defer_low_cutoff(eax_call);
  723. break;
  724. case EAXEQUALIZER_MID1GAIN:
  725. defer_mid1_gain(eax_call);
  726. break;
  727. case EAXEQUALIZER_MID1CENTER:
  728. defer_mid1_center(eax_call);
  729. break;
  730. case EAXEQUALIZER_MID1WIDTH:
  731. defer_mid1_width(eax_call);
  732. break;
  733. case EAXEQUALIZER_MID2GAIN:
  734. defer_mid2_gain(eax_call);
  735. break;
  736. case EAXEQUALIZER_MID2CENTER:
  737. defer_mid2_center(eax_call);
  738. break;
  739. case EAXEQUALIZER_MID2WIDTH:
  740. defer_mid2_width(eax_call);
  741. break;
  742. case EAXEQUALIZER_HIGHGAIN:
  743. defer_high_gain(eax_call);
  744. break;
  745. case EAXEQUALIZER_HIGHCUTOFF:
  746. defer_high_cutoff(eax_call);
  747. break;
  748. default:
  749. throw EaxEqualizerEffectException{"Unsupported property id."};
  750. }
  751. }
  752. } // namespace
  753. EaxEffectUPtr eax_create_eax_equalizer_effect()
  754. {
  755. return std::make_unique<EaxEqualizerEffect>();
  756. }
  757. #endif // ALSOFT_EAX