1/**
2 * Copyright (c) 2006-2023 LOVE Development Team
3 *
4 * This software is provided 'as-is', without any express or implied
5 * warranty. In no event will the authors be held liable for any damages
6 * arising from the use of this software.
7 *
8 * Permission is granted to anyone to use this software for any purpose,
9 * including commercial applications, and to alter it and redistribute it
10 * freely, subject to the following restrictions:
11 *
12 * 1. The origin of this software must not be misrepresented; you must not
13 * claim that you wrote the original software. If you use this software
14 * in a product, an acknowledgment in the product documentation would be
15 * appreciated but is not required.
16 * 2. Altered source versions must be plainly marked as such, and must not be
17 * misrepresented as being the original software.
18 * 3. This notice may not be removed or altered from any source distribution.
19 **/
20
21#include "Filter.h"
22#include "common/Exception.h"
23
24#include <cmath>
25
26namespace love
27{
28namespace audio
29{
30namespace openal
31{
32
33//base class
34Filter::Filter()
35{
36 generateFilter();
37}
38
39Filter::Filter(const Filter &s)
40 : Filter()
41{
42 setParams(s.getParams());
43}
44
45Filter::~Filter()
46{
47 deleteFilter();
48}
49
50Filter *Filter::clone()
51{
52 return new Filter(*this);
53}
54
55bool Filter::generateFilter()
56{
57#ifdef ALC_EXT_EFX
58 if (!alGenFilters)
59 return false;
60
61 if (filter != AL_FILTER_NULL)
62 return true;
63
64 alGenFilters(1, &filter);
65 if (alGetError() != AL_NO_ERROR)
66 throw love::Exception("Failed to create sound Filter.");
67
68 return true;
69#else
70 return false;
71#endif
72}
73
74void Filter::deleteFilter()
75{
76#ifdef ALC_EXT_EFX
77 if (filter != AL_FILTER_NULL)
78 alDeleteFilters(1, &filter);
79#endif
80 filter = AL_FILTER_NULL;
81}
82
83ALuint Filter::getFilter() const
84{
85 return filter;
86}
87
88bool Filter::setParams(const std::map<Parameter, float> &params)
89{
90 this->params = params;
91 type = (Type)(int) this->params[FILTER_TYPE];
92
93 if (!generateFilter())
94 return false;
95
96#ifdef ALC_EXT_EFX
97 switch (type)
98 {
99 case TYPE_LOWPASS:
100 alFilteri(filter, AL_FILTER_TYPE, AL_FILTER_LOWPASS);
101 break;
102 case TYPE_HIGHPASS:
103 alFilteri(filter, AL_FILTER_TYPE, AL_FILTER_HIGHPASS);
104 break;
105 case TYPE_BANDPASS:
106 alFilteri(filter, AL_FILTER_TYPE, AL_FILTER_BANDPASS);
107 break;
108 case TYPE_BASIC:
109 case TYPE_MAX_ENUM:
110 break;
111 }
112
113 //failed to make filter specific type - not supported etc.
114 if (alGetError() != AL_NO_ERROR)
115 {
116 deleteFilter();
117 return false;
118 }
119
120#define clampf(v,l,h) fmax(fmin((v),(h)),(l))
121#define PARAMSTR(i,e,v) filter,AL_##e##_##v,clampf(getValue(i,AL_##e##_DEFAULT_##v),AL_##e##_MIN_##v,AL_##e##_MAX_##v)
122 switch (type)
123 {
124 case TYPE_LOWPASS:
125 alFilterf(PARAMSTR(FILTER_VOLUME,LOWPASS,GAIN));
126 alFilterf(PARAMSTR(FILTER_HIGHGAIN,LOWPASS,GAINHF));
127 break;
128 case TYPE_HIGHPASS:
129 alFilterf(PARAMSTR(FILTER_VOLUME,HIGHPASS,GAIN));
130 alFilterf(PARAMSTR(FILTER_LOWGAIN,HIGHPASS,GAINLF));
131 break;
132 case TYPE_BANDPASS:
133 alFilterf(PARAMSTR(FILTER_VOLUME,BANDPASS,GAIN));
134 alFilterf(PARAMSTR(FILTER_LOWGAIN,BANDPASS,GAINLF));
135 alFilterf(PARAMSTR(FILTER_HIGHGAIN,BANDPASS,GAINHF));
136 break;
137 case TYPE_BASIC:
138 case TYPE_MAX_ENUM:
139 break;
140 }
141#undef clampf
142#undef PARAMSTR
143 //alGetError();
144
145 return true;
146#else
147 return false;
148#endif
149}
150
151const std::map<Filter::Parameter, float> &Filter::getParams() const
152{
153 return params;
154}
155
156float Filter::getValue(Parameter in, float def) const
157{
158 return params.find(in) == params.end() ? def : params.at(in);
159}
160
161int Filter::getValue(Parameter in, int def) const
162{
163 return params.find(in) == params.end() ? def : static_cast<int>(params.at(in));
164}
165
166} //openal
167} //audio
168} //love
169