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

565 lines
18 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. class EaxEqualizerEffectException : public EaxException
  147. {
  148. public:
  149. explicit EaxEqualizerEffectException(const char* message)
  150. : EaxException{"EAX_EQUALIZER_EFFECT", message}
  151. {}
  152. }; // EaxEqualizerEffectException
  153. class EaxEqualizerEffect final : public EaxEffect4<EaxEqualizerEffectException, EAXEQUALIZERPROPERTIES>
  154. {
  155. public:
  156. EaxEqualizerEffect(const EaxCall& call);
  157. private:
  158. struct LowGainValidator {
  159. void operator()(long lLowGain) const
  160. {
  161. eax_validate_range<Exception>(
  162. "Low Gain",
  163. lLowGain,
  164. EAXEQUALIZER_MINLOWGAIN,
  165. EAXEQUALIZER_MAXLOWGAIN);
  166. }
  167. }; // LowGainValidator
  168. struct LowCutOffValidator {
  169. void operator()(float flLowCutOff) const
  170. {
  171. eax_validate_range<Exception>(
  172. "Low Cutoff",
  173. flLowCutOff,
  174. EAXEQUALIZER_MINLOWCUTOFF,
  175. EAXEQUALIZER_MAXLOWCUTOFF);
  176. }
  177. }; // LowCutOffValidator
  178. struct Mid1GainValidator {
  179. void operator()(long lMid1Gain) const
  180. {
  181. eax_validate_range<Exception>(
  182. "Mid1 Gain",
  183. lMid1Gain,
  184. EAXEQUALIZER_MINMID1GAIN,
  185. EAXEQUALIZER_MAXMID1GAIN);
  186. }
  187. }; // Mid1GainValidator
  188. struct Mid1CenterValidator {
  189. void operator()(float flMid1Center) const
  190. {
  191. eax_validate_range<Exception>(
  192. "Mid1 Center",
  193. flMid1Center,
  194. EAXEQUALIZER_MINMID1CENTER,
  195. EAXEQUALIZER_MAXMID1CENTER);
  196. }
  197. }; // Mid1CenterValidator
  198. struct Mid1WidthValidator {
  199. void operator()(float flMid1Width) const
  200. {
  201. eax_validate_range<Exception>(
  202. "Mid1 Width",
  203. flMid1Width,
  204. EAXEQUALIZER_MINMID1WIDTH,
  205. EAXEQUALIZER_MAXMID1WIDTH);
  206. }
  207. }; // Mid1WidthValidator
  208. struct Mid2GainValidator {
  209. void operator()(long lMid2Gain) const
  210. {
  211. eax_validate_range<Exception>(
  212. "Mid2 Gain",
  213. lMid2Gain,
  214. EAXEQUALIZER_MINMID2GAIN,
  215. EAXEQUALIZER_MAXMID2GAIN);
  216. }
  217. }; // Mid2GainValidator
  218. struct Mid2CenterValidator {
  219. void operator()(float flMid2Center) const
  220. {
  221. eax_validate_range<Exception>(
  222. "Mid2 Center",
  223. flMid2Center,
  224. EAXEQUALIZER_MINMID2CENTER,
  225. EAXEQUALIZER_MAXMID2CENTER);
  226. }
  227. }; // Mid2CenterValidator
  228. struct Mid2WidthValidator {
  229. void operator()(float flMid2Width) const
  230. {
  231. eax_validate_range<Exception>(
  232. "Mid2 Width",
  233. flMid2Width,
  234. EAXEQUALIZER_MINMID2WIDTH,
  235. EAXEQUALIZER_MAXMID2WIDTH);
  236. }
  237. }; // Mid2WidthValidator
  238. struct HighGainValidator {
  239. void operator()(long lHighGain) const
  240. {
  241. eax_validate_range<Exception>(
  242. "High Gain",
  243. lHighGain,
  244. EAXEQUALIZER_MINHIGHGAIN,
  245. EAXEQUALIZER_MAXHIGHGAIN);
  246. }
  247. }; // HighGainValidator
  248. struct HighCutOffValidator {
  249. void operator()(float flHighCutOff) const
  250. {
  251. eax_validate_range<Exception>(
  252. "High Cutoff",
  253. flHighCutOff,
  254. EAXEQUALIZER_MINHIGHCUTOFF,
  255. EAXEQUALIZER_MAXHIGHCUTOFF);
  256. }
  257. }; // HighCutOffValidator
  258. struct AllValidator {
  259. void operator()(const Props& all) const
  260. {
  261. LowGainValidator{}(all.lLowGain);
  262. LowCutOffValidator{}(all.flLowCutOff);
  263. Mid1GainValidator{}(all.lMid1Gain);
  264. Mid1CenterValidator{}(all.flMid1Center);
  265. Mid1WidthValidator{}(all.flMid1Width);
  266. Mid2GainValidator{}(all.lMid2Gain);
  267. Mid2CenterValidator{}(all.flMid2Center);
  268. Mid2WidthValidator{}(all.flMid2Width);
  269. HighGainValidator{}(all.lHighGain);
  270. HighCutOffValidator{}(all.flHighCutOff);
  271. }
  272. }; // AllValidator
  273. void set_defaults(Props& props) override;
  274. void set_efx_low_gain() noexcept;
  275. void set_efx_low_cutoff() noexcept;
  276. void set_efx_mid1_gain() noexcept;
  277. void set_efx_mid1_center() noexcept;
  278. void set_efx_mid1_width() noexcept;
  279. void set_efx_mid2_gain() noexcept;
  280. void set_efx_mid2_center() noexcept;
  281. void set_efx_mid2_width() noexcept;
  282. void set_efx_high_gain() noexcept;
  283. void set_efx_high_cutoff() noexcept;
  284. void set_efx_defaults() override;
  285. void get(const EaxCall& call, const Props& props) override;
  286. void set(const EaxCall& call, Props& props) override;
  287. bool commit_props(const Props& props) override;
  288. }; // EaxEqualizerEffect
  289. EaxEqualizerEffect::EaxEqualizerEffect(const EaxCall& call)
  290. : EaxEffect4{AL_EFFECT_EQUALIZER, call}
  291. {}
  292. void EaxEqualizerEffect::set_defaults(Props& props)
  293. {
  294. props.lLowGain = EAXEQUALIZER_DEFAULTLOWGAIN;
  295. props.flLowCutOff = EAXEQUALIZER_DEFAULTLOWCUTOFF;
  296. props.lMid1Gain = EAXEQUALIZER_DEFAULTMID1GAIN;
  297. props.flMid1Center = EAXEQUALIZER_DEFAULTMID1CENTER;
  298. props.flMid1Width = EAXEQUALIZER_DEFAULTMID1WIDTH;
  299. props.lMid2Gain = EAXEQUALIZER_DEFAULTMID2GAIN;
  300. props.flMid2Center = EAXEQUALIZER_DEFAULTMID2CENTER;
  301. props.flMid2Width = EAXEQUALIZER_DEFAULTMID2WIDTH;
  302. props.lHighGain = EAXEQUALIZER_DEFAULTHIGHGAIN;
  303. props.flHighCutOff = EAXEQUALIZER_DEFAULTHIGHCUTOFF;
  304. }
  305. void EaxEqualizerEffect::set_efx_low_gain() noexcept
  306. {
  307. al_effect_props_.Equalizer.LowGain = clamp(
  308. level_mb_to_gain(static_cast<float>(props_.lLowGain)),
  309. AL_EQUALIZER_MIN_LOW_GAIN,
  310. AL_EQUALIZER_MAX_LOW_GAIN);
  311. }
  312. void EaxEqualizerEffect::set_efx_low_cutoff() noexcept
  313. {
  314. al_effect_props_.Equalizer.LowCutoff = clamp(
  315. props_.flLowCutOff,
  316. AL_EQUALIZER_MIN_LOW_CUTOFF,
  317. AL_EQUALIZER_MAX_LOW_CUTOFF);
  318. }
  319. void EaxEqualizerEffect::set_efx_mid1_gain() noexcept
  320. {
  321. al_effect_props_.Equalizer.Mid1Gain = clamp(
  322. level_mb_to_gain(static_cast<float>(props_.lMid1Gain)),
  323. AL_EQUALIZER_MIN_MID1_GAIN,
  324. AL_EQUALIZER_MAX_MID1_GAIN);
  325. }
  326. void EaxEqualizerEffect::set_efx_mid1_center() noexcept
  327. {
  328. al_effect_props_.Equalizer.Mid1Center = clamp(
  329. props_.flMid1Center,
  330. AL_EQUALIZER_MIN_MID1_CENTER,
  331. AL_EQUALIZER_MAX_MID1_CENTER);
  332. }
  333. void EaxEqualizerEffect::set_efx_mid1_width() noexcept
  334. {
  335. al_effect_props_.Equalizer.Mid1Width = clamp(
  336. props_.flMid1Width,
  337. AL_EQUALIZER_MIN_MID1_WIDTH,
  338. AL_EQUALIZER_MAX_MID1_WIDTH);
  339. }
  340. void EaxEqualizerEffect::set_efx_mid2_gain() noexcept
  341. {
  342. al_effect_props_.Equalizer.Mid2Gain = clamp(
  343. level_mb_to_gain(static_cast<float>(props_.lMid2Gain)),
  344. AL_EQUALIZER_MIN_MID2_GAIN,
  345. AL_EQUALIZER_MAX_MID2_GAIN);
  346. }
  347. void EaxEqualizerEffect::set_efx_mid2_center() noexcept
  348. {
  349. al_effect_props_.Equalizer.Mid2Center = clamp(
  350. props_.flMid2Center,
  351. AL_EQUALIZER_MIN_MID2_CENTER,
  352. AL_EQUALIZER_MAX_MID2_CENTER);
  353. }
  354. void EaxEqualizerEffect::set_efx_mid2_width() noexcept
  355. {
  356. al_effect_props_.Equalizer.Mid2Width = clamp(
  357. props_.flMid2Width,
  358. AL_EQUALIZER_MIN_MID2_WIDTH,
  359. AL_EQUALIZER_MAX_MID2_WIDTH);
  360. }
  361. void EaxEqualizerEffect::set_efx_high_gain() noexcept
  362. {
  363. al_effect_props_.Equalizer.HighGain = clamp(
  364. level_mb_to_gain(static_cast<float>(props_.lHighGain)),
  365. AL_EQUALIZER_MIN_HIGH_GAIN,
  366. AL_EQUALIZER_MAX_HIGH_GAIN);
  367. }
  368. void EaxEqualizerEffect::set_efx_high_cutoff() noexcept
  369. {
  370. al_effect_props_.Equalizer.HighCutoff = clamp(
  371. props_.flHighCutOff,
  372. AL_EQUALIZER_MIN_HIGH_CUTOFF,
  373. AL_EQUALIZER_MAX_HIGH_CUTOFF);
  374. }
  375. void EaxEqualizerEffect::set_efx_defaults()
  376. {
  377. set_efx_low_gain();
  378. set_efx_low_cutoff();
  379. set_efx_mid1_gain();
  380. set_efx_mid1_center();
  381. set_efx_mid1_width();
  382. set_efx_mid2_gain();
  383. set_efx_mid2_center();
  384. set_efx_mid2_width();
  385. set_efx_high_gain();
  386. set_efx_high_cutoff();
  387. }
  388. void EaxEqualizerEffect::get(const EaxCall& call, const Props& props)
  389. {
  390. switch(call.get_property_id())
  391. {
  392. case EAXEQUALIZER_NONE: break;
  393. case EAXEQUALIZER_ALLPARAMETERS: call.set_value<Exception>(props); break;
  394. case EAXEQUALIZER_LOWGAIN: call.set_value<Exception>(props.lLowGain); break;
  395. case EAXEQUALIZER_LOWCUTOFF: call.set_value<Exception>(props.flLowCutOff); break;
  396. case EAXEQUALIZER_MID1GAIN: call.set_value<Exception>(props.lMid1Gain); break;
  397. case EAXEQUALIZER_MID1CENTER: call.set_value<Exception>(props.flMid1Center); break;
  398. case EAXEQUALIZER_MID1WIDTH: call.set_value<Exception>(props.flMid1Width); break;
  399. case EAXEQUALIZER_MID2GAIN: call.set_value<Exception>(props.lMid2Gain); break;
  400. case EAXEQUALIZER_MID2CENTER: call.set_value<Exception>(props.flMid2Center); break;
  401. case EAXEQUALIZER_MID2WIDTH: call.set_value<Exception>(props.flMid2Width); break;
  402. case EAXEQUALIZER_HIGHGAIN: call.set_value<Exception>(props.lHighGain); break;
  403. case EAXEQUALIZER_HIGHCUTOFF: call.set_value<Exception>(props.flHighCutOff); break;
  404. default: fail_unknown_property_id();
  405. }
  406. }
  407. void EaxEqualizerEffect::set(const EaxCall& call, Props& props)
  408. {
  409. switch(call.get_property_id())
  410. {
  411. case EAXEQUALIZER_NONE: break;
  412. case EAXEQUALIZER_ALLPARAMETERS: defer<AllValidator>(call, props); break;
  413. case EAXEQUALIZER_LOWGAIN: defer<LowGainValidator>(call, props.lLowGain); break;
  414. case EAXEQUALIZER_LOWCUTOFF: defer<LowCutOffValidator>(call, props.flLowCutOff); break;
  415. case EAXEQUALIZER_MID1GAIN: defer<Mid1GainValidator>(call, props.lMid1Gain); break;
  416. case EAXEQUALIZER_MID1CENTER: defer<Mid1CenterValidator>(call, props.flMid1Center); break;
  417. case EAXEQUALIZER_MID1WIDTH: defer<Mid1WidthValidator>(call, props.flMid1Width); break;
  418. case EAXEQUALIZER_MID2GAIN: defer<Mid2GainValidator>(call, props.lMid2Gain); break;
  419. case EAXEQUALIZER_MID2CENTER: defer<Mid2CenterValidator>(call, props.flMid2Center); break;
  420. case EAXEQUALIZER_MID2WIDTH: defer<Mid2WidthValidator>(call, props.flMid2Width); break;
  421. case EAXEQUALIZER_HIGHGAIN: defer<HighGainValidator>(call, props.lHighGain); break;
  422. case EAXEQUALIZER_HIGHCUTOFF: defer<HighCutOffValidator>(call, props.flHighCutOff); break;
  423. default: fail_unknown_property_id();
  424. }
  425. }
  426. bool EaxEqualizerEffect::commit_props(const Props& props)
  427. {
  428. auto is_dirty = false;
  429. if (props_.lLowGain != props.lLowGain)
  430. {
  431. is_dirty = true;
  432. set_efx_low_gain();
  433. }
  434. if (props_.flLowCutOff != props.flLowCutOff)
  435. {
  436. is_dirty = true;
  437. set_efx_low_cutoff();
  438. }
  439. if (props_.lMid1Gain != props.lMid1Gain)
  440. {
  441. is_dirty = true;
  442. set_efx_mid1_gain();
  443. }
  444. if (props_.flMid1Center != props.flMid1Center)
  445. {
  446. is_dirty = true;
  447. set_efx_mid1_center();
  448. }
  449. if (props_.flMid1Width != props.flMid1Width)
  450. {
  451. is_dirty = true;
  452. set_efx_mid1_width();
  453. }
  454. if (props_.lMid2Gain != props.lMid2Gain)
  455. {
  456. is_dirty = true;
  457. set_efx_mid2_gain();
  458. }
  459. if (props_.flMid2Center != props.flMid2Center)
  460. {
  461. is_dirty = true;
  462. set_efx_mid2_center();
  463. }
  464. if (props_.flMid2Width != props.flMid2Width)
  465. {
  466. is_dirty = true;
  467. set_efx_mid2_width();
  468. }
  469. if (props_.lHighGain != props.lHighGain)
  470. {
  471. is_dirty = true;
  472. set_efx_high_gain();
  473. }
  474. if (props_.flHighCutOff != props.flHighCutOff)
  475. {
  476. is_dirty = true;
  477. set_efx_high_cutoff();
  478. }
  479. return is_dirty;
  480. }
  481. } // namespace
  482. EaxEffectUPtr eax_create_eax_equalizer_effect(const EaxCall& call)
  483. {
  484. return eax_create_eax4_effect<EaxEqualizerEffect>(call);
  485. }
  486. #endif // ALSOFT_EAX