Check for a minimum PipeWire version
[openal-soft.git] / al / effects / compressor.cpp
blobbb5dfa3e43dc1bd6ffdf1a5afccd62221af3c7cc
2 #include "config.h"
4 #include "AL/al.h"
5 #include "AL/efx.h"
7 #include "alc/effects/base.h"
8 #include "effects.h"
10 #ifdef ALSOFT_EAX
11 #include "alnumeric.h"
13 #include "al/eax_exception.h"
14 #include "al/eax_utils.h"
15 #endif // ALSOFT_EAX
18 namespace {
20 void Compressor_setParami(EffectProps *props, ALenum param, int val)
22 switch(param)
24 case AL_COMPRESSOR_ONOFF:
25 if(!(val >= AL_COMPRESSOR_MIN_ONOFF && val <= AL_COMPRESSOR_MAX_ONOFF))
26 throw effect_exception{AL_INVALID_VALUE, "Compressor state out of range"};
27 props->Compressor.OnOff = (val != AL_FALSE);
28 break;
30 default:
31 throw effect_exception{AL_INVALID_ENUM, "Invalid compressor integer property 0x%04x",
32 param};
35 void Compressor_setParamiv(EffectProps *props, ALenum param, const int *vals)
36 { Compressor_setParami(props, param, vals[0]); }
37 void Compressor_setParamf(EffectProps*, ALenum param, float)
38 { throw effect_exception{AL_INVALID_ENUM, "Invalid compressor float property 0x%04x", param}; }
39 void Compressor_setParamfv(EffectProps*, ALenum param, const float*)
41 throw effect_exception{AL_INVALID_ENUM, "Invalid compressor float-vector property 0x%04x",
42 param};
45 void Compressor_getParami(const EffectProps *props, ALenum param, int *val)
47 switch(param)
49 case AL_COMPRESSOR_ONOFF:
50 *val = props->Compressor.OnOff;
51 break;
53 default:
54 throw effect_exception{AL_INVALID_ENUM, "Invalid compressor integer property 0x%04x",
55 param};
58 void Compressor_getParamiv(const EffectProps *props, ALenum param, int *vals)
59 { Compressor_getParami(props, param, vals); }
60 void Compressor_getParamf(const EffectProps*, ALenum param, float*)
61 { throw effect_exception{AL_INVALID_ENUM, "Invalid compressor float property 0x%04x", param}; }
62 void Compressor_getParamfv(const EffectProps*, ALenum param, float*)
64 throw effect_exception{AL_INVALID_ENUM, "Invalid compressor float-vector property 0x%04x",
65 param};
68 EffectProps genDefaultProps() noexcept
70 EffectProps props{};
71 props.Compressor.OnOff = AL_COMPRESSOR_DEFAULT_ONOFF;
72 return props;
75 } // namespace
77 DEFINE_ALEFFECT_VTABLE(Compressor);
79 const EffectProps CompressorEffectProps{genDefaultProps()};
81 #ifdef ALSOFT_EAX
82 namespace {
84 using EaxCompressorEffectDirtyFlagsValue = std::uint_least8_t;
86 struct EaxCompressorEffectDirtyFlags
88 using EaxIsBitFieldStruct = bool;
90 EaxCompressorEffectDirtyFlagsValue ulOnOff : 1;
91 }; // EaxCompressorEffectDirtyFlags
94 class EaxCompressorEffect final :
95 public EaxEffect
97 public:
98 EaxCompressorEffect();
101 void dispatch(const EaxEaxCall& eax_call) override;
103 // [[nodiscard]]
104 bool apply_deferred() override;
106 private:
107 EAXAGCCOMPRESSORPROPERTIES eax_{};
108 EAXAGCCOMPRESSORPROPERTIES eax_d_{};
109 EaxCompressorEffectDirtyFlags eax_dirty_flags_{};
112 void set_eax_defaults();
114 void set_efx_on_off();
115 void set_efx_defaults();
117 void get(const EaxEaxCall& eax_call);
119 void validate_on_off(unsigned long ulOnOff);
120 void validate_all(const EAXAGCCOMPRESSORPROPERTIES& eax_all);
122 void defer_on_off(unsigned long ulOnOff);
123 void defer_all(const EAXAGCCOMPRESSORPROPERTIES& eax_all);
125 void defer_on_off(const EaxEaxCall& eax_call);
126 void defer_all(const EaxEaxCall& eax_call);
128 void set(const EaxEaxCall& eax_call);
129 }; // EaxCompressorEffect
132 class EaxCompressorEffectException :
133 public EaxException
135 public:
136 explicit EaxCompressorEffectException(
137 const char* message)
139 EaxException{"EAX_COMPRESSOR_EFFECT", message}
142 }; // EaxCompressorEffectException
145 EaxCompressorEffect::EaxCompressorEffect()
146 : EaxEffect{AL_EFFECT_COMPRESSOR}
148 set_eax_defaults();
149 set_efx_defaults();
152 // [[nodiscard]]
153 void EaxCompressorEffect::dispatch(const EaxEaxCall& eax_call)
155 eax_call.is_get() ? get(eax_call) : set(eax_call);
158 void EaxCompressorEffect::set_eax_defaults()
160 eax_.ulOnOff = EAXAGCCOMPRESSOR_DEFAULTONOFF;
162 eax_d_ = eax_;
165 void EaxCompressorEffect::set_efx_on_off()
167 const auto on_off = clamp(
168 static_cast<ALint>(eax_.ulOnOff),
169 AL_COMPRESSOR_MIN_ONOFF,
170 AL_COMPRESSOR_MAX_ONOFF);
172 al_effect_props_.Compressor.OnOff = (on_off != AL_FALSE);
175 void EaxCompressorEffect::set_efx_defaults()
177 set_efx_on_off();
180 void EaxCompressorEffect::get(const EaxEaxCall& eax_call)
182 switch(eax_call.get_property_id())
184 case EAXAGCCOMPRESSOR_NONE:
185 break;
187 case EAXAGCCOMPRESSOR_ALLPARAMETERS:
188 eax_call.set_value<EaxCompressorEffectException>(eax_);
189 break;
191 case EAXAGCCOMPRESSOR_ONOFF:
192 eax_call.set_value<EaxCompressorEffectException>(eax_.ulOnOff);
193 break;
195 default:
196 throw EaxCompressorEffectException{"Unsupported property id."};
200 void EaxCompressorEffect::validate_on_off(
201 unsigned long ulOnOff)
203 eax_validate_range<EaxCompressorEffectException>(
204 "On-Off",
205 ulOnOff,
206 EAXAGCCOMPRESSOR_MINONOFF,
207 EAXAGCCOMPRESSOR_MAXONOFF);
210 void EaxCompressorEffect::validate_all(
211 const EAXAGCCOMPRESSORPROPERTIES& eax_all)
213 validate_on_off(eax_all.ulOnOff);
216 void EaxCompressorEffect::defer_on_off(
217 unsigned long ulOnOff)
219 eax_d_.ulOnOff = ulOnOff;
220 eax_dirty_flags_.ulOnOff = (eax_.ulOnOff != eax_d_.ulOnOff);
223 void EaxCompressorEffect::defer_all(
224 const EAXAGCCOMPRESSORPROPERTIES& eax_all)
226 defer_on_off(eax_all.ulOnOff);
229 void EaxCompressorEffect::defer_on_off(
230 const EaxEaxCall& eax_call)
232 const auto& on_off =
233 eax_call.get_value<EaxCompressorEffectException, const decltype(EAXAGCCOMPRESSORPROPERTIES::ulOnOff)>();
235 validate_on_off(on_off);
236 defer_on_off(on_off);
239 void EaxCompressorEffect::defer_all(
240 const EaxEaxCall& eax_call)
242 const auto& all =
243 eax_call.get_value<EaxCompressorEffectException, const EAXAGCCOMPRESSORPROPERTIES>();
245 validate_all(all);
246 defer_all(all);
249 // [[nodiscard]]
250 bool EaxCompressorEffect::apply_deferred()
252 if (eax_dirty_flags_ == EaxCompressorEffectDirtyFlags{})
254 return false;
257 eax_ = eax_d_;
259 if (eax_dirty_flags_.ulOnOff)
261 set_efx_on_off();
264 eax_dirty_flags_ = EaxCompressorEffectDirtyFlags{};
266 return true;
269 void EaxCompressorEffect::set(const EaxEaxCall& eax_call)
271 switch(eax_call.get_property_id())
273 case EAXAGCCOMPRESSOR_NONE:
274 break;
276 case EAXAGCCOMPRESSOR_ALLPARAMETERS:
277 defer_all(eax_call);
278 break;
280 case EAXAGCCOMPRESSOR_ONOFF:
281 defer_on_off(eax_call);
282 break;
284 default:
285 throw EaxCompressorEffectException{"Unsupported property id."};
289 } // namespace
291 EaxEffectUPtr eax_create_eax_compressor_effect()
293 return std::make_unique<EaxCompressorEffect>();
296 #endif // ALSOFT_EAX