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

318 lines
9.2 KiB

  1. #include "config.h"
  2. #include <cmath>
  3. #include <cstdlib>
  4. #include <algorithm>
  5. #include "AL/efx.h"
  6. #include "alc/effects/base.h"
  7. #include "effects.h"
  8. #ifdef ALSOFT_EAX
  9. #include "alnumeric.h"
  10. #include "al/eax/exception.h"
  11. #include "al/eax/utils.h"
  12. #endif // ALSOFT_EAX
  13. namespace {
  14. void Autowah_setParamf(EffectProps *props, ALenum param, float val)
  15. {
  16. switch(param)
  17. {
  18. case AL_AUTOWAH_ATTACK_TIME:
  19. if(!(val >= AL_AUTOWAH_MIN_ATTACK_TIME && val <= AL_AUTOWAH_MAX_ATTACK_TIME))
  20. throw effect_exception{AL_INVALID_VALUE, "Autowah attack time out of range"};
  21. props->Autowah.AttackTime = val;
  22. break;
  23. case AL_AUTOWAH_RELEASE_TIME:
  24. if(!(val >= AL_AUTOWAH_MIN_RELEASE_TIME && val <= AL_AUTOWAH_MAX_RELEASE_TIME))
  25. throw effect_exception{AL_INVALID_VALUE, "Autowah release time out of range"};
  26. props->Autowah.ReleaseTime = val;
  27. break;
  28. case AL_AUTOWAH_RESONANCE:
  29. if(!(val >= AL_AUTOWAH_MIN_RESONANCE && val <= AL_AUTOWAH_MAX_RESONANCE))
  30. throw effect_exception{AL_INVALID_VALUE, "Autowah resonance out of range"};
  31. props->Autowah.Resonance = val;
  32. break;
  33. case AL_AUTOWAH_PEAK_GAIN:
  34. if(!(val >= AL_AUTOWAH_MIN_PEAK_GAIN && val <= AL_AUTOWAH_MAX_PEAK_GAIN))
  35. throw effect_exception{AL_INVALID_VALUE, "Autowah peak gain out of range"};
  36. props->Autowah.PeakGain = val;
  37. break;
  38. default:
  39. throw effect_exception{AL_INVALID_ENUM, "Invalid autowah float property 0x%04x", param};
  40. }
  41. }
  42. void Autowah_setParamfv(EffectProps *props, ALenum param, const float *vals)
  43. { Autowah_setParamf(props, param, vals[0]); }
  44. void Autowah_setParami(EffectProps*, ALenum param, int)
  45. { throw effect_exception{AL_INVALID_ENUM, "Invalid autowah integer property 0x%04x", param}; }
  46. void Autowah_setParamiv(EffectProps*, ALenum param, const int*)
  47. {
  48. throw effect_exception{AL_INVALID_ENUM, "Invalid autowah integer vector property 0x%04x",
  49. param};
  50. }
  51. void Autowah_getParamf(const EffectProps *props, ALenum param, float *val)
  52. {
  53. switch(param)
  54. {
  55. case AL_AUTOWAH_ATTACK_TIME:
  56. *val = props->Autowah.AttackTime;
  57. break;
  58. case AL_AUTOWAH_RELEASE_TIME:
  59. *val = props->Autowah.ReleaseTime;
  60. break;
  61. case AL_AUTOWAH_RESONANCE:
  62. *val = props->Autowah.Resonance;
  63. break;
  64. case AL_AUTOWAH_PEAK_GAIN:
  65. *val = props->Autowah.PeakGain;
  66. break;
  67. default:
  68. throw effect_exception{AL_INVALID_ENUM, "Invalid autowah float property 0x%04x", param};
  69. }
  70. }
  71. void Autowah_getParamfv(const EffectProps *props, ALenum param, float *vals)
  72. { Autowah_getParamf(props, param, vals); }
  73. void Autowah_getParami(const EffectProps*, ALenum param, int*)
  74. { throw effect_exception{AL_INVALID_ENUM, "Invalid autowah integer property 0x%04x", param}; }
  75. void Autowah_getParamiv(const EffectProps*, ALenum param, int*)
  76. {
  77. throw effect_exception{AL_INVALID_ENUM, "Invalid autowah integer vector property 0x%04x",
  78. param};
  79. }
  80. EffectProps genDefaultProps() noexcept
  81. {
  82. EffectProps props{};
  83. props.Autowah.AttackTime = AL_AUTOWAH_DEFAULT_ATTACK_TIME;
  84. props.Autowah.ReleaseTime = AL_AUTOWAH_DEFAULT_RELEASE_TIME;
  85. props.Autowah.Resonance = AL_AUTOWAH_DEFAULT_RESONANCE;
  86. props.Autowah.PeakGain = AL_AUTOWAH_DEFAULT_PEAK_GAIN;
  87. return props;
  88. }
  89. } // namespace
  90. DEFINE_ALEFFECT_VTABLE(Autowah);
  91. const EffectProps AutowahEffectProps{genDefaultProps()};
  92. #ifdef ALSOFT_EAX
  93. namespace {
  94. class EaxAutoWahEffectException : public EaxException {
  95. public:
  96. explicit EaxAutoWahEffectException(const char* message)
  97. : EaxException{"EAX_AUTO_WAH_EFFECT", message}
  98. {}
  99. }; // EaxAutoWahEffectException
  100. class EaxAutoWahEffect final : public EaxEffect4<EaxAutoWahEffectException, EAXAUTOWAHPROPERTIES> {
  101. public:
  102. EaxAutoWahEffect(const EaxCall& call);
  103. private:
  104. struct AttackTimeValidator {
  105. void operator()(float flAttackTime) const
  106. {
  107. eax_validate_range<Exception>(
  108. "Attack Time",
  109. flAttackTime,
  110. EAXAUTOWAH_MINATTACKTIME,
  111. EAXAUTOWAH_MAXATTACKTIME);
  112. }
  113. }; // AttackTimeValidator
  114. struct ReleaseTimeValidator {
  115. void operator()(float flReleaseTime) const
  116. {
  117. eax_validate_range<Exception>(
  118. "Release Time",
  119. flReleaseTime,
  120. EAXAUTOWAH_MINRELEASETIME,
  121. EAXAUTOWAH_MAXRELEASETIME);
  122. }
  123. }; // ReleaseTimeValidator
  124. struct ResonanceValidator {
  125. void operator()(long lResonance) const
  126. {
  127. eax_validate_range<Exception>(
  128. "Resonance",
  129. lResonance,
  130. EAXAUTOWAH_MINRESONANCE,
  131. EAXAUTOWAH_MAXRESONANCE);
  132. }
  133. }; // ResonanceValidator
  134. struct PeakLevelValidator {
  135. void operator()(long lPeakLevel) const
  136. {
  137. eax_validate_range<Exception>(
  138. "Peak Level",
  139. lPeakLevel,
  140. EAXAUTOWAH_MINPEAKLEVEL,
  141. EAXAUTOWAH_MAXPEAKLEVEL);
  142. }
  143. }; // PeakLevelValidator
  144. struct AllValidator {
  145. void operator()(const Props& all) const
  146. {
  147. AttackTimeValidator{}(all.flAttackTime);
  148. ReleaseTimeValidator{}(all.flReleaseTime);
  149. ResonanceValidator{}(all.lResonance);
  150. PeakLevelValidator{}(all.lPeakLevel);
  151. }
  152. }; // AllValidator
  153. void set_defaults(Props& props) override;
  154. void set_efx_attack_time() noexcept;
  155. void set_efx_release_time() noexcept;
  156. void set_efx_resonance() noexcept;
  157. void set_efx_peak_gain() noexcept;
  158. void set_efx_defaults() override;
  159. void get(const EaxCall& call, const Props& props) override;
  160. void set(const EaxCall& call, Props& props) override;
  161. bool commit_props(const Props& props) override;
  162. }; // EaxAutoWahEffect
  163. EaxAutoWahEffect::EaxAutoWahEffect(const EaxCall& call)
  164. : EaxEffect4{AL_EFFECT_AUTOWAH, call}
  165. {}
  166. void EaxAutoWahEffect::set_defaults(Props& props)
  167. {
  168. props.flAttackTime = EAXAUTOWAH_DEFAULTATTACKTIME;
  169. props.flReleaseTime = EAXAUTOWAH_DEFAULTRELEASETIME;
  170. props.lResonance = EAXAUTOWAH_DEFAULTRESONANCE;
  171. props.lPeakLevel = EAXAUTOWAH_DEFAULTPEAKLEVEL;
  172. }
  173. void EaxAutoWahEffect::set_efx_attack_time() noexcept
  174. {
  175. al_effect_props_.Autowah.AttackTime = clamp(
  176. props_.flAttackTime,
  177. AL_AUTOWAH_MIN_ATTACK_TIME,
  178. AL_AUTOWAH_MAX_ATTACK_TIME);
  179. }
  180. void EaxAutoWahEffect::set_efx_release_time() noexcept
  181. {
  182. al_effect_props_.Autowah.ReleaseTime = clamp(
  183. props_.flReleaseTime,
  184. AL_AUTOWAH_MIN_RELEASE_TIME,
  185. AL_AUTOWAH_MAX_RELEASE_TIME);
  186. }
  187. void EaxAutoWahEffect::set_efx_resonance() noexcept
  188. {
  189. al_effect_props_.Autowah.Resonance = clamp(
  190. level_mb_to_gain(static_cast<float>(props_.lResonance)),
  191. AL_AUTOWAH_MIN_RESONANCE,
  192. AL_AUTOWAH_MAX_RESONANCE);
  193. }
  194. void EaxAutoWahEffect::set_efx_peak_gain() noexcept
  195. {
  196. al_effect_props_.Autowah.PeakGain = clamp(
  197. level_mb_to_gain(static_cast<float>(props_.lPeakLevel)),
  198. AL_AUTOWAH_MIN_PEAK_GAIN,
  199. AL_AUTOWAH_MAX_PEAK_GAIN);
  200. }
  201. void EaxAutoWahEffect::set_efx_defaults()
  202. {
  203. set_efx_attack_time();
  204. set_efx_release_time();
  205. set_efx_resonance();
  206. set_efx_peak_gain();
  207. }
  208. void EaxAutoWahEffect::get(const EaxCall& call, const Props& props)
  209. {
  210. switch (call.get_property_id())
  211. {
  212. case EAXAUTOWAH_NONE: break;
  213. case EAXAUTOWAH_ALLPARAMETERS: call.set_value<Exception>(props); break;
  214. case EAXAUTOWAH_ATTACKTIME: call.set_value<Exception>(props.flAttackTime); break;
  215. case EAXAUTOWAH_RELEASETIME: call.set_value<Exception>(props.flReleaseTime); break;
  216. case EAXAUTOWAH_RESONANCE: call.set_value<Exception>(props.lResonance); break;
  217. case EAXAUTOWAH_PEAKLEVEL: call.set_value<Exception>(props.lPeakLevel); break;
  218. default: fail_unknown_property_id();
  219. }
  220. }
  221. void EaxAutoWahEffect::set(const EaxCall& call, Props& props)
  222. {
  223. switch (call.get_property_id())
  224. {
  225. case EAXAUTOWAH_NONE: break;
  226. case EAXAUTOWAH_ALLPARAMETERS: defer<AllValidator>(call, props); break;
  227. case EAXAUTOWAH_ATTACKTIME: defer<AttackTimeValidator>(call, props.flAttackTime); break;
  228. case EAXAUTOWAH_RELEASETIME: defer<ReleaseTimeValidator>(call, props.flReleaseTime); break;
  229. case EAXAUTOWAH_RESONANCE: defer<ResonanceValidator>(call, props.lResonance); break;
  230. case EAXAUTOWAH_PEAKLEVEL: defer<PeakLevelValidator>(call, props.lPeakLevel); break;
  231. default: fail_unknown_property_id();
  232. }
  233. }
  234. bool EaxAutoWahEffect::commit_props(const Props& props)
  235. {
  236. auto is_dirty = false;
  237. if (props_.flAttackTime != props.flAttackTime)
  238. {
  239. is_dirty = true;
  240. set_efx_attack_time();
  241. }
  242. if (props_.flReleaseTime != props.flReleaseTime)
  243. {
  244. is_dirty = true;
  245. set_efx_release_time();
  246. }
  247. if (props_.lResonance != props.lResonance)
  248. {
  249. is_dirty = true;
  250. set_efx_resonance();
  251. }
  252. if (props_.lPeakLevel != props.lPeakLevel)
  253. {
  254. is_dirty = true;
  255. set_efx_peak_gain();
  256. }
  257. return is_dirty;
  258. }
  259. } // namespace
  260. EaxEffectUPtr eax_create_eax_auto_wah_effect(const EaxCall& call)
  261. {
  262. return eax_create_eax4_effect<EaxAutoWahEffect>(call);
  263. }
  264. #endif // ALSOFT_EAX