autowah.cpp 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  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/effect.h"
  11. #include "al/eax/exception.h"
  12. #include "al/eax/utils.h"
  13. #endif // ALSOFT_EAX
  14. namespace {
  15. constexpr EffectProps genDefaultProps() noexcept
  16. {
  17. AutowahProps props{};
  18. props.AttackTime = AL_AUTOWAH_DEFAULT_ATTACK_TIME;
  19. props.ReleaseTime = AL_AUTOWAH_DEFAULT_RELEASE_TIME;
  20. props.Resonance = AL_AUTOWAH_DEFAULT_RESONANCE;
  21. props.PeakGain = AL_AUTOWAH_DEFAULT_PEAK_GAIN;
  22. return props;
  23. }
  24. } // namespace
  25. const EffectProps AutowahEffectProps{genDefaultProps()};
  26. void AutowahEffectHandler::SetParami(AutowahProps&, ALenum param, int)
  27. { throw effect_exception{AL_INVALID_ENUM, "Invalid autowah integer property 0x%04x", param}; }
  28. void AutowahEffectHandler::SetParamiv(AutowahProps&, ALenum param, const int*)
  29. {
  30. throw effect_exception{AL_INVALID_ENUM, "Invalid autowah integer vector property 0x%04x",
  31. param};
  32. }
  33. void AutowahEffectHandler::SetParamf(AutowahProps &props, ALenum param, float val)
  34. {
  35. switch(param)
  36. {
  37. case AL_AUTOWAH_ATTACK_TIME:
  38. if(!(val >= AL_AUTOWAH_MIN_ATTACK_TIME && val <= AL_AUTOWAH_MAX_ATTACK_TIME))
  39. throw effect_exception{AL_INVALID_VALUE, "Autowah attack time out of range"};
  40. props.AttackTime = val;
  41. break;
  42. case AL_AUTOWAH_RELEASE_TIME:
  43. if(!(val >= AL_AUTOWAH_MIN_RELEASE_TIME && val <= AL_AUTOWAH_MAX_RELEASE_TIME))
  44. throw effect_exception{AL_INVALID_VALUE, "Autowah release time out of range"};
  45. props.ReleaseTime = val;
  46. break;
  47. case AL_AUTOWAH_RESONANCE:
  48. if(!(val >= AL_AUTOWAH_MIN_RESONANCE && val <= AL_AUTOWAH_MAX_RESONANCE))
  49. throw effect_exception{AL_INVALID_VALUE, "Autowah resonance out of range"};
  50. props.Resonance = val;
  51. break;
  52. case AL_AUTOWAH_PEAK_GAIN:
  53. if(!(val >= AL_AUTOWAH_MIN_PEAK_GAIN && val <= AL_AUTOWAH_MAX_PEAK_GAIN))
  54. throw effect_exception{AL_INVALID_VALUE, "Autowah peak gain out of range"};
  55. props.PeakGain = val;
  56. break;
  57. default:
  58. throw effect_exception{AL_INVALID_ENUM, "Invalid autowah float property 0x%04x", param};
  59. }
  60. }
  61. void AutowahEffectHandler::SetParamfv(AutowahProps &props, ALenum param, const float *vals)
  62. { SetParamf(props, param, *vals); }
  63. void AutowahEffectHandler::GetParami(const AutowahProps&, ALenum param, int*)
  64. { throw effect_exception{AL_INVALID_ENUM, "Invalid autowah integer property 0x%04x", param}; }
  65. void AutowahEffectHandler::GetParamiv(const AutowahProps&, ALenum param, int*)
  66. {
  67. throw effect_exception{AL_INVALID_ENUM, "Invalid autowah integer vector property 0x%04x",
  68. param};
  69. }
  70. void AutowahEffectHandler::GetParamf(const AutowahProps &props, ALenum param, float *val)
  71. {
  72. switch(param)
  73. {
  74. case AL_AUTOWAH_ATTACK_TIME: *val = props.AttackTime; break;
  75. case AL_AUTOWAH_RELEASE_TIME: *val = props.ReleaseTime; break;
  76. case AL_AUTOWAH_RESONANCE: *val = props.Resonance; break;
  77. case AL_AUTOWAH_PEAK_GAIN: *val = props.PeakGain; break;
  78. default:
  79. throw effect_exception{AL_INVALID_ENUM, "Invalid autowah float property 0x%04x", param};
  80. }
  81. }
  82. void AutowahEffectHandler::GetParamfv(const AutowahProps &props, ALenum param, float *vals)
  83. { GetParamf(props, param, vals); }
  84. #ifdef ALSOFT_EAX
  85. namespace {
  86. using AutowahCommitter = EaxCommitter<EaxAutowahCommitter>;
  87. struct AttackTimeValidator {
  88. void operator()(float flAttackTime) const
  89. {
  90. eax_validate_range<AutowahCommitter::Exception>(
  91. "Attack Time",
  92. flAttackTime,
  93. EAXAUTOWAH_MINATTACKTIME,
  94. EAXAUTOWAH_MAXATTACKTIME);
  95. }
  96. }; // AttackTimeValidator
  97. struct ReleaseTimeValidator {
  98. void operator()(float flReleaseTime) const
  99. {
  100. eax_validate_range<AutowahCommitter::Exception>(
  101. "Release Time",
  102. flReleaseTime,
  103. EAXAUTOWAH_MINRELEASETIME,
  104. EAXAUTOWAH_MAXRELEASETIME);
  105. }
  106. }; // ReleaseTimeValidator
  107. struct ResonanceValidator {
  108. void operator()(long lResonance) const
  109. {
  110. eax_validate_range<AutowahCommitter::Exception>(
  111. "Resonance",
  112. lResonance,
  113. EAXAUTOWAH_MINRESONANCE,
  114. EAXAUTOWAH_MAXRESONANCE);
  115. }
  116. }; // ResonanceValidator
  117. struct PeakLevelValidator {
  118. void operator()(long lPeakLevel) const
  119. {
  120. eax_validate_range<AutowahCommitter::Exception>(
  121. "Peak Level",
  122. lPeakLevel,
  123. EAXAUTOWAH_MINPEAKLEVEL,
  124. EAXAUTOWAH_MAXPEAKLEVEL);
  125. }
  126. }; // PeakLevelValidator
  127. struct AllValidator {
  128. void operator()(const EAXAUTOWAHPROPERTIES& all) const
  129. {
  130. AttackTimeValidator{}(all.flAttackTime);
  131. ReleaseTimeValidator{}(all.flReleaseTime);
  132. ResonanceValidator{}(all.lResonance);
  133. PeakLevelValidator{}(all.lPeakLevel);
  134. }
  135. }; // AllValidator
  136. } // namespace
  137. template<>
  138. struct AutowahCommitter::Exception : public EaxException
  139. {
  140. explicit Exception(const char *message) : EaxException{"EAX_AUTOWAH_EFFECT", message}
  141. { }
  142. };
  143. template<>
  144. [[noreturn]] void AutowahCommitter::fail(const char *message)
  145. {
  146. throw Exception{message};
  147. }
  148. bool EaxAutowahCommitter::commit(const EAXAUTOWAHPROPERTIES &props)
  149. {
  150. if(auto *cur = std::get_if<EAXAUTOWAHPROPERTIES>(&mEaxProps); cur && *cur == props)
  151. return false;
  152. mEaxProps = props;
  153. mAlProps = [&]{
  154. AutowahProps ret{};
  155. ret.AttackTime = props.flAttackTime;
  156. ret.ReleaseTime = props.flReleaseTime;
  157. ret.Resonance = level_mb_to_gain(static_cast<float>(props.lResonance));
  158. ret.PeakGain = level_mb_to_gain(static_cast<float>(props.lPeakLevel));
  159. return ret;
  160. }();
  161. return true;
  162. }
  163. void EaxAutowahCommitter::SetDefaults(EaxEffectProps &props)
  164. {
  165. static constexpr EAXAUTOWAHPROPERTIES defprops{[]
  166. {
  167. EAXAUTOWAHPROPERTIES ret{};
  168. ret.flAttackTime = EAXAUTOWAH_DEFAULTATTACKTIME;
  169. ret.flReleaseTime = EAXAUTOWAH_DEFAULTRELEASETIME;
  170. ret.lResonance = EAXAUTOWAH_DEFAULTRESONANCE;
  171. ret.lPeakLevel = EAXAUTOWAH_DEFAULTPEAKLEVEL;
  172. return ret;
  173. }()};
  174. props = defprops;
  175. }
  176. void EaxAutowahCommitter::Get(const EaxCall &call, const EAXAUTOWAHPROPERTIES &props)
  177. {
  178. switch(call.get_property_id())
  179. {
  180. case EAXAUTOWAH_NONE: break;
  181. case EAXAUTOWAH_ALLPARAMETERS: call.set_value<Exception>(props); break;
  182. case EAXAUTOWAH_ATTACKTIME: call.set_value<Exception>(props.flAttackTime); break;
  183. case EAXAUTOWAH_RELEASETIME: call.set_value<Exception>(props.flReleaseTime); break;
  184. case EAXAUTOWAH_RESONANCE: call.set_value<Exception>(props.lResonance); break;
  185. case EAXAUTOWAH_PEAKLEVEL: call.set_value<Exception>(props.lPeakLevel); break;
  186. default: fail_unknown_property_id();
  187. }
  188. }
  189. void EaxAutowahCommitter::Set(const EaxCall &call, EAXAUTOWAHPROPERTIES &props)
  190. {
  191. switch(call.get_property_id())
  192. {
  193. case EAXAUTOWAH_NONE: break;
  194. case EAXAUTOWAH_ALLPARAMETERS: defer<AllValidator>(call, props); break;
  195. case EAXAUTOWAH_ATTACKTIME: defer<AttackTimeValidator>(call, props.flAttackTime); break;
  196. case EAXAUTOWAH_RELEASETIME: defer<ReleaseTimeValidator>(call, props.flReleaseTime); break;
  197. case EAXAUTOWAH_RESONANCE: defer<ResonanceValidator>(call, props.lResonance); break;
  198. case EAXAUTOWAH_PEAKLEVEL: defer<PeakLevelValidator>(call, props.lPeakLevel); break;
  199. default: fail_unknown_property_id();
  200. }
  201. }
  202. #endif // ALSOFT_EAX