1 /**
2  * Copyright (c) 2006-2019 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 
26 namespace love
27 {
28 namespace audio
29 {
30 namespace openal
31 {
32 
33 //base class
Filter()34 Filter::Filter()
35 {
36 	generateFilter();
37 }
38 
Filter(const Filter & s)39 Filter::Filter(const Filter &s)
40 	: Filter()
41 {
42 	setParams(s.getParams());
43 }
44 
~Filter()45 Filter::~Filter()
46 {
47 	deleteFilter();
48 }
49 
clone()50 Filter *Filter::clone()
51 {
52 	return new Filter(*this);
53 }
54 
generateFilter()55 bool 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 
deleteFilter()74 void 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 
getFilter() const83 ALuint Filter::getFilter() const
84 {
85 	return filter;
86 }
87 
setParams(const std::map<Parameter,float> & params)88 bool 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 
getParams() const151 const std::map<Filter::Parameter, float> &Filter::getParams() const
152 {
153 	return params;
154 }
155 
getValue(Parameter in,float def) const156 float Filter::getValue(Parameter in, float def) const
157 {
158 	return params.find(in) == params.end() ? def : params.at(in);
159 }
160 
getValue(Parameter in,int def) const161 int 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