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

296 lines
6.8 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 Compressor_setParami(EffectProps *props, ALenum param, int val)
  13. {
  14. switch(param)
  15. {
  16. case AL_COMPRESSOR_ONOFF:
  17. if(!(val >= AL_COMPRESSOR_MIN_ONOFF && val <= AL_COMPRESSOR_MAX_ONOFF))
  18. throw effect_exception{AL_INVALID_VALUE, "Compressor state out of range"};
  19. props->Compressor.OnOff = (val != AL_FALSE);
  20. break;
  21. default:
  22. throw effect_exception{AL_INVALID_ENUM, "Invalid compressor integer property 0x%04x",
  23. param};
  24. }
  25. }
  26. void Compressor_setParamiv(EffectProps *props, ALenum param, const int *vals)
  27. { Compressor_setParami(props, param, vals[0]); }
  28. void Compressor_setParamf(EffectProps*, ALenum param, float)
  29. { throw effect_exception{AL_INVALID_ENUM, "Invalid compressor float property 0x%04x", param}; }
  30. void Compressor_setParamfv(EffectProps*, ALenum param, const float*)
  31. {
  32. throw effect_exception{AL_INVALID_ENUM, "Invalid compressor float-vector property 0x%04x",
  33. param};
  34. }
  35. void Compressor_getParami(const EffectProps *props, ALenum param, int *val)
  36. {
  37. switch(param)
  38. {
  39. case AL_COMPRESSOR_ONOFF:
  40. *val = props->Compressor.OnOff;
  41. break;
  42. default:
  43. throw effect_exception{AL_INVALID_ENUM, "Invalid compressor integer property 0x%04x",
  44. param};
  45. }
  46. }
  47. void Compressor_getParamiv(const EffectProps *props, ALenum param, int *vals)
  48. { Compressor_getParami(props, param, vals); }
  49. void Compressor_getParamf(const EffectProps*, ALenum param, float*)
  50. { throw effect_exception{AL_INVALID_ENUM, "Invalid compressor float property 0x%04x", param}; }
  51. void Compressor_getParamfv(const EffectProps*, ALenum param, float*)
  52. {
  53. throw effect_exception{AL_INVALID_ENUM, "Invalid compressor float-vector property 0x%04x",
  54. param};
  55. }
  56. EffectProps genDefaultProps() noexcept
  57. {
  58. EffectProps props{};
  59. props.Compressor.OnOff = AL_COMPRESSOR_DEFAULT_ONOFF;
  60. return props;
  61. }
  62. } // namespace
  63. DEFINE_ALEFFECT_VTABLE(Compressor);
  64. const EffectProps CompressorEffectProps{genDefaultProps()};
  65. #ifdef ALSOFT_EAX
  66. namespace {
  67. using EaxCompressorEffectDirtyFlagsValue = std::uint_least8_t;
  68. struct EaxCompressorEffectDirtyFlags
  69. {
  70. using EaxIsBitFieldStruct = bool;
  71. EaxCompressorEffectDirtyFlagsValue ulOnOff : 1;
  72. }; // EaxCompressorEffectDirtyFlags
  73. class EaxCompressorEffect final :
  74. public EaxEffect
  75. {
  76. public:
  77. EaxCompressorEffect();
  78. void dispatch(const EaxEaxCall& eax_call) override;
  79. // [[nodiscard]]
  80. bool apply_deferred() override;
  81. private:
  82. EAXAGCCOMPRESSORPROPERTIES eax_{};
  83. EAXAGCCOMPRESSORPROPERTIES eax_d_{};
  84. EaxCompressorEffectDirtyFlags eax_dirty_flags_{};
  85. void set_eax_defaults();
  86. void set_efx_on_off();
  87. void set_efx_defaults();
  88. void get(const EaxEaxCall& eax_call);
  89. void validate_on_off(unsigned long ulOnOff);
  90. void validate_all(const EAXAGCCOMPRESSORPROPERTIES& eax_all);
  91. void defer_on_off(unsigned long ulOnOff);
  92. void defer_all(const EAXAGCCOMPRESSORPROPERTIES& eax_all);
  93. void defer_on_off(const EaxEaxCall& eax_call);
  94. void defer_all(const EaxEaxCall& eax_call);
  95. void set(const EaxEaxCall& eax_call);
  96. }; // EaxCompressorEffect
  97. class EaxCompressorEffectException :
  98. public EaxException
  99. {
  100. public:
  101. explicit EaxCompressorEffectException(
  102. const char* message)
  103. :
  104. EaxException{"EAX_COMPRESSOR_EFFECT", message}
  105. {
  106. }
  107. }; // EaxCompressorEffectException
  108. EaxCompressorEffect::EaxCompressorEffect()
  109. : EaxEffect{AL_EFFECT_COMPRESSOR}
  110. {
  111. set_eax_defaults();
  112. set_efx_defaults();
  113. }
  114. // [[nodiscard]]
  115. void EaxCompressorEffect::dispatch(const EaxEaxCall& eax_call)
  116. {
  117. eax_call.is_get() ? get(eax_call) : set(eax_call);
  118. }
  119. void EaxCompressorEffect::set_eax_defaults()
  120. {
  121. eax_.ulOnOff = EAXAGCCOMPRESSOR_DEFAULTONOFF;
  122. eax_d_ = eax_;
  123. }
  124. void EaxCompressorEffect::set_efx_on_off()
  125. {
  126. const auto on_off = clamp(
  127. static_cast<ALint>(eax_.ulOnOff),
  128. AL_COMPRESSOR_MIN_ONOFF,
  129. AL_COMPRESSOR_MAX_ONOFF);
  130. al_effect_props_.Compressor.OnOff = (on_off != AL_FALSE);
  131. }
  132. void EaxCompressorEffect::set_efx_defaults()
  133. {
  134. set_efx_on_off();
  135. }
  136. void EaxCompressorEffect::get(const EaxEaxCall& eax_call)
  137. {
  138. switch(eax_call.get_property_id())
  139. {
  140. case EAXAGCCOMPRESSOR_NONE:
  141. break;
  142. case EAXAGCCOMPRESSOR_ALLPARAMETERS:
  143. eax_call.set_value<EaxCompressorEffectException>(eax_);
  144. break;
  145. case EAXAGCCOMPRESSOR_ONOFF:
  146. eax_call.set_value<EaxCompressorEffectException>(eax_.ulOnOff);
  147. break;
  148. default:
  149. throw EaxCompressorEffectException{"Unsupported property id."};
  150. }
  151. }
  152. void EaxCompressorEffect::validate_on_off(
  153. unsigned long ulOnOff)
  154. {
  155. eax_validate_range<EaxCompressorEffectException>(
  156. "On-Off",
  157. ulOnOff,
  158. EAXAGCCOMPRESSOR_MINONOFF,
  159. EAXAGCCOMPRESSOR_MAXONOFF);
  160. }
  161. void EaxCompressorEffect::validate_all(
  162. const EAXAGCCOMPRESSORPROPERTIES& eax_all)
  163. {
  164. validate_on_off(eax_all.ulOnOff);
  165. }
  166. void EaxCompressorEffect::defer_on_off(
  167. unsigned long ulOnOff)
  168. {
  169. eax_d_.ulOnOff = ulOnOff;
  170. eax_dirty_flags_.ulOnOff = (eax_.ulOnOff != eax_d_.ulOnOff);
  171. }
  172. void EaxCompressorEffect::defer_all(
  173. const EAXAGCCOMPRESSORPROPERTIES& eax_all)
  174. {
  175. defer_on_off(eax_all.ulOnOff);
  176. }
  177. void EaxCompressorEffect::defer_on_off(
  178. const EaxEaxCall& eax_call)
  179. {
  180. const auto& on_off =
  181. eax_call.get_value<EaxCompressorEffectException, const decltype(EAXAGCCOMPRESSORPROPERTIES::ulOnOff)>();
  182. validate_on_off(on_off);
  183. defer_on_off(on_off);
  184. }
  185. void EaxCompressorEffect::defer_all(
  186. const EaxEaxCall& eax_call)
  187. {
  188. const auto& all =
  189. eax_call.get_value<EaxCompressorEffectException, const EAXAGCCOMPRESSORPROPERTIES>();
  190. validate_all(all);
  191. defer_all(all);
  192. }
  193. // [[nodiscard]]
  194. bool EaxCompressorEffect::apply_deferred()
  195. {
  196. if (eax_dirty_flags_ == EaxCompressorEffectDirtyFlags{})
  197. {
  198. return false;
  199. }
  200. eax_ = eax_d_;
  201. if (eax_dirty_flags_.ulOnOff)
  202. {
  203. set_efx_on_off();
  204. }
  205. eax_dirty_flags_ = EaxCompressorEffectDirtyFlags{};
  206. return true;
  207. }
  208. void EaxCompressorEffect::set(const EaxEaxCall& eax_call)
  209. {
  210. switch(eax_call.get_property_id())
  211. {
  212. case EAXAGCCOMPRESSOR_NONE:
  213. break;
  214. case EAXAGCCOMPRESSOR_ALLPARAMETERS:
  215. defer_all(eax_call);
  216. break;
  217. case EAXAGCCOMPRESSOR_ONOFF:
  218. defer_on_off(eax_call);
  219. break;
  220. default:
  221. throw EaxCompressorEffectException{"Unsupported property id."};
  222. }
  223. }
  224. } // namespace
  225. EaxEffectUPtr eax_create_eax_compressor_effect()
  226. {
  227. return std::make_unique<EaxCompressorEffect>();
  228. }
  229. #endif // ALSOFT_EAX