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 "Effect.h"
22#include "common/Exception.h"
23
24#include <cmath>
25#include <iostream>
26
27namespace love
28{
29namespace audio
30{
31namespace openal
32{
33
34//base class
35Effect::Effect()
36{
37 generateEffect();
38}
39
40Effect::Effect(const Effect &s)
41 : Effect()
42{
43 setParams(s.getParams());
44}
45
46Effect::~Effect()
47{
48 deleteEffect();
49}
50
51Effect *Effect::clone()
52{
53 return new Effect(*this);
54}
55
56bool Effect::generateEffect()
57{
58#ifdef ALC_EXT_EFX
59 if (!alGenEffects)
60 return false;
61
62 if (effect != AL_EFFECT_NULL)
63 return true;
64
65 alGenEffects(1, &effect);
66 if (alGetError() != AL_NO_ERROR)
67 throw love::Exception("Failed to create sound Effect.");
68
69 return true;
70#else
71 return false;
72#endif
73}
74
75void Effect::deleteEffect()
76{
77#ifdef ALC_EXT_EFX
78 if (effect != AL_EFFECT_NULL)
79 alDeleteEffects(1, &effect);
80#endif
81 effect = AL_EFFECT_NULL;
82}
83
84ALuint Effect::getEffect() const
85{
86 return effect;
87}
88
89bool Effect::setParams(const std::map<Parameter, float> &params)
90{
91 this->params = params;
92 type = (Type)(int) this->params[EFFECT_TYPE];
93
94 if (!generateEffect())
95 return false;
96
97#ifdef ALC_EXT_EFX
98 //parameter table without EFFECT_TYPE entry is illegal
99 switch (type)
100 {
101 case TYPE_REVERB:
102 alEffecti(effect, AL_EFFECT_TYPE, AL_EFFECT_REVERB);
103 break;
104 case TYPE_CHORUS:
105 alEffecti(effect, AL_EFFECT_TYPE, AL_EFFECT_CHORUS);
106 break;
107 case TYPE_DISTORTION:
108 alEffecti(effect, AL_EFFECT_TYPE, AL_EFFECT_DISTORTION);
109 break;
110 case TYPE_ECHO:
111 alEffecti(effect, AL_EFFECT_TYPE, AL_EFFECT_ECHO);
112 break;
113 case TYPE_FLANGER:
114 alEffecti(effect, AL_EFFECT_TYPE, AL_EFFECT_FLANGER);
115 break;
116/*
117 case TYPE_FREQSHIFTER:
118 alEffecti(effect, AL_EFFECT_TYPE, AL_EFFECT_FREQUENCY_SHIFTER);
119 break;
120 case TYPE_MORPHER:
121 alEffecti(effect, AL_EFFECT_TYPE, AL_EFFECT_VOCAL_MORPHER);
122 break;
123 case TYPE_PITCHSHIFTER:
124 alEffecti(effect, AL_EFFECT_TYPE, AL_EFFECT_PITCH_SHIFTER);
125 break;
126*/
127 case TYPE_MODULATOR:
128 alEffecti(effect, AL_EFFECT_TYPE, AL_EFFECT_RING_MODULATOR);
129 break;
130/*
131 case TYPE_AUTOWAH:
132 alEffecti(effect, AL_EFFECT_TYPE, AL_EFFECT_AUTOWAH);
133 break;
134*/
135 case TYPE_COMPRESSOR:
136 alEffecti(effect, AL_EFFECT_TYPE, AL_EFFECT_COMPRESSOR);
137 break;
138 case TYPE_EQUALIZER:
139 alEffecti(effect, AL_EFFECT_TYPE, AL_EFFECT_EQUALIZER);
140 break;
141 case TYPE_BASIC:
142 case TYPE_MAX_ENUM:
143 break;
144 }
145
146 //failed to make effect specific type - not supported etc.
147 if (alGetError() != AL_NO_ERROR)
148 {
149 deleteEffect();
150 return false;
151 }
152
153#define clampf(v,l,h) fmax(fmin((v),(h)),(l))
154#define PARAMSTR(i,e,v) effect,AL_##e##_##v,clampf(getValue(i,AL_##e##_DEFAULT_##v),AL_##e##_MIN_##v,AL_##e##_MAX_##v)
155 switch (type)
156 {
157 case TYPE_REVERB:
158 {
159 alEffectf(PARAMSTR(REVERB_GAIN,REVERB,GAIN));
160 alEffectf(PARAMSTR(REVERB_HFGAIN,REVERB,GAINHF));
161 alEffectf(PARAMSTR(REVERB_DENSITY,REVERB,DENSITY));
162 alEffectf(PARAMSTR(REVERB_DIFFUSION,REVERB,DIFFUSION));
163 alEffectf(PARAMSTR(REVERB_DECAY,REVERB,DECAY_TIME));
164 alEffectf(PARAMSTR(REVERB_HFDECAY,REVERB,DECAY_HFRATIO));
165 alEffectf(PARAMSTR(REVERB_EARLYGAIN,REVERB,REFLECTIONS_GAIN));
166 alEffectf(PARAMSTR(REVERB_EARLYDELAY,REVERB,REFLECTIONS_DELAY));
167 alEffectf(PARAMSTR(REVERB_LATEGAIN,REVERB,LATE_REVERB_GAIN));
168 alEffectf(PARAMSTR(REVERB_LATEDELAY,REVERB,LATE_REVERB_DELAY));;
169 alEffectf(PARAMSTR(REVERB_ROLLOFF,REVERB,ROOM_ROLLOFF_FACTOR));
170 alEffectf(PARAMSTR(REVERB_AIRHFGAIN,REVERB,AIR_ABSORPTION_GAINHF));
171 alEffecti(effect, AL_REVERB_DECAY_HFLIMIT, getValue(REVERB_HFLIMITER, 0));
172 break;
173 }
174 case TYPE_CHORUS:
175 {
176 Waveform wave = static_cast<Waveform>(getValue(CHORUS_WAVEFORM, static_cast<int>(WAVE_MAX_ENUM)));
177 if (wave == WAVE_SINE)
178 alEffecti(effect, AL_CHORUS_WAVEFORM, AL_CHORUS_WAVEFORM_SINUSOID);
179 else if (wave == WAVE_TRIANGLE)
180 alEffecti(effect, AL_CHORUS_WAVEFORM, AL_CHORUS_WAVEFORM_TRIANGLE);
181 else
182 alEffecti(effect, AL_CHORUS_WAVEFORM, AL_CHORUS_DEFAULT_WAVEFORM);
183
184 alEffecti(PARAMSTR(CHORUS_PHASE,CHORUS,PHASE));
185 alEffectf(PARAMSTR(CHORUS_RATE,CHORUS,RATE));
186 alEffectf(PARAMSTR(CHORUS_DEPTH,CHORUS,DEPTH));
187 alEffectf(PARAMSTR(CHORUS_FEEDBACK,CHORUS,FEEDBACK));
188 alEffectf(PARAMSTR(CHORUS_DELAY,CHORUS,DELAY));
189 break;
190 }
191 case TYPE_DISTORTION:
192 alEffectf(PARAMSTR(DISTORTION_GAIN,DISTORTION,GAIN));
193 alEffectf(PARAMSTR(DISTORTION_EDGE,DISTORTION,EDGE));
194 alEffectf(PARAMSTR(DISTORTION_LOWCUT,DISTORTION,LOWPASS_CUTOFF));
195 alEffectf(PARAMSTR(DISTORTION_EQCENTER,DISTORTION,EQCENTER));
196 alEffectf(PARAMSTR(DISTORTION_EQBAND,DISTORTION,EQBANDWIDTH));
197 break;
198
199 case TYPE_ECHO:
200 alEffectf(PARAMSTR(ECHO_DELAY,ECHO,DELAY));
201 alEffectf(PARAMSTR(ECHO_LRDELAY,ECHO,LRDELAY));
202 alEffectf(PARAMSTR(ECHO_DAMPING,ECHO,DAMPING));
203 alEffectf(PARAMSTR(ECHO_FEEDBACK,ECHO,FEEDBACK));
204 alEffectf(PARAMSTR(ECHO_SPREAD,ECHO,SPREAD));
205 break;
206
207 case TYPE_FLANGER:
208 {
209 Waveform wave = static_cast<Waveform>(getValue(FLANGER_WAVEFORM, static_cast<int>(WAVE_MAX_ENUM)));
210 if (wave == WAVE_SINE)
211 alEffecti(effect, AL_FLANGER_WAVEFORM, AL_FLANGER_WAVEFORM_SINUSOID);
212 else if (wave == WAVE_TRIANGLE)
213 alEffecti(effect, AL_FLANGER_WAVEFORM, AL_FLANGER_WAVEFORM_TRIANGLE);
214 else
215 alEffecti(effect, AL_FLANGER_WAVEFORM, AL_FLANGER_DEFAULT_WAVEFORM);
216
217 alEffecti(PARAMSTR(FLANGER_PHASE,FLANGER,PHASE));
218 alEffectf(PARAMSTR(FLANGER_RATE,FLANGER,RATE));
219 alEffectf(PARAMSTR(FLANGER_DEPTH,FLANGER,DEPTH));
220 alEffectf(PARAMSTR(FLANGER_FEEDBACK,FLANGER,FEEDBACK));
221 alEffectf(PARAMSTR(FLANGER_DELAY,FLANGER,DELAY));
222 break;
223 }
224/*
225 case TYPE_FREQSHIFTER:
226 {
227 alEffectf(PARAMSTR(FREQSHIFTER_FREQ,FREQUENCY_SHIFTER,FREQUENCY));
228
229 Direction dir = static_cast<Direction>(getValue(FREQSHIFTER_LEFTDIR, static_cast<int>(DIR_MAX_ENUM)));
230 if (dir == DIR_NONE)
231 alEffecti(effect, AL_FREQUENCY_SHIFTER_LEFT_DIRECTION, AL_FREQUENCY_SHIFTER_DIRECTION_OFF);
232 else if(dir == DIR_UP)
233 alEffecti(effect, AL_FREQUENCY_SHIFTER_LEFT_DIRECTION, AL_FREQUENCY_SHIFTER_DIRECTION_UP);
234 else if(dir == DIR_DOWN)
235 alEffecti(effect, AL_FREQUENCY_SHIFTER_LEFT_DIRECTION, AL_FREQUENCY_SHIFTER_DIRECTION_DOWN);
236 else
237 alEffecti(effect, AL_FREQUENCY_SHIFTER_LEFT_DIRECTION, AL_FREQUENCY_SHIFTER_DEFAULT_LEFT_DIRECTION);
238
239 dir = static_cast<Direction>(getValue(FREQSHIFTER_RIGHTDIR, static_cast<int>(DIR_MAX_ENUM)));
240 if (dir == DIR_NONE)
241 alEffecti(effect, AL_FREQUENCY_SHIFTER_RIGHT_DIRECTION, AL_FREQUENCY_SHIFTER_DIRECTION_OFF);
242 else if(dir == DIR_UP)
243 alEffecti(effect, AL_FREQUENCY_SHIFTER_RIGHT_DIRECTION, AL_FREQUENCY_SHIFTER_DIRECTION_UP);
244 else if(dir == DIR_DOWN)
245 alEffecti(effect, AL_FREQUENCY_SHIFTER_RIGHT_DIRECTION, AL_FREQUENCY_SHIFTER_DIRECTION_DOWN);
246 else
247 alEffecti(effect, AL_FREQUENCY_SHIFTER_RIGHT_DIRECTION, AL_FREQUENCY_SHIFTER_DEFAULT_RIGHT_DIRECTION);
248 break;
249 }
250 case TYPE_MORPHER:
251 {
252 Waveform wave = static_cast<Waveform>(getValue(MORPHER_WAVEFORM, static_cast<int>(WAVE_MAX_ENUM)));
253 if (wave == WAVE_SINE)
254 alEffecti(effect, AL_VOCAL_MORPHER_WAVEFORM, AL_VOCAL_MORPHER_WAVEFORM_SINUSOID);
255 else if (wave == WAVE_TRIANGLE)
256 alEffecti(effect, AL_VOCAL_MORPHER_WAVEFORM, AL_VOCAL_MORPHER_WAVEFORM_TRIANGLE);
257 else if (wave == WAVE_SAWTOOTH)
258 alEffecti(effect, AL_VOCAL_MORPHER_WAVEFORM, AL_VOCAL_MORPHER_WAVEFORM_SAWTOOTH);
259 else
260 alEffecti(effect, AL_VOCAL_MORPHER_WAVEFORM, AL_VOCAL_MORPHER_DEFAULT_WAVEFORM);
261
262 Phoneme phoneme = static_cast<Phoneme>(getValue(MORPHER_PHONEMEA, static_cast<int>(PHONEME_MAX_ENUM)));
263 if (phoneme == PHONEME_MAX_ENUM)
264 alEffecti(effect, AL_VOCAL_MORPHER_PHONEMEA, AL_VOCAL_MORPHER_DEFAULT_PHONEMEA);
265 else
266 alEffecti(effect, AL_VOCAL_MORPHER_PHONEMEA, phonemeMap[phoneme]);
267
268 phoneme = static_cast<Phoneme>(getValue(MORPHER_PHONEMEB, static_cast<int>(PHONEME_MAX_ENUM)));
269 if (phoneme == PHONEME_MAX_ENUM)
270 alEffecti(effect, AL_VOCAL_MORPHER_PHONEMEB, AL_VOCAL_MORPHER_DEFAULT_PHONEMEB);
271 else
272 alEffecti(effect, AL_VOCAL_MORPHER_PHONEMEB, phonemeMap[phoneme]);
273
274 alEffectf(PARAMSTR(MORPHER_RATE,VOCAL_MORPHER,RATE));
275 alEffecti(PARAMSTR(MORPHER_TUNEA,VOCAL_MORPHER,PHONEMEA_COARSE_TUNING));
276 alEffecti(PARAMSTR(MORPHER_TUNEB,VOCAL_MORPHER,PHONEMEB_COARSE_TUNING));
277 break;
278 }
279 case TYPE_PITCHSHIFTER:
280 {
281 float tune = getValue(PITCHSHIFTER_PITCH, (float)AL_PITCH_SHIFTER_DEFAULT_COARSE_TUNE + (float)(AL_PITCH_SHIFTER_DEFAULT_FINE_TUNE - 50) / 100.0 );
282
283 int coarse = (int)floor(tune);
284 int fine = (int)(fmod(tune, 1.0)*100.0);
285 if (fine > 50)
286 {
287 fine -= 100;
288 coarse += 1;
289 }
290 else if (fine < -50)
291 {
292 fine += 100;
293 coarse -= 1;
294 }
295 if (coarse > AL_PITCH_SHIFTER_MAX_COARSE_TUNE)
296 {
297 coarse = AL_PITCH_SHIFTER_MAX_COARSE_TUNE;
298 fine = AL_PITCH_SHIFTER_MAX_FINE_TUNE;
299 }
300 else if (coarse < AL_PITCH_SHIFTER_MIN_COARSE_TUNE)
301 {
302 coarse = AL_PITCH_SHIFTER_MIN_COARSE_TUNE;
303 fine = AL_PITCH_SHIFTER_MIN_FINE_TUNE;
304 }
305 alEffecti(effect, AL_PITCH_SHIFTER_COARSE_TUNE, coarse);
306 alEffecti(effect, AL_PITCH_SHIFTER_FINE_TUNE, fine);
307 break;
308 }
309*/
310 case TYPE_MODULATOR:
311 {
312 Waveform wave = static_cast<Waveform>(getValue(MODULATOR_WAVEFORM,static_cast<int>(WAVE_MAX_ENUM)));
313 if (wave == WAVE_SINE)
314 alEffecti(effect, AL_RING_MODULATOR_WAVEFORM, AL_RING_MODULATOR_SINUSOID);
315 else if (wave == WAVE_SAWTOOTH)
316 alEffecti(effect, AL_RING_MODULATOR_WAVEFORM, AL_RING_MODULATOR_SAWTOOTH);
317 else if (wave == WAVE_SQUARE)
318 alEffecti(effect, AL_RING_MODULATOR_WAVEFORM, AL_RING_MODULATOR_SQUARE);
319 else
320 alEffecti(effect, AL_RING_MODULATOR_WAVEFORM, AL_RING_MODULATOR_DEFAULT_WAVEFORM);
321
322 alEffectf(PARAMSTR(MODULATOR_FREQ,RING_MODULATOR,FREQUENCY));
323 alEffectf(PARAMSTR(MODULATOR_HIGHCUT,RING_MODULATOR,HIGHPASS_CUTOFF));
324 break;
325 }
326/*
327 case TYPE_AUTOWAH:
328 alEffectf(PARAMSTR(AUTOWAH_ATTACK,AUTOWAH,ATTACK_TIME));
329 alEffectf(PARAMSTR(AUTOWAH_RELEASE,AUTOWAH,RELEASE_TIME));
330 alEffectf(PARAMSTR(AUTOWAH_RESONANCE,AUTOWAH,RESONANCE));
331 alEffectf(PARAMSTR(AUTOWAH_PEAKGAIN,AUTOWAH,PEAK_GAIN));
332 break;
333*/
334 case TYPE_COMPRESSOR:
335 alEffecti(effect, AL_COMPRESSOR_ONOFF, getValue(COMPRESSOR_ENABLE,static_cast<int>(AL_COMPRESSOR_DEFAULT_ONOFF)));
336 break;
337
338 case TYPE_EQUALIZER:
339 alEffectf(PARAMSTR(EQUALIZER_LOWGAIN,EQUALIZER,LOW_GAIN));
340 alEffectf(PARAMSTR(EQUALIZER_LOWCUT,EQUALIZER,LOW_CUTOFF));
341 alEffectf(PARAMSTR(EQUALIZER_MID1GAIN,EQUALIZER,MID1_GAIN));
342 alEffectf(PARAMSTR(EQUALIZER_MID1FREQ,EQUALIZER,MID1_CENTER));
343 alEffectf(PARAMSTR(EQUALIZER_MID1BAND,EQUALIZER,MID1_WIDTH));
344 alEffectf(PARAMSTR(EQUALIZER_MID2GAIN,EQUALIZER,MID2_GAIN));
345 alEffectf(PARAMSTR(EQUALIZER_MID2FREQ,EQUALIZER,MID2_CENTER));
346 alEffectf(PARAMSTR(EQUALIZER_MID2BAND,EQUALIZER,MID2_WIDTH));
347 alEffectf(PARAMSTR(EQUALIZER_HIGHGAIN,EQUALIZER,HIGH_GAIN));
348 alEffectf(PARAMSTR(EQUALIZER_HIGHCUT,EQUALIZER,HIGH_CUTOFF));
349 break;
350 case TYPE_BASIC:
351 case TYPE_MAX_ENUM:
352 break;
353 }
354#undef PARAMSTR
355#undef clampf
356 //alGetError();
357
358 return true;
359#else
360 return false;
361#endif //ALC_EXT_EFX
362}
363
364const std::map<Effect::Parameter, float> &Effect::getParams() const
365{
366 return params;
367}
368
369float Effect::getValue(Parameter in, float def) const
370{
371 return params.find(in) == params.end() ? def : params.at(in);
372}
373
374int Effect::getValue(Parameter in, int def) const
375{
376 return params.find(in) == params.end() ? def : static_cast<int>(params.at(in));
377}
378
379/*
380std::map<Effect::Phoneme, ALint> Effect::phonemeMap =
381{
382 {Effect::PHONEME_A, AL_VOCAL_MORPHER_PHONEME_A},
383 {Effect::PHONEME_E, AL_VOCAL_MORPHER_PHONEME_E},
384 {Effect::PHONEME_I, AL_VOCAL_MORPHER_PHONEME_I},
385 {Effect::PHONEME_O, AL_VOCAL_MORPHER_PHONEME_O},
386 {Effect::PHONEME_U, AL_VOCAL_MORPHER_PHONEME_U},
387 {Effect::PHONEME_AA, AL_VOCAL_MORPHER_PHONEME_AA},
388 {Effect::PHONEME_AE, AL_VOCAL_MORPHER_PHONEME_AE},
389 {Effect::PHONEME_AH, AL_VOCAL_MORPHER_PHONEME_AH},
390 {Effect::PHONEME_AO, AL_VOCAL_MORPHER_PHONEME_AO},
391 {Effect::PHONEME_EH, AL_VOCAL_MORPHER_PHONEME_EH},
392 {Effect::PHONEME_ER, AL_VOCAL_MORPHER_PHONEME_ER},
393 {Effect::PHONEME_IH, AL_VOCAL_MORPHER_PHONEME_IH},
394 {Effect::PHONEME_IY, AL_VOCAL_MORPHER_PHONEME_IY},
395 {Effect::PHONEME_UH, AL_VOCAL_MORPHER_PHONEME_UH},
396 {Effect::PHONEME_UW, AL_VOCAL_MORPHER_PHONEME_UW},
397 {Effect::PHONEME_B, AL_VOCAL_MORPHER_PHONEME_B},
398 {Effect::PHONEME_D, AL_VOCAL_MORPHER_PHONEME_D},
399 {Effect::PHONEME_F, AL_VOCAL_MORPHER_PHONEME_F},
400 {Effect::PHONEME_G, AL_VOCAL_MORPHER_PHONEME_G},
401 {Effect::PHONEME_J, AL_VOCAL_MORPHER_PHONEME_J},
402 {Effect::PHONEME_K, AL_VOCAL_MORPHER_PHONEME_K},
403 {Effect::PHONEME_L, AL_VOCAL_MORPHER_PHONEME_L},
404 {Effect::PHONEME_M, AL_VOCAL_MORPHER_PHONEME_M},
405 {Effect::PHONEME_N, AL_VOCAL_MORPHER_PHONEME_N},
406 {Effect::PHONEME_P, AL_VOCAL_MORPHER_PHONEME_P},
407 {Effect::PHONEME_R, AL_VOCAL_MORPHER_PHONEME_R},
408 {Effect::PHONEME_S, AL_VOCAL_MORPHER_PHONEME_S},
409 {Effect::PHONEME_T, AL_VOCAL_MORPHER_PHONEME_T},
410 {Effect::PHONEME_V, AL_VOCAL_MORPHER_PHONEME_V},
411 {Effect::PHONEME_Z, AL_VOCAL_MORPHER_PHONEME_Z}
412};
413*/
414
415} //openal
416} //audio
417} //love
418