Browse Source

Named Effect parameters added. Unsupported effects disabled.

Unnamed parameter Effect setting is no longer functional.

--HG--
branch : minor
Raidho 8 years ago
parent
commit
42f89153ae

+ 4 - 6
src/modules/audio/Audio.h

@@ -211,11 +211,10 @@ public:
 	/**
 	 * Sets scene EFX effect.
 	 * @param slot Slot to put effect into.
-	 * @param type Effect type to use.
-	 * @param params Effect description table.
+	 * @param fxparams Effect description table.
 	 * @return true if successful, false otherwise.
 	 */
-	virtual bool setSceneEffect(int slot, Effect::Type type, std::vector<float> &params) = 0;
+	virtual bool setSceneEffect(int slot, std::map<Effect::Parameter, float> &params) = 0;
 
 	/**
 	 * Removes scene EFX effect.
@@ -227,11 +226,10 @@ public:
 	/**
 	 * Gets scene EFX effect.
 	 * @param slot Slot from which to get effect.
-	 * @param type Effect type.
-	 * @param params Effect description table.
+	 * @param fxparams Effect description table.
 	 * @return true if effect was present, false otherwise.
 	 */
-	virtual bool getSceneEffect(int slot, Effect::Type &type, std::vector<float> &params) = 0;
+	virtual bool getSceneEffect(int slot, std::map<Effect::Parameter, float> &params) = 0;
 
 	/**
 	 * Gets maximum number of scene EFX effects.

+ 236 - 36
src/modules/audio/Effect.cpp

@@ -47,7 +47,7 @@ bool Effect::getConstant(Type in, const char *&out)
 {
 	return types.find(in, out);
 }
-
+/*
 bool Effect::getConstant(const char *in, Phoneme &out)
 {
 	return phonemes.find(in, out);
@@ -57,7 +57,7 @@ bool Effect::getConstant(Phoneme in, const char *&out)
 {
 	return phonemes.find(in, out);
 }
-
+*/
 bool Effect::getConstant(const char *in, Waveform &out)
 {
 	return waveforms.find(in, out);
@@ -67,7 +67,7 @@ bool Effect::getConstant(Waveform in, const char *&out)
 {
 	return waveforms.find(in, out);
 }
-
+/*
 bool Effect::getConstant(const char *in, Direction &out)
 {
 	return directions.find(in, out);
@@ -77,8 +77,18 @@ bool Effect::getConstant(Direction in, const char *&out)
 {
 	return directions.find(in, out);
 }
+*/
+bool Effect::getConstant(const char *in, Parameter &out, Type t)
+{
+	return parameterNames[t].find(in, out);
+}
+
+bool Effect::getConstant(Parameter in, const char *&out, Type t)
+{
+	return parameterNames[t].find(in, out);
+}
 
-const std::vector<Effect::ParameterType> &Effect::getParameterTypes(Effect::Type in)
+Effect::ParameterType Effect::getParameterType(Effect::Parameter in)
 {
 	return parameterTypes[in];
 }
@@ -90,11 +100,11 @@ StringMap<Effect::Type, Effect::TYPE_MAX_ENUM>::Entry Effect::typeEntries[] =
 	{"distortion", Effect::TYPE_DISTORTION},
 	{"echo", Effect::TYPE_ECHO},
 	{"flanger", Effect::TYPE_FLANGER},
-	{"frequencyshifter", Effect::TYPE_FREQSHIFTER},
-	{"vocalmorpher", Effect::TYPE_MORPHER},
-	{"pitchshifter", Effect::TYPE_PITCHSHIFTER},
+	//{"frequencyshifter", Effect::TYPE_FREQSHIFTER},
+	//{"vocalmorpher", Effect::TYPE_MORPHER},
+	//{"pitchshifter", Effect::TYPE_PITCHSHIFTER},
 	{"ringmodulator", Effect::TYPE_MODULATOR},
-	{"autowah", Effect::TYPE_AUTOWAH},
+	//{"autowah", Effect::TYPE_AUTOWAH},
 	{"compressor", Effect::TYPE_COMPRESSOR},
 	{"equalizer", Effect::TYPE_EQUALIZER},
 };
@@ -111,6 +121,7 @@ StringMap<Effect::Waveform, Effect::WAVE_MAX_ENUM>::Entry Effect::waveformEntrie
 
 StringMap<Effect::Waveform, Effect::WAVE_MAX_ENUM> Effect::waveforms(Effect::waveformEntries, sizeof(Effect::waveformEntries));
 
+/*
 StringMap<Effect::Direction, Effect::DIR_MAX_ENUM>::Entry Effect::directionEntries[] =
 {
 	{"up", Effect::DIR_UP},
@@ -155,35 +166,224 @@ StringMap<Effect::Phoneme, Effect::PHONEME_MAX_ENUM>::Entry Effect::phonemeEntri
 };
 
 StringMap<Effect::Phoneme, Effect::PHONEME_MAX_ENUM> Effect::phonemes(Effect::phonemeEntries, sizeof(Effect::phonemeEntries));
+*/
+
+#define StringMap LazierAndSlowerButEasilyArrayableStringMap
+
+std::vector<StringMap<Effect::Parameter>::Entry> Effect::basicParameters =
+{
+	{"type", Effect::EFFECT_TYPE},
+	{"volume", Effect::EFFECT_VOLUME}
+};
+
+std::vector<StringMap<Effect::Parameter>::Entry> Effect::reverbParameters =
+{
+	{"gain", Effect::REVERB_GAIN},
+	{"hfgain", Effect::REVERB_HFGAIN},
+	{"density", Effect::REVERB_DENSITY},
+	{"diffusion", Effect::REVERB_DIFFUSION},
+	{"decay", Effect::REVERB_DECAY},
+	{"hfdecay", Effect::REVERB_HFDECAY},
+	{"earlygain", Effect::REVERB_EARLYGAIN},
+	{"earlydelay", Effect::REVERB_EARLYDELAY},
+	{"lategain", Effect::REVERB_LATEGAIN},
+	{"latedelay", Effect::REVERB_LATEDELAY},
+	{"rolloff", Effect::REVERB_ROLLOFF},
+	{"airhfgain", Effect::REVERB_AIRHFGAIN},
+	{"hflimiter", Effect::REVERB_HFLIMITER}
+};
+
+std::vector<StringMap<Effect::Parameter>::Entry> Effect::chorusParameters =
+{
+	{"waveform", Effect::CHORUS_WAVEFORM},
+	{"phase", Effect::CHORUS_PHASE},
+	{"rate", Effect::CHORUS_RATE},
+	{"depth", Effect::CHORUS_DEPTH},
+	{"feedback", Effect::CHORUS_FEEDBACK},
+	{"delay", Effect::CHORUS_DELAY}
+};
+
+std::vector<StringMap<Effect::Parameter>::Entry> Effect::distortionParameters = 
+{
+	{"gain", Effect::DISTORTION_GAIN},
+	{"edge", Effect::DISTORTION_EDGE},
+	{"lowcut", Effect::DISTORTION_LOWCUT},
+	{"eqcenter", Effect::DISTORTION_EQCENTER},
+	{"eqbandwidth", Effect::DISTORTION_EQBAND}
+};
+
+std::vector<StringMap<Effect::Parameter>::Entry> Effect::echoParameters = 
+{
+	{"delay", Effect::ECHO_DELAY},
+	{"lrdelay", Effect::ECHO_LRDELAY},
+	{"damping", Effect::ECHO_DAMPING},
+	{"feedback", Effect::ECHO_FEEDBACK},
+	{"spread", Effect::ECHO_SPREAD}
+};
+
+std::vector<StringMap<Effect::Parameter>::Entry> Effect::flangerParameters = 
+{
+	{"waveform", Effect::FLANGER_WAVEFORM},
+	{"phase", Effect::FLANGER_PHASE},
+	{"rate", Effect::FLANGER_RATE},
+	{"depth", Effect::FLANGER_DEPTH},
+	{"feedback", Effect::FLANGER_FEEDBACK},
+	{"delay", Effect::FLANGER_DELAY}
+};
+/*
+std::vector<StringMap<Effect::Parameter>::Entry> Effect::freqshifterParameters = 
+{
+	{"frequency", Effect::FREQSHIFTER_FREQ},
+	{"leftdirection", Effect::FREQSHIFTER_LEFTDIR},
+	{"rightdirection", Effect::FREQSHIFTER_RIGHTDIR}
+};
+
+std::vector<StringMap<Effect::Parameter>::Entry> Effect::morpherParameters = 
+{
+	{"waveform", Effect::MORPHER_WAVEFORM},
+	{"rate", Effect::MORPHER_RATE},
+	{"phonemea", Effect::MORPHER_PHONEMEA},
+	{"phonemeb", Effect::MORPHER_PHONEMEB},
+	{"tunea", Effect::MORPHER_COARSEA},
+	{"tuneb", Effect::MORPHER_COARSEB}
+}
+;
+std::vector<StringMap<Effect::Parameter>::Entry> Effect::pitchshifterParameters = 
+{
+	{"pitch", Effect::PITCHSHIFTER_PITCH}
+};
+*/
+std::vector<StringMap<Effect::Parameter>::Entry> Effect::modulatorParameters = 
+{
+	{"waveform", Effect::MODULATOR_WAVEFORM},
+	{"frequency", Effect::MODULATOR_FREQ},
+	{"highcut", Effect::MODULATOR_HIGHCUT}
+};
+/*
+std::vector<StringMap<Effect::Parameter>::Entry> Effect::autowahParameters = 
+{
+	{"attack", Effect::AUTOWAH_ATTACK},
+	{"release", Effect::AUTOWAH_RELEASE},
+	{"resonance", Effect::AUTOWAH_RESONANCE},
+	{"peakgain", Effect::AUTOWAH_PEAKGAIN}
+};
+*/
+std::vector<StringMap<Effect::Parameter>::Entry> Effect::compressorParameters = 
+{
+	{"enable", Effect::COMPRESSOR_ENABLE}
+};
+
+std::vector<StringMap<Effect::Parameter>::Entry> Effect::equalizerParameters = 
+{
+	{"lowgain", Effect::EQUALIZER_LOWGAIN},
+	{"lowcut", Effect::EQUALIZER_LOWCUT},
+	{"mid1gain", Effect::EQUALIZER_MID1GAIN},
+	{"mid1frequency", Effect::EQUALIZER_MID1FREQ},
+	{"mid1bandwidth", Effect::EQUALIZER_MID1BAND},
+	{"mid2gain", Effect::EQUALIZER_MID2GAIN},
+	{"mid2frequency", Effect::EQUALIZER_MID2FREQ},
+	{"mid2bandwidth", Effect::EQUALIZER_MID2BAND},
+	{"highgain", Effect::EQUALIZER_HIGHGAIN},
+	{"highcut", Effect::EQUALIZER_HIGHCUT}
+};
+
+std::map<Effect::Type, StringMap<Effect::Parameter>> Effect::parameterNames = 
+{
+	{Effect::TYPE_BASIC, Effect::basicParameters},
+	{Effect::TYPE_REVERB, Effect::reverbParameters},
+	{Effect::TYPE_CHORUS, Effect::chorusParameters},
+	{Effect::TYPE_DISTORTION, Effect::distortionParameters},
+	{Effect::TYPE_ECHO, Effect::echoParameters},
+	{Effect::TYPE_FLANGER, Effect::flangerParameters},
+	//{Effect::TYPE_FREQSHIFTER, Effect::freqshifterParameters},
+	//{Effect::TYPE_MORPHER, Effect::morpherbParameters},
+	//{Effect::TYPE_PITCHSHIFTER, Effect::pitchshifterParameters},
+	{Effect::TYPE_MODULATOR, Effect::modulatorParameters},
+	//{Effect::TYPE_AUTOWAH, Effect::autowahParameters},
+	{Effect::TYPE_COMPRESSOR, Effect::compressorParameters},
+	{Effect::TYPE_EQUALIZER, Effect::equalizerParameters}
+};
+#undef StringMap
+
+std::map<Effect::Parameter, Effect::ParameterType> Effect::parameterTypes = 
+{
+	{Effect::EFFECT_TYPE, Effect::PARAM_TYPE},
+	{Effect::EFFECT_VOLUME, Effect::PARAM_FLOAT},
+
+	{Effect::REVERB_GAIN, Effect::PARAM_FLOAT},
+	{Effect::REVERB_HFGAIN, Effect::PARAM_FLOAT},
+	{Effect::REVERB_DENSITY, Effect::PARAM_FLOAT},
+	{Effect::REVERB_DIFFUSION, Effect::PARAM_FLOAT},
+	{Effect::REVERB_DECAY, Effect::PARAM_FLOAT},
+	{Effect::REVERB_HFDECAY, Effect::PARAM_FLOAT},
+	{Effect::REVERB_EARLYGAIN, Effect::PARAM_FLOAT},
+	{Effect::REVERB_EARLYDELAY, Effect::PARAM_FLOAT},
+	{Effect::REVERB_LATEGAIN, Effect::PARAM_FLOAT},
+	{Effect::REVERB_LATEDELAY, Effect::PARAM_FLOAT},
+	{Effect::REVERB_ROLLOFF, Effect::PARAM_FLOAT},
+	{Effect::REVERB_AIRHFGAIN, Effect::PARAM_FLOAT},
+	{Effect::REVERB_HFLIMITER, Effect::PARAM_BOOL},
+
+	{Effect::CHORUS_WAVEFORM, Effect::PARAM_WAVEFORM},
+	{Effect::CHORUS_PHASE, Effect::PARAM_FLOAT},
+	{Effect::CHORUS_RATE, Effect::PARAM_FLOAT},
+	{Effect::CHORUS_DEPTH, Effect::PARAM_FLOAT},
+	{Effect::CHORUS_FEEDBACK, Effect::PARAM_FLOAT},
+	{Effect::CHORUS_DELAY, Effect::PARAM_FLOAT},
+
+	{Effect::DISTORTION_GAIN, Effect::PARAM_FLOAT},
+	{Effect::DISTORTION_EDGE, Effect::PARAM_FLOAT},
+	{Effect::DISTORTION_LOWCUT, Effect::PARAM_FLOAT},
+	{Effect::DISTORTION_EQCENTER, Effect::PARAM_FLOAT},
+	{Effect::DISTORTION_EQBAND, Effect::PARAM_FLOAT},
+
+	{Effect::ECHO_DELAY, Effect::PARAM_FLOAT},
+	{Effect::ECHO_LRDELAY, Effect::PARAM_FLOAT},
+	{Effect::ECHO_DAMPING, Effect::PARAM_FLOAT},
+	{Effect::ECHO_FEEDBACK, Effect::PARAM_FLOAT},
+	{Effect::ECHO_SPREAD, Effect::PARAM_FLOAT},
+
+	{Effect::FLANGER_WAVEFORM, Effect::PARAM_WAVEFORM},
+	{Effect::FLANGER_PHASE, Effect::PARAM_FLOAT},
+	{Effect::FLANGER_RATE, Effect::PARAM_FLOAT},
+	{Effect::FLANGER_DEPTH, Effect::PARAM_FLOAT},
+	{Effect::FLANGER_FEEDBACK, Effect::PARAM_FLOAT},
+	{Effect::FLANGER_DELAY, Effect::PARAM_FLOAT},
+/*
+	{Effect::FREQSHIFTER_FREQ, Effect::PARAM_FLOAT},
+	{Effect::FREQSHIFTER_LEFTDIR, Effect::PARAM_DIRECTION},
+	{Effect::FREQSHIFTER_RIGHTDIR, Effect::PARAM_DIRECTION},
+
+	{Effect::MORPHER_WAVEFORM, Effect::PARAM_WAVEFORM},
+	{Effect::MORPHER_RATE, Effect::PARAM_FLOAT},
+	{Effect::MORPHER_PHONEMEA, Effect::PARAM_PHONEME},
+	{Effect::MORPHER_PHONEMEB, Effect::PARAM_PHONEME},
+	{Effect::MORPHER_TUNEA, Effect::PARAM_FLOAT},
+	{Effect::MORPHER_TUNEB, Effect::PARAM_FLOAT},
+
+	{Effect::PITCHSHIFTER_PITCH, Effect::PARAM_FLOAT},
+*/
+	{Effect::MODULATOR_WAVEFORM, Effect::PARAM_WAVEFORM},
+	{Effect::MODULATOR_FREQ, Effect::PARAM_FLOAT},
+	{Effect::MODULATOR_HIGHCUT, Effect::PARAM_FLOAT},
+/*
+	{Effect::AUTOWAH_ATTACK, Effect::PARAM_FLOAT},
+	{Effect::AUTOWAH_RELEASE, Effect::PARAM_FLOAT},
+	{Effect::AUTOWAH_RESONANCE, Effect::PARAM_FLOAT},
+	{Effect::AUTOWAH_PEAKGAIN, Effect::PARAM_FLOAT},
+*/
+	{Effect::COMPRESSOR_ENABLE, Effect::PARAM_BOOL},
 
-std::map<Effect::Type, std::vector<Effect::ParameterType>> Effect::parameterTypes =
-{
-	//gain, high gain, density, diffusion, decay, high decay ratio, refl gain, refl delay, late gain, late delay, rolloff, air high gain, high limiter
-	{Effect::TYPE_REVERB, {Effect::PAR_FLOAT, Effect::PAR_FLOAT, Effect::PAR_FLOAT, Effect::PAR_FLOAT, Effect::PAR_FLOAT, Effect::PAR_FLOAT,
-		Effect::PAR_FLOAT, Effect::PAR_FLOAT, Effect::PAR_FLOAT, Effect::PAR_FLOAT, Effect::PAR_FLOAT, Effect::PAR_FLOAT, Effect::PAR_BOOL}},
-	//waveform, phase, rate, depth, feedback, delay
-	{Effect::TYPE_CHORUS, { Effect::PAR_WAVEFORM, Effect::PAR_FLOAT, Effect::PAR_FLOAT, Effect::PAR_FLOAT, Effect::PAR_FLOAT, Effect::PAR_FLOAT}},
-	//gain, edge, lowpass cutoff, eq center, eq width
-	{Effect::TYPE_DISTORTION, {Effect::PAR_FLOAT, Effect::PAR_FLOAT, Effect::PAR_FLOAT, Effect::PAR_FLOAT, Effect::PAR_FLOAT}},
-	//delay, LR delay, damping, feedback, spread
-	{Effect::TYPE_ECHO, {Effect::PAR_FLOAT, Effect::PAR_FLOAT, Effect::PAR_FLOAT, Effect::PAR_FLOAT, Effect::PAR_FLOAT}},
-	//waveform, phase, rate, depth, feedback, delay
-	{Effect::TYPE_FLANGER, {Effect::PAR_WAVEFORM, Effect::PAR_FLOAT, Effect::PAR_FLOAT, Effect::PAR_FLOAT, Effect::PAR_FLOAT, Effect::PAR_FLOAT}},
-	//frequency, left direction, right direction
-	{Effect::TYPE_FREQSHIFTER, {Effect::PAR_FLOAT, Effect::PAR_DIRECTION, Effect::PAR_DIRECTION}},
-	//waveform, rate, phoneme A, phoneme B, phoneme A coarse tune, phoneme B coarse tune
-	{Effect::TYPE_MORPHER, {Effect::PAR_WAVEFORM, Effect::PAR_FLOAT, Effect::PAR_PHONEME, Effect::PAR_PHONEME, Effect::PAR_FLOAT, Effect::PAR_FLOAT}},
-	//pitch(semitones)
-	{Effect::TYPE_PITCHSHIFTER, {Effect::PAR_FLOAT}},
-	//waveform, frequency, highpass cutoff
-	{Effect::TYPE_MODULATOR, {Effect::PAR_WAVEFORM, Effect::PAR_FLOAT, Effect::PAR_FLOAT}},
-	//attack, release, resonance, peak gain
-	{Effect::TYPE_AUTOWAH, {Effect::PAR_FLOAT, Effect::PAR_FLOAT, Effect::PAR_FLOAT, Effect::PAR_FLOAT}},
-	// on-off switch
-	{Effect::TYPE_COMPRESSOR, {Effect::PAR_BOOL}},
-	//low gain, low cut, mid1 gain, mid1 freq, mid1 band, mid2 gain, mid2 freq, mid2 band, high gain, high cut
-	{Effect::TYPE_EQUALIZER, {Effect::PAR_FLOAT, Effect::PAR_FLOAT, Effect::PAR_FLOAT, Effect::PAR_FLOAT, Effect::PAR_FLOAT, 
-		Effect::PAR_FLOAT, Effect::PAR_FLOAT, Effect::PAR_FLOAT, Effect::PAR_FLOAT, Effect::PAR_FLOAT}},
+	{Effect::EQUALIZER_LOWGAIN, Effect::PARAM_FLOAT},
+	{Effect::EQUALIZER_LOWCUT, Effect::PARAM_FLOAT},
+	{Effect::EQUALIZER_MID1GAIN, Effect::PARAM_FLOAT},
+	{Effect::EQUALIZER_MID1FREQ, Effect::PARAM_FLOAT},
+	{Effect::EQUALIZER_MID1BAND, Effect::PARAM_FLOAT},
+	{Effect::EQUALIZER_MID2GAIN, Effect::PARAM_FLOAT},
+	{Effect::EQUALIZER_MID2FREQ, Effect::PARAM_FLOAT},
+	{Effect::EQUALIZER_MID2BAND, Effect::PARAM_FLOAT},
+	{Effect::EQUALIZER_HIGHGAIN, Effect::PARAM_FLOAT},
+	{Effect::EQUALIZER_HIGHCUT, Effect::PARAM_FLOAT}
 };
 
 } //audio

+ 169 - 21
src/modules/audio/Effect.h

@@ -26,6 +26,49 @@
 #include <map>
 #include <vector>
 
+template<typename T>
+class LazierAndSlowerButEasilyArrayableStringMap
+{
+public:
+	struct Entry
+	{
+		const char *key;
+		T value;
+	};
+	LazierAndSlowerButEasilyArrayableStringMap()
+	{
+	}
+
+	LazierAndSlowerButEasilyArrayableStringMap(const std::vector<Entry> &entries)
+	{
+		for (auto entry : entries)
+		{
+			forward[entry.key] = entry.value;
+			reverse[entry.value] = entry.key;
+		}
+	}
+
+	bool find(const char *key, T &t)
+	{
+		if (forward.find(key) == forward.end()) 
+			return false;
+		t = forward[key];
+		return true;
+	}
+
+	bool find(T key, const char *&str) 
+	{
+		if (reverse.find(key) == reverse.end())
+			return false;
+		str = reverse[key];
+		return true;
+	}
+
+private:
+	std::map<std::string, T> forward;
+	std::map<T, const char*> reverse;
+};
+
 namespace love
 {
 namespace audio
@@ -36,29 +79,114 @@ class Effect
 public:
 	enum Type
 	{
+		TYPE_BASIC, //not a real type
 		TYPE_REVERB,
 		TYPE_CHORUS,
 		TYPE_DISTORTION,
 		TYPE_ECHO,
 		TYPE_FLANGER,
-		TYPE_FREQSHIFTER,
-		TYPE_MORPHER,
-		TYPE_PITCHSHIFTER,
+		//TYPE_FREQSHIFTER,
+		//TYPE_MORPHER,
+		//TYPE_PITCHSHIFTER,
 		TYPE_MODULATOR,
-		TYPE_AUTOWAH,
+		//TYPE_AUTOWAH,
 		TYPE_COMPRESSOR,
 		TYPE_EQUALIZER,
 		TYPE_MAX_ENUM
 	};
 
+	enum Parameter
+	{
+		EFFECT_TYPE,
+		EFFECT_VOLUME,
+
+		REVERB_GAIN,
+		REVERB_HFGAIN,
+		REVERB_DENSITY,
+		REVERB_DIFFUSION,
+		REVERB_DECAY,
+		REVERB_HFDECAY,
+		REVERB_EARLYGAIN,
+		REVERB_EARLYDELAY,
+		REVERB_LATEGAIN,
+		REVERB_LATEDELAY,
+		REVERB_ROLLOFF,
+		REVERB_AIRHFGAIN,
+		REVERB_HFLIMITER,
+
+		CHORUS_WAVEFORM,
+		CHORUS_PHASE,
+		CHORUS_RATE,
+		CHORUS_DEPTH,
+		CHORUS_FEEDBACK,
+		CHORUS_DELAY,
+
+		DISTORTION_GAIN,
+		DISTORTION_EDGE,
+		DISTORTION_LOWCUT,
+		DISTORTION_EQCENTER,
+		DISTORTION_EQBAND,
+
+		ECHO_DELAY,
+		ECHO_LRDELAY,
+		ECHO_DAMPING,
+		ECHO_FEEDBACK,
+		ECHO_SPREAD,
+
+		FLANGER_WAVEFORM,
+		FLANGER_PHASE,
+		FLANGER_RATE,
+		FLANGER_DEPTH,
+		FLANGER_FEEDBACK,
+		FLANGER_DELAY,
+/*
+		FREQSHIFTER_FREQ,
+		FREQSHIFTER_LEFTDIR,
+		FREQSHIFTER_RIGHTDIR,
+
+		MORPHER_WAVEFORM,
+		MORPHER_RATE,
+		MORPHER_PHONEMEA,
+		MORPHER_PHONEMEB,
+		MORPHER_TUNEA,
+		MORPHER_TUNEB,
+
+		PITCHSHIFTER_PITCH,
+*/
+		MODULATOR_WAVEFORM,
+		MODULATOR_FREQ,
+		MODULATOR_HIGHCUT,
+/*
+		AUTOWAH_ATTACK,
+		AUTOWAH_RELEASE,
+		AUTOWAH_RESONANCE,
+		AUTOWAH_PEAKGAIN,
+*/
+		COMPRESSOR_ENABLE,
+
+		EQUALIZER_LOWGAIN,
+		EQUALIZER_LOWCUT,
+		EQUALIZER_MID1GAIN,
+		EQUALIZER_MID1FREQ,
+		EQUALIZER_MID1BAND,
+		EQUALIZER_MID2GAIN,
+		EQUALIZER_MID2FREQ,
+		EQUALIZER_MID2BAND,
+		EQUALIZER_HIGHGAIN,
+		EQUALIZER_HIGHCUT,
+
+		EFFECT_MAX_ENUM
+	};
+
 	enum ParameterType
 	{
-		PAR_FLOAT,
-		PAR_BOOL,
-		PAR_WAVEFORM,
-		PAR_DIRECTION,
-		PAR_PHONEME,
-		PAR_MAX_ENUM
+		PARAM_TYPE,
+		PARAM_FLOAT,
+		PARAM_BOOL,
+		PARAM_WAVEFORM,
+		//PARAM_DIRECTION,
+		//PARAM_PHONEME,
+		PARAM_MAX_ENUM
 	};
 
 	enum Waveform
@@ -69,7 +197,7 @@ public:
 		WAVE_SQUARE,
 		WAVE_MAX_ENUM
 	};
-
+	/*
 	enum Direction
 	{
 		DIR_NONE,
@@ -112,6 +240,7 @@ public:
 		PHONEME_Z,
 		PHONEME_MAX_ENUM
 	};
+	*/
 
 	Effect();
 	virtual ~Effect();
@@ -121,11 +250,13 @@ public:
 	static bool getConstant(Type in, const char *&out);
 	static bool getConstant(const char *in, Waveform &out);
 	static bool getConstant(Waveform in, const char *&out);
-	static bool getConstant(const char *in, Direction &out);
-	static bool getConstant(Direction in, const char *&out);
-	static bool getConstant(const char *in, Phoneme &out);
-	static bool getConstant(Phoneme in, const char *&out);
-	static const std::vector<ParameterType> &getParameterTypes(Type in);
+	//static bool getConstant(const char *in, Direction &out);
+	//static bool getConstant(Direction in, const char *&out);
+	//static bool getConstant(const char *in, Phoneme &out);
+	//static bool getConstant(Phoneme in, const char *&out);
+	static bool getConstant(const char *in, Parameter &out, Type t);
+	static bool getConstant(Parameter in, const char *&out, Type t);
+	static ParameterType getParameterType(Parameter in);
 
 protected:
 	Type type;
@@ -135,11 +266,28 @@ private:
 	static StringMap<Type, TYPE_MAX_ENUM> types;
 	static StringMap<Waveform, WAVE_MAX_ENUM>::Entry waveformEntries[];
 	static StringMap<Waveform, WAVE_MAX_ENUM> waveforms;
-	static StringMap<Direction, DIR_MAX_ENUM>::Entry directionEntries[];
-	static StringMap<Direction, DIR_MAX_ENUM> directions;
-	static StringMap<Phoneme, PHONEME_MAX_ENUM>::Entry phonemeEntries[];
-	static StringMap<Phoneme, PHONEME_MAX_ENUM> phonemes;
-	static std::map<Type, std::vector<Effect::ParameterType>> parameterTypes;
+	//static StringMap<Direction, DIR_MAX_ENUM>::Entry directionEntries[];
+	//static StringMap<Direction, DIR_MAX_ENUM> directions;
+	//static StringMap<Phoneme, PHONEME_MAX_ENUM>::Entry phonemeEntries[];
+	//static StringMap<Phoneme, PHONEME_MAX_ENUM> phonemes;
+#define StringMap LazierAndSlowerButEasilyArrayableStringMap
+	static std::vector<StringMap<Effect::Parameter>::Entry> basicParameters;
+	static std::vector<StringMap<Effect::Parameter>::Entry> reverbParameters;
+	static std::vector<StringMap<Effect::Parameter>::Entry> chorusParameters;
+	static std::vector<StringMap<Effect::Parameter>::Entry> distortionParameters;
+	static std::vector<StringMap<Effect::Parameter>::Entry> echoParameters;
+	static std::vector<StringMap<Effect::Parameter>::Entry> flangerParameters;
+	//static std::vector<StringMap<Effect::Parameter>::Entry> freqshifterParameters;
+	//static std::vector<StringMap<Effect::Parameter>::Entry> morpherParameters;
+	//static std::vector<StringMap<Effect::Parameter>::Entry> pitchshifterParameters;
+	static std::vector<StringMap<Effect::Parameter>::Entry> modulatorParameters;
+	//static std::vector<StringMap<Effect::Parameter>::Entry> autowahParameters;
+	static std::vector<StringMap<Effect::Parameter>::Entry> compressorParameters;
+	static std::vector<StringMap<Effect::Parameter>::Entry> equalizerParameters;
+	static std::map<Type, StringMap<Parameter>> parameterNames;
+#undef StringMap
+	static std::map<Parameter, ParameterType> parameterTypes;
+
 };
 
 } //audio

+ 2 - 2
src/modules/audio/null/Audio.cpp

@@ -168,7 +168,7 @@ void Audio::setDistanceModel(DistanceModel distanceModel)
 	this->distanceModel = distanceModel;
 }
 
-bool Audio::setSceneEffect(int, Effect::Type, std::vector<float> &)
+bool Audio::setSceneEffect(int, std::map<Effect::Parameter, float> &)
 {
 	return false;
 }
@@ -178,7 +178,7 @@ bool Audio::setSceneEffect(int)
 	return false;
 }
 
-bool Audio::getSceneEffect(int, Effect::Type &, std::vector<float> &)
+bool Audio::getSceneEffect(int, std::map<Effect::Parameter, float> &)
 {
 	return false;
 }

+ 2 - 2
src/modules/audio/null/Audio.h

@@ -78,9 +78,9 @@ public:
 	DistanceModel getDistanceModel() const;
 	void setDistanceModel(DistanceModel distanceModel);
 
-	bool setSceneEffect(int slot, Effect::Type type, std::vector<float> &params);
+	bool setSceneEffect(int slot, std::map<Effect::Parameter, float> &params);
 	bool setSceneEffect(int slot);
-	bool getSceneEffect(int slot, Effect::Type &type, std::vector<float> &params);
+	bool getSceneEffect(int slot, std::map<Effect::Parameter, float> &params);
 	int getMaxSceneEffects() const;
 	int getMaxSourceEffects() const;
 	bool isEFXsupported() const;

+ 5 - 5
src/modules/audio/openal/Audio.cpp

@@ -445,7 +445,7 @@ const std::vector<love::audio::RecordingDevice*> &Audio::getRecordingDevices()
 	return capture;
 }
 
-bool Audio::setSceneEffect(int slot, Effect::Type type, std::vector<float> &params)
+bool Audio::setSceneEffect(int slot, std::map<Effect::Parameter, float> &params)
 {
 	if (slot < 0 || slot >= MAX_SCENE_EFFECTS)
 		return false;
@@ -453,15 +453,16 @@ bool Audio::setSceneEffect(int slot, Effect::Type type, std::vector<float> &para
 	if (!effects[slot])
 		effects[slot] = new Effect();
 
-	bool result = effects[slot]->setParams(type, params);
+	bool result = effects[slot]->setParams(params);
 
 	#ifdef ALC_EXT_EFX
 	if (alAuxiliaryEffectSloti)
 	{
 		if (result == true)
 		{
+			if (params.find(Effect::EFFECT_VOLUME) != params.end())
+				alAuxiliaryEffectSlotf(effectSlots[slot], AL_EFFECTSLOT_GAIN, params[Effect::EFFECT_VOLUME]);
 			alAuxiliaryEffectSloti(effectSlots[slot], AL_EFFECTSLOT_EFFECT, effects[slot]->getEffect());
-			alAuxiliaryEffectSlotf(effectSlots[slot], AL_EFFECTSLOT_GAIN, params[0]);
 		}
 		else
 			alAuxiliaryEffectSloti(effectSlots[slot], AL_EFFECTSLOT_EFFECT, AL_EFFECT_NULL);
@@ -490,7 +491,7 @@ bool Audio::setSceneEffect(int slot)
 	return true;
 }
 
-bool Audio::getSceneEffect(int slot, Effect::Type &type, std::vector<float> &params)
+bool Audio::getSceneEffect(int slot, std::map<Effect::Parameter, float> &params)
 {
 	if (slot < 0 || slot >= MAX_SCENE_EFFECTS)
 		return false;
@@ -498,7 +499,6 @@ bool Audio::getSceneEffect(int slot, Effect::Type &type, std::vector<float> &par
 	if (!effects[slot])
 		return false;
 
-	type = effects[slot]->getType();
 	params = effects[slot]->getParams();
 
 	return true;

+ 2 - 2
src/modules/audio/openal/Audio.h

@@ -114,9 +114,9 @@ public:
 	DistanceModel getDistanceModel() const;
 	void setDistanceModel(DistanceModel distanceModel);
 
-	bool setSceneEffect(int slot, Effect::Type type, std::vector<float> &params);
+	bool setSceneEffect(int slot, std::map<Effect::Parameter, float> &params);
 	bool setSceneEffect(int slot);
-	bool getSceneEffect(int slot, Effect::Type &type, std::vector<float> &params);
+	bool getSceneEffect(int slot, std::map<Effect::Parameter, float> &params);
 	int getMaxSceneEffects() const;
 	int getMaxSourceEffects() const;
 	bool isEFXsupported() const;

+ 131 - 121
src/modules/audio/openal/Effect.cpp

@@ -40,7 +40,7 @@ Effect::Effect()
 Effect::Effect(const Effect &s)
 	: Effect()
 {
-	setParams(s.getType(), s.getParams());
+	setParams(s.getParams());
 }
 
 Effect::~Effect()
@@ -81,21 +81,21 @@ void Effect::deleteEffect()
 	effect = AL_EFFECT_NULL;
 }
 
-
 ALuint Effect::getEffect() const
 {
 	return effect;
 }
 
-bool Effect::setParams(Type type, const std::vector<float> &params)
+bool Effect::setParams(const std::map<Parameter, float> &params)
 {
-	this->type = type;
 	this->params = params;
+	type = static_cast<Type>(this->params[EFFECT_TYPE]);
 
 	if (!generateEffect())
 		return false;
 
 	#ifdef ALC_EXT_EFX
+	//parameter table without EFFECT_TYPE entry is illegal
 	switch (type)
 	{
 	case TYPE_REVERB:
@@ -113,6 +113,7 @@ bool Effect::setParams(Type type, const std::vector<float> &params)
 	case TYPE_FLANGER:
 		alEffecti(effect, AL_EFFECT_TYPE, AL_EFFECT_FLANGER);
 		break;
+/*
 	case TYPE_FREQSHIFTER:
 		alEffecti(effect, AL_EFFECT_TYPE, AL_EFFECT_FREQUENCY_SHIFTER);
 		break;
@@ -122,18 +123,22 @@ bool Effect::setParams(Type type, const std::vector<float> &params)
 	case TYPE_PITCHSHIFTER:
 		alEffecti(effect, AL_EFFECT_TYPE, AL_EFFECT_PITCH_SHIFTER);
 		break;
+*/
 	case TYPE_MODULATOR:
 		alEffecti(effect, AL_EFFECT_TYPE, AL_EFFECT_RING_MODULATOR);
 		break;
+/*
 	case TYPE_AUTOWAH:
 		alEffecti(effect, AL_EFFECT_TYPE, AL_EFFECT_AUTOWAH);
 		break;
+*/
 	case TYPE_COMPRESSOR:
 		alEffecti(effect, AL_EFFECT_TYPE, AL_EFFECT_COMPRESSOR);
 		break;
 	case TYPE_EQUALIZER:
 		alEffecti(effect, AL_EFFECT_TYPE, AL_EFFECT_EQUALIZER);
 		break;
+	case TYPE_BASIC:
 	case TYPE_MAX_ENUM:
 		break;
 	}
@@ -145,96 +150,98 @@ bool Effect::setParams(Type type, const std::vector<float> &params)
 		return false;
 	}
 
-	#define PARAMSTR(i,e,v) effect, AL_ ## e ## _ ## v, clampf(params[(i)], AL_ ## e ## _MIN_ ## v, AL_ ## e ## _MAX_ ## v, AL_ ## e ## _DEFAULT_ ## v)
+	#define clampf(v,l,h) fmax(fmin((v),(h)),(l))
+	#define PARAMSTR(i,e,v) effect,AL_##e##_##v,clampf(getValue(i,AL_##e##_DEFAULT_##v),AL_##e##_MIN_##v,AL_##e##_MAX_##v)
 	switch (type)
 	{
 	case TYPE_REVERB:
 	{
-		alEffectf(PARAMSTR(1,REVERB,GAIN));
-		alEffectf(PARAMSTR(2,REVERB,GAINHF));
-		alEffectf(PARAMSTR(3,REVERB,DENSITY));
-		alEffectf(PARAMSTR(4,REVERB,DIFFUSION));
-		alEffectf(PARAMSTR(5,REVERB,DECAY_TIME));
-		alEffectf(PARAMSTR(6,REVERB,DECAY_HFRATIO));
-		alEffectf(PARAMSTR(7,REVERB,REFLECTIONS_GAIN));
-		alEffectf(PARAMSTR(8,REVERB,REFLECTIONS_DELAY));
-		alEffectf(PARAMSTR(9,REVERB,LATE_REVERB_GAIN));
-		alEffectf(PARAMSTR(10,REVERB,LATE_REVERB_DELAY));;
-		alEffectf(PARAMSTR(11,REVERB,ROOM_ROLLOFF_FACTOR));
-		alEffectf(PARAMSTR(12,REVERB,AIR_ABSORPTION_GAINHF));
-		alEffecti(effect, AL_REVERB_DECAY_HFLIMIT, params[13] < 0.5 ? AL_FALSE : AL_TRUE);
+		alEffectf(PARAMSTR(REVERB_GAIN,REVERB,GAIN));
+		alEffectf(PARAMSTR(REVERB_HFGAIN,REVERB,GAINHF));
+		alEffectf(PARAMSTR(REVERB_DENSITY,REVERB,DENSITY));
+		alEffectf(PARAMSTR(REVERB_DIFFUSION,REVERB,DIFFUSION));
+		alEffectf(PARAMSTR(REVERB_DECAY,REVERB,DECAY_TIME));
+		alEffectf(PARAMSTR(REVERB_HFDECAY,REVERB,DECAY_HFRATIO));
+		alEffectf(PARAMSTR(REVERB_EARLYGAIN,REVERB,REFLECTIONS_GAIN));
+		alEffectf(PARAMSTR(REVERB_EARLYDELAY,REVERB,REFLECTIONS_DELAY));
+		alEffectf(PARAMSTR(REVERB_LATEGAIN,REVERB,LATE_REVERB_GAIN));
+		alEffectf(PARAMSTR(REVERB_LATEDELAY,REVERB,LATE_REVERB_DELAY));;
+		alEffectf(PARAMSTR(REVERB_ROLLOFF,REVERB,ROOM_ROLLOFF_FACTOR));
+		alEffectf(PARAMSTR(REVERB_AIRHFGAIN,REVERB,AIR_ABSORPTION_GAINHF));
+		alEffecti(effect, AL_REVERB_DECAY_HFLIMIT, getValue(REVERB_HFLIMITER, 0));
 		break;
 	}
 	case TYPE_CHORUS:
 	{
-		Effect::Waveform wave = static_cast<Effect::Waveform>(params[1]);
-		if (wave == Effect::WAVE_SINE)
+		Waveform wave = static_cast<Waveform>(getValue(CHORUS_WAVEFORM, static_cast<int>(WAVE_MAX_ENUM)));
+		if (wave == WAVE_SINE)
 			alEffecti(effect, AL_CHORUS_WAVEFORM, AL_CHORUS_WAVEFORM_SINUSOID);
-		else if (wave == Effect::WAVE_TRIANGLE)
+		else if (wave == WAVE_TRIANGLE)
 			alEffecti(effect, AL_CHORUS_WAVEFORM, AL_CHORUS_WAVEFORM_TRIANGLE);
 		else
 			alEffecti(effect, AL_CHORUS_WAVEFORM, AL_CHORUS_DEFAULT_WAVEFORM);
 
-		alEffecti(PARAMSTR(2,CHORUS,PHASE));
-		alEffectf(PARAMSTR(3,CHORUS,RATE));
-		alEffectf(PARAMSTR(4,CHORUS,DEPTH));
-		alEffectf(PARAMSTR(5,CHORUS,FEEDBACK));
-		alEffectf(PARAMSTR(6,CHORUS,DELAY));
+		alEffecti(PARAMSTR(CHORUS_PHASE,CHORUS,PHASE));
+		alEffectf(PARAMSTR(CHORUS_RATE,CHORUS,RATE));
+		alEffectf(PARAMSTR(CHORUS_DEPTH,CHORUS,DEPTH));
+		alEffectf(PARAMSTR(CHORUS_FEEDBACK,CHORUS,FEEDBACK));
+		alEffectf(PARAMSTR(CHORUS_DELAY,CHORUS,DELAY));
 		break;
 	}
 	case TYPE_DISTORTION:
-		alEffectf(PARAMSTR(1,DISTORTION,GAIN));
-		alEffectf(PARAMSTR(2,DISTORTION,EDGE));
-		alEffectf(PARAMSTR(3,DISTORTION,LOWPASS_CUTOFF));
-		alEffectf(PARAMSTR(4,DISTORTION,EQCENTER));
-		alEffectf(PARAMSTR(5,DISTORTION,EQBANDWIDTH));
+		alEffectf(PARAMSTR(DISTORTION_GAIN,DISTORTION,GAIN));
+		alEffectf(PARAMSTR(DISTORTION_EDGE,DISTORTION,EDGE));
+		alEffectf(PARAMSTR(DISTORTION_LOWCUT,DISTORTION,LOWPASS_CUTOFF));
+		alEffectf(PARAMSTR(DISTORTION_EQCENTER,DISTORTION,EQCENTER));
+		alEffectf(PARAMSTR(DISTORTION_EQBAND,DISTORTION,EQBANDWIDTH));
 		break;
 
 	case TYPE_ECHO:
-		alEffectf(PARAMSTR(1,ECHO,DELAY));
-		alEffectf(PARAMSTR(2,ECHO,LRDELAY));
-		alEffectf(PARAMSTR(3,ECHO,DAMPING));
-		alEffectf(PARAMSTR(4,ECHO,FEEDBACK));
-		alEffectf(PARAMSTR(5,ECHO,SPREAD));
+		alEffectf(PARAMSTR(ECHO_DELAY,ECHO,DELAY));
+		alEffectf(PARAMSTR(ECHO_LRDELAY,ECHO,LRDELAY));
+		alEffectf(PARAMSTR(ECHO_DAMPING,ECHO,DAMPING));
+		alEffectf(PARAMSTR(ECHO_FEEDBACK,ECHO,FEEDBACK));
+		alEffectf(PARAMSTR(ECHO_SPREAD,ECHO,SPREAD));
 		break;
 
 	case TYPE_FLANGER:
 	{
-		Effect::Waveform wave = static_cast<Effect::Waveform>(params[1]);
-		if (wave == Effect::WAVE_SINE)
+		Waveform wave = static_cast<Waveform>(getValue(FLANGER_WAVEFORM, static_cast<int>(WAVE_MAX_ENUM)));
+		if (wave == WAVE_SINE)
 			alEffecti(effect, AL_FLANGER_WAVEFORM, AL_FLANGER_WAVEFORM_SINUSOID);
-		else if (wave == Effect::WAVE_TRIANGLE)
+		else if (wave == WAVE_TRIANGLE)
 			alEffecti(effect, AL_FLANGER_WAVEFORM, AL_FLANGER_WAVEFORM_TRIANGLE);
 		else
 			alEffecti(effect, AL_FLANGER_WAVEFORM, AL_FLANGER_DEFAULT_WAVEFORM);
 
-		alEffecti(PARAMSTR(2,FLANGER,PHASE));
-		alEffectf(PARAMSTR(3,FLANGER,RATE));
-		alEffectf(PARAMSTR(4,FLANGER,DEPTH));
-		alEffectf(PARAMSTR(5,FLANGER,FEEDBACK));
-		alEffectf(PARAMSTR(6,FLANGER,DELAY));
+		alEffecti(PARAMSTR(FLANGER_PHASE,FLANGER,PHASE));
+		alEffectf(PARAMSTR(FLANGER_RATE,FLANGER,RATE));
+		alEffectf(PARAMSTR(FLANGER_DEPTH,FLANGER,DEPTH));
+		alEffectf(PARAMSTR(FLANGER_FEEDBACK,FLANGER,FEEDBACK));
+		alEffectf(PARAMSTR(FLANGER_DELAY,FLANGER,DELAY));
 		break;
 	}
+/*
 	case TYPE_FREQSHIFTER:
 	{
-		alEffectf(PARAMSTR(1,FREQUENCY_SHIFTER,FREQUENCY)); 
+		alEffectf(PARAMSTR(FREQSHIFTER_FREQ,FREQUENCY_SHIFTER,FREQUENCY)); 
 
-		Effect::Direction dir = static_cast<Effect::Direction>(params[2]);
-		if (dir == Effect::DIR_NONE)
+		Direction dir = static_cast<Direction>(getValue(FREQSHIFTER_LEFTDIR, static_cast<int>(DIR_MAX_ENUM)));
+		if (dir == DIR_NONE)
 			alEffecti(effect, AL_FREQUENCY_SHIFTER_LEFT_DIRECTION, AL_FREQUENCY_SHIFTER_DIRECTION_OFF);
-		else if(dir == Effect::DIR_UP)
+		else if(dir == DIR_UP)
 			alEffecti(effect, AL_FREQUENCY_SHIFTER_LEFT_DIRECTION, AL_FREQUENCY_SHIFTER_DIRECTION_UP);
-		else if(dir == Effect::DIR_DOWN)
+		else if(dir == DIR_DOWN)
 			alEffecti(effect, AL_FREQUENCY_SHIFTER_LEFT_DIRECTION, AL_FREQUENCY_SHIFTER_DIRECTION_DOWN);
 		else 
 			alEffecti(effect, AL_FREQUENCY_SHIFTER_LEFT_DIRECTION, AL_FREQUENCY_SHIFTER_DEFAULT_LEFT_DIRECTION);
 
-		dir = static_cast<Effect::Direction>(params[3]);
-		if (dir == Effect::DIR_NONE)
+		dir = static_cast<Direction>(getValue(FREQSHIFTER_RIGHTDIR, static_cast<int>(DIR_MAX_ENUM)));
+		if (dir == DIR_NONE)
 			alEffecti(effect, AL_FREQUENCY_SHIFTER_RIGHT_DIRECTION, AL_FREQUENCY_SHIFTER_DIRECTION_OFF);
-		else if(dir == Effect::DIR_UP)
+		else if(dir == DIR_UP)
 			alEffecti(effect, AL_FREQUENCY_SHIFTER_RIGHT_DIRECTION, AL_FREQUENCY_SHIFTER_DIRECTION_UP);
-		else if(dir == Effect::DIR_DOWN)
+		else if(dir == DIR_DOWN)
 			alEffecti(effect, AL_FREQUENCY_SHIFTER_RIGHT_DIRECTION, AL_FREQUENCY_SHIFTER_DIRECTION_DOWN);
 		else 
 			alEffecti(effect, AL_FREQUENCY_SHIFTER_RIGHT_DIRECTION, AL_FREQUENCY_SHIFTER_DEFAULT_RIGHT_DIRECTION);
@@ -242,110 +249,110 @@ bool Effect::setParams(Type type, const std::vector<float> &params)
 	}
 	case TYPE_MORPHER:
 	{
-		Effect::Waveform wave = static_cast<Effect::Waveform>(params[1]);
-		if (wave == Effect::WAVE_SINE)
+		Waveform wave = static_cast<Waveform>(getValue(MORPHER_WAVEFORM, static_cast<int>(WAVE_MAX_ENUM)));
+		if (wave == WAVE_SINE)
 			alEffecti(effect, AL_VOCAL_MORPHER_WAVEFORM, AL_VOCAL_MORPHER_WAVEFORM_SINUSOID);
-		else if (wave == Effect::WAVE_TRIANGLE)
+		else if (wave == WAVE_TRIANGLE)
 			alEffecti(effect, AL_VOCAL_MORPHER_WAVEFORM, AL_VOCAL_MORPHER_WAVEFORM_TRIANGLE);
-		else if (wave == Effect::WAVE_SAWTOOTH)
+		else if (wave == WAVE_SAWTOOTH)
 			alEffecti(effect, AL_VOCAL_MORPHER_WAVEFORM, AL_VOCAL_MORPHER_WAVEFORM_SAWTOOTH);
 		else
 			alEffecti(effect, AL_VOCAL_MORPHER_WAVEFORM, AL_VOCAL_MORPHER_DEFAULT_WAVEFORM);
 
-		alEffectf(PARAMSTR(2,VOCAL_MORPHER,RATE));
-
-		if (isnanf(params[3]))
+		Phoneme phoneme = static_cast<Phoneme>(getValue(MORPHER_PHONEMEA, static_cast<int>(PHONEME_MAX_ENUM)));
+		if (phoneme == PHONEME_MAX_ENUM)
 			alEffecti(effect, AL_VOCAL_MORPHER_PHONEMEA, AL_VOCAL_MORPHER_DEFAULT_PHONEMEA);
 		else
-			alEffecti(effect, AL_VOCAL_MORPHER_PHONEMEA, phonemeMap[static_cast<Effect::Phoneme>(params[2])]);
+			alEffecti(effect, AL_VOCAL_MORPHER_PHONEMEA, phonemeMap[phoneme]);
 
-		if (isnanf(params[4]))
+		phoneme = static_cast<Phoneme>(getValue(MORPHER_PHONEMEB, static_cast<int>(PHONEME_MAX_ENUM)));
+		if (phoneme == PHONEME_MAX_ENUM)
 			alEffecti(effect, AL_VOCAL_MORPHER_PHONEMEB, AL_VOCAL_MORPHER_DEFAULT_PHONEMEB);
 		else
-			alEffecti(effect, AL_VOCAL_MORPHER_PHONEMEB, phonemeMap[static_cast<Effect::Phoneme>(params[3])]);
+			alEffecti(effect, AL_VOCAL_MORPHER_PHONEMEB, phonemeMap[phoneme]);
 
-		alEffecti(PARAMSTR(5,VOCAL_MORPHER,PHONEMEA_COARSE_TUNING));
-		alEffecti(PARAMSTR(6,VOCAL_MORPHER,PHONEMEB_COARSE_TUNING));
+		alEffectf(PARAMSTR(MORPHER_RATE,VOCAL_MORPHER,RATE));
+		alEffecti(PARAMSTR(MORPHER_TUNEA,VOCAL_MORPHER,PHONEMEA_COARSE_TUNING));
+		alEffecti(PARAMSTR(MORPHER_TUNEB,VOCAL_MORPHER,PHONEMEB_COARSE_TUNING));
 		break;
 	}
 	case TYPE_PITCHSHIFTER:
 	{
-		int coarse = AL_PITCH_SHIFTER_DEFAULT_COARSE_TUNE;
-		int fine = AL_PITCH_SHIFTER_DEFAULT_FINE_TUNE;
-		if (!isnanf(params[1]))
+		float tune = getValue(PITCHSHIFTER_PITCH, (float)AL_PITCH_SHIFTER_DEFAULT_COARSE_TUNE + (float)(AL_PITCH_SHIFTER_DEFAULT_FINE_TUNE - 50) / 100.0 );
+
+		int coarse = (int)floor(tune);
+		int fine = (int)(fmod(tune, 1.0)*100.0);
+		if (fine > 50)
+		{
+			fine -= 100;
+			coarse += 1;
+		}
+		else if (fine < -50)
+		{
+			fine += 100;
+			coarse -= 1;
+		}
+		if (coarse > AL_PITCH_SHIFTER_MAX_COARSE_TUNE)
 		{
-			coarse = (int)floor(params[1]);
-			fine = (int)(fmod(params[1], 1.0)*100.0);
-			if (fine > 50)
-			{
-				fine -= 100;
-				coarse += 1;
-			}
-			else if (fine < -50)
-			{
-				fine += 100;
-				coarse -= 1;
-			}
-			if (coarse > AL_PITCH_SHIFTER_MAX_COARSE_TUNE)
-			{
-				coarse = AL_PITCH_SHIFTER_MAX_COARSE_TUNE;
-				fine = AL_PITCH_SHIFTER_MAX_FINE_TUNE;
-			}
-			else if (coarse < AL_PITCH_SHIFTER_MIN_COARSE_TUNE)
-			{
-				coarse = AL_PITCH_SHIFTER_MIN_COARSE_TUNE;
-				fine = AL_PITCH_SHIFTER_MIN_FINE_TUNE;
-			}
+			coarse = AL_PITCH_SHIFTER_MAX_COARSE_TUNE;
+			fine = AL_PITCH_SHIFTER_MAX_FINE_TUNE;
+		}
+		else if (coarse < AL_PITCH_SHIFTER_MIN_COARSE_TUNE)
+		{
+			coarse = AL_PITCH_SHIFTER_MIN_COARSE_TUNE;
+			fine = AL_PITCH_SHIFTER_MIN_FINE_TUNE;
 		}
 		alEffecti(effect, AL_PITCH_SHIFTER_COARSE_TUNE, coarse);
 		alEffecti(effect, AL_PITCH_SHIFTER_FINE_TUNE, fine);
 		break;
 	}
-
+*/
 	case TYPE_MODULATOR:
 	{
-		Effect::Waveform wave = static_cast<Effect::Waveform>(params[1]);
-		if (wave == Effect::WAVE_SINE)
+		Waveform wave = static_cast<Waveform>(getValue(MODULATOR_WAVEFORM,static_cast<int>(WAVE_MAX_ENUM)));
+		if (wave == WAVE_SINE)
 			alEffecti(effect, AL_RING_MODULATOR_WAVEFORM, AL_RING_MODULATOR_SINUSOID);
-		else if (wave == Effect::WAVE_SAWTOOTH)
+		else if (wave == WAVE_SAWTOOTH)
 			alEffecti(effect, AL_RING_MODULATOR_WAVEFORM, AL_RING_MODULATOR_SAWTOOTH);
-		else if (wave == Effect::WAVE_SQUARE)
+		else if (wave == WAVE_SQUARE)
 			alEffecti(effect, AL_RING_MODULATOR_WAVEFORM, AL_RING_MODULATOR_SQUARE);
 		else
 			alEffecti(effect, AL_RING_MODULATOR_WAVEFORM, AL_RING_MODULATOR_DEFAULT_WAVEFORM);
 
-		alEffectf(PARAMSTR(2,RING_MODULATOR,FREQUENCY));
-		alEffectf(PARAMSTR(3,RING_MODULATOR,HIGHPASS_CUTOFF));
+		alEffectf(PARAMSTR(MODULATOR_FREQ,RING_MODULATOR,FREQUENCY));
+		alEffectf(PARAMSTR(MODULATOR_HIGHCUT,RING_MODULATOR,HIGHPASS_CUTOFF));
 		break;
 	}
+/*
 	case TYPE_AUTOWAH:
-		alEffectf(PARAMSTR(1,AUTOWAH,ATTACK_TIME));
-		alEffectf(PARAMSTR(2,AUTOWAH,RELEASE_TIME));
-		alEffectf(PARAMSTR(3,AUTOWAH,RESONANCE));
-		alEffectf(PARAMSTR(4,AUTOWAH,PEAK_GAIN));
+		alEffectf(PARAMSTR(AUTOWAH_ATTACK,AUTOWAH,ATTACK_TIME));
+		alEffectf(PARAMSTR(AUTOWAH_RELEASE,AUTOWAH,RELEASE_TIME));
+		alEffectf(PARAMSTR(AUTOWAH_RESONANCE,AUTOWAH,RESONANCE));
+		alEffectf(PARAMSTR(AUTOWAH_PEAKGAIN,AUTOWAH,PEAK_GAIN));
 		break;
-
+*/
 	case TYPE_COMPRESSOR:
-		alEffecti(effect, AL_COMPRESSOR_ONOFF, params[1] < 0.5 ? 0 : 1);
+		alEffecti(effect, AL_COMPRESSOR_ONOFF, getValue(COMPRESSOR_ENABLE,static_cast<int>(AL_COMPRESSOR_DEFAULT_ONOFF)));
 		break;
 
 	case TYPE_EQUALIZER:
-		alEffectf(PARAMSTR(1,EQUALIZER,LOW_GAIN));
-		alEffectf(PARAMSTR(2,EQUALIZER,LOW_CUTOFF));
-		alEffectf(PARAMSTR(3,EQUALIZER,MID1_GAIN));
-		alEffectf(PARAMSTR(4,EQUALIZER,MID1_CENTER));
-		alEffectf(PARAMSTR(5,EQUALIZER,MID1_WIDTH));
-		alEffectf(PARAMSTR(6,EQUALIZER,MID2_GAIN));
-		alEffectf(PARAMSTR(7,EQUALIZER,MID2_CENTER));
-		alEffectf(PARAMSTR(8,EQUALIZER,MID2_WIDTH));
-		alEffectf(PARAMSTR(9,EQUALIZER,HIGH_GAIN));
-		alEffectf(PARAMSTR(10,EQUALIZER,HIGH_CUTOFF));
+		alEffectf(PARAMSTR(EQUALIZER_LOWGAIN,EQUALIZER,LOW_GAIN));
+		alEffectf(PARAMSTR(EQUALIZER_LOWCUT,EQUALIZER,LOW_CUTOFF));
+		alEffectf(PARAMSTR(EQUALIZER_MID1GAIN,EQUALIZER,MID1_GAIN));
+		alEffectf(PARAMSTR(EQUALIZER_MID1FREQ,EQUALIZER,MID1_CENTER));
+		alEffectf(PARAMSTR(EQUALIZER_MID1BAND,EQUALIZER,MID1_WIDTH));
+		alEffectf(PARAMSTR(EQUALIZER_MID2GAIN,EQUALIZER,MID2_GAIN));
+		alEffectf(PARAMSTR(EQUALIZER_MID2FREQ,EQUALIZER,MID2_CENTER));
+		alEffectf(PARAMSTR(EQUALIZER_MID2BAND,EQUALIZER,MID2_WIDTH));
+		alEffectf(PARAMSTR(EQUALIZER_HIGHGAIN,EQUALIZER,HIGH_GAIN));
+		alEffectf(PARAMSTR(EQUALIZER_HIGHCUT,EQUALIZER,HIGH_CUTOFF));
 		break;
-
+	case TYPE_BASIC:
 	case TYPE_MAX_ENUM:
 		break;
 	}
 	#undef PARAMSTR
+	#undef clampf
 	//alGetError();
 
 	return true;
@@ -354,20 +361,22 @@ bool Effect::setParams(Type type, const std::vector<float> &params)
 	#endif //ALC_EXT_EFX
 }
 
-const std::vector<float> &Effect::getParams() const
+const std::map<Effect::Parameter, float> &Effect::getParams() const
 {
 	return params;
 }
 
-//clamp values silently to avoid randomly throwing errors due to implementation differences
-float Effect::clampf(float val, float min, float max, float def)
+float Effect::getValue(Parameter in, float def) const
+{
+	return params.find(in) == params.end() ? def : params.at(in);
+}
+
+int Effect::getValue(Parameter in, int def) const
 {
-	if (isnanf(val)) return def;
-	else if (val < min) val = min;
-	else if (val > max) val = max;
-	return val;
+	return params.find(in) == params.end() ? def : static_cast<int>(params.at(in));
 }
 
+/*
 std::map<Effect::Phoneme, ALint> Effect::phonemeMap = 
 {
 	{Effect::PHONEME_A, AL_VOCAL_MORPHER_PHONEME_A},
@@ -401,6 +410,7 @@ std::map<Effect::Phoneme, ALint> Effect::phonemeMap =
 	{Effect::PHONEME_V, AL_VOCAL_MORPHER_PHONEME_V},
 	{Effect::PHONEME_Z, AL_VOCAL_MORPHER_PHONEME_Z}
 };
+*/
 
 } //openal
 } //audio

+ 7 - 5
src/modules/audio/openal/Effect.h

@@ -66,16 +66,18 @@ public:
 	virtual ~Effect();
 	virtual Effect *clone();
 	ALuint getEffect() const;
-	virtual bool setParams(Type type, const std::vector<float> &params);
-	virtual const std::vector<float> &getParams() const;
+	virtual bool setParams(const std::map<Parameter, float> &params);
+	virtual const std::map<Parameter, float> &getParams() const;
 
 private:
 	bool generateEffect();
 	void deleteEffect();
-	float clampf(float val, float min, float max, float def);
+	float getValue(Parameter in, float def) const;
+	int getValue(Parameter in, int def) const;
+
 	ALuint effect = AL_EFFECT_NULL;
-	std::vector<float> params;
-	static std::map<Phoneme, ALint> phonemeMap;
+	std::map<Parameter, float> params;
+	//static std::map<Phoneme, ALint> phonemeMap;
 };
 
 } //openal

+ 127 - 124
src/modules/audio/wrap_Audio.cpp

@@ -305,109 +305,107 @@ int w_getRecordingDevices(lua_State *L)
 	return 1;
 }
 
-int setSceneEffectHandleParam(lua_State *L, int pos, Effect::ParameterType type, std::vector<float> &params)
-{
-	if (lua_isnoneornil(L, pos))
-		params.push_back(nanf(""));
-	else
-	{
-		const char *typestr;
-		switch (type)
-		{
-		case Effect::PAR_FLOAT:
-			params.push_back(luaL_checknumber(L, pos)); 
-			break;
-		case Effect::PAR_BOOL:
-			if (!lua_isboolean(L, pos))
-				return luax_typerror(L, pos, "boolean");
-			params.push_back(lua_toboolean(L, pos) ? 1.0 : 0.0); 
-			break;
-		case Effect::PAR_WAVEFORM:
-		{
-			typestr = luaL_checkstring(L, pos);
-			Effect::Waveform waveform;
-			if (!Effect::getConstant(typestr, waveform))
-				return luaL_error(L, "Invalid waveform type: %s", typestr);
-			params.push_back(static_cast<int>(waveform));
-			break;
-		}
-		case Effect::PAR_DIRECTION:
-		{
-			typestr = luaL_checkstring(L, pos);
-			Effect::Direction direction;
-			if (!Effect::getConstant(typestr, direction))
-				return luaL_error(L, "Invalid direction type: %s", typestr);
-			params.push_back(static_cast<int>(direction));
-			break;
-		}
-		case Effect::PAR_PHONEME:
-		{
-			typestr = luaL_checkstring(L, pos);
-			Effect::Phoneme phoneme;
-			if (!Effect::getConstant(typestr, phoneme))
-				return luaL_error(L, "Invalid phoneme type: %s", typestr);
-			params.push_back(static_cast<int>(phoneme));
-			break;
-		}
-		case Effect::PAR_MAX_ENUM:
-			break;
-		}
-	}
-	return 0;
-}
-
 int w_setSceneEffect(lua_State *L)
 {
 	int slot = luaL_checknumber(L, 1) - 1;
 
-	const char *typestr;
-	Effect::Type type;
-	std::vector<float> params;
-
-	if (lua_gettop(L) == 1)
+	if (lua_gettop(L) == 1 || (lua_gettop(L) == 2 && lua_isnoneornil(L, 2)))
 	{
 		lua_pushboolean(L, instance()->setSceneEffect(slot));
 		return 1;
 	}
-	else if (lua_gettop(L) > 2)
-	{
-		typestr = luaL_checkstring(L, 2);
-		if (!Effect::getConstant(typestr, type))
-			return luaL_error(L, "Invalid effect type: %s", typestr);
-
-		params.push_back(luaL_checknumber(L, 3));
-		const std::vector<Effect::ParameterType> &paramtypes = Effect::getParameterTypes(type);
-		for (unsigned int i = 0; i < paramtypes.size(); i++)
-			setSceneEffectHandleParam(L, i + 4, paramtypes[i], params);
-	}
-	else if (lua_istable(L, 2))
+
+	luaL_checktype(L, 2, LUA_TTABLE);
+
+	const char *paramstr = nullptr;
+
+	//find type (mandatory)
+	Effect::getConstant(Effect::EFFECT_TYPE, paramstr, Effect::TYPE_BASIC);
+	lua_pushstring(L, paramstr);
+	lua_rawget(L, 2);
+	if (lua_type(L, -1) == LUA_TNIL)
+		return luaL_error(L, "Effect type not specificed.");
+
+	Effect::Type type = Effect::TYPE_MAX_ENUM;
+	const char *typestr = luaL_checkstring(L, -1);
+	if (!Effect::getConstant(typestr, type))
+		return luaL_error(L, "Invalid Effect type: %s", typestr);
+
+	lua_pop(L, 1);
+	std::map<Effect::Parameter, float> params;
+	params[Effect::EFFECT_TYPE] = static_cast<int>(type);
+
+	// Iterate over the whole table, reading valid parameters and erroring on invalid ones
+	lua_pushnil(L);
+	while (lua_next(L, 2))
 	{
-		if (lua_objlen(L, 2) == 0) //empty table also clears effect
+		const char *keystr = luaL_checkstring(L, -2);
+		Effect::Parameter param;
+
+		if(Effect::getConstant(keystr, param, type) || Effect::getConstant(keystr, param, Effect::TYPE_BASIC))
 		{
-			lua_pushboolean(L, instance()->setSceneEffect(slot));
-			return 1;
+			#define luax_effecterror(l,t) luaL_error(l,"Bad parameter type for %s %s: " t " expected, got %s", typestr, keystr, lua_typename(L, -1))
+			switch(Effect::getParameterType(param))
+			{
+			case Effect::PARAM_FLOAT:
+				if (!lua_isnumber(L, -1))
+					return luax_effecterror(L, "number");
+				params[param] = lua_tonumber(L, -1);
+				break;
+			case Effect::PARAM_BOOL:
+				if (!lua_isboolean(L, -1))
+					return luax_effecterror(L, "boolean");
+				params[param] = lua_toboolean(L, -1) ? 1.0 : 0.0; 
+				break;
+			case Effect::PARAM_WAVEFORM:
+			{
+				if (!lua_isstring(L, -1))
+					return luax_effecterror(L, "string");
+				paramstr = lua_tostring(L, -1);
+				Effect::Waveform waveform;
+				if (!Effect::getConstant(paramstr, waveform))
+					return luaL_error(L, "Invalid waveform type: %s", paramstr);
+				params[param] = static_cast<int>(waveform);
+				break;
+			}
+			/*
+			case Effect::PARAM_DIRECTION:
+			{
+				if (!lua_isstring(L, -1))
+					return luax_effecterror(L, "string");
+				paramstr = lua_tostring(L, -1);
+				Effect::Direction direction;
+				if (!Effect::getConstant(paramstr, direction))
+					return luaL_error(L, "Invalid direction type: %s", paramstr);
+				params[param] = static_cast<int>(direction);
+				break;
+			}
+			case Effect::PARAM_PHONEME:
+			{
+				if (!lua_isstring(L, -1))
+					return luax_effecterror(L, "string");
+				paramstr = lua_tostring(L, -1);
+				Effect::Phoneme phoneme;
+				if (!Effect::getConstant(basicstr, phoneme))
+					return luaL_error(L, "Invalid phoneme type: %s", paramstr);
+				params[param] = static_cast<int>(phoneme);
+				break;
+			}
+			*/
+			case Effect::PARAM_TYPE:
+			case Effect::PARAM_MAX_ENUM:
+				break;
+			}
+			#undef luaL_effecterror
 		}
-		lua_rawgeti(L, 2, 1);
-		typestr = luaL_checkstring(L, -1);
-		if (!Effect::getConstant(typestr, type))
-			return luaL_error(L, "Invalid effect type: %s", typestr);
-		lua_pop(L, 1);
+		else
+			luaL_error(L, "Invalid '%s' Effect parameter: %s", typestr, keystr);
 
-		const std::vector<Effect::ParameterType> &paramtypes = Effect::getParameterTypes(type);
-		lua_rawgeti(L, 2, 2);
-		params.push_back(luaL_checknumber(L, -1));
+		//remove the value (-1) from stack, keep the key (-2) to feed into lua_next
 		lua_pop(L, 1);
-		for (unsigned int i = 0; i < paramtypes.size(); i++)
-		{
-			lua_rawgeti(L, 2, i + 3);
-			setSceneEffectHandleParam(L, -1, paramtypes[i], params);
-			lua_pop(L, 1);
-		}
 	}
-	else
-		return luax_typerror(L, 2, "effect description");
 
-	luax_catchexcept(L, [&]() { lua_pushboolean(L, instance()->setSceneEffect(slot, type, params)); });
+	luax_catchexcept(L, [&]() { lua_pushboolean(L, instance()->setSceneEffect(slot, params)); });
 	return 1;
 }
 
@@ -415,49 +413,54 @@ int w_getSceneEffect(lua_State *L)
 {
 	int slot = luaL_checknumber(L, 1) - 1;
 
-	Effect::Type type;
-	std::vector<float> params;
+	std::map<Effect::Parameter, float> params;
 
-	if (!instance()->getSceneEffect(slot, type, params))
+	if (!instance()->getSceneEffect(slot, params))
 		return 0;
 
-	const char *str = nullptr;
-	Effect::getConstant(type, str);
-	lua_pushstring(L, str);
-	lua_pushnumber(L, params[0]);
+	const char *keystr, *valstr;
+	Effect::Type type = static_cast<Effect::Type>((int)params[Effect::EFFECT_TYPE]);
 
-	const std::vector<Effect::ParameterType> &paramtypes = Effect::getParameterTypes(type);
+	lua_createtable(L, 0, params.size());
 
-	for (unsigned int i = 1; i < params.size(); i++)
+	for (auto p : params)
 	{
-		if (isnanf(params[i]))
-			lua_pushnil(L);
-		else
-			switch(paramtypes[i-1])
-			{
-			case Effect::PAR_FLOAT:
-				lua_pushnumber(L, params[i]); 
-				break;
-			case Effect::PAR_BOOL:
-				lua_pushboolean(L, params[i] < 0.5 ? false : true); 
-				break;
-			case Effect::PAR_WAVEFORM:
-				Effect::getConstant(static_cast<Effect::Waveform>((int)params[i]), str);
-				lua_pushstring(L, str);
-				break;
-			case Effect::PAR_DIRECTION:
-				Effect::getConstant(static_cast<Effect::Direction>((int)params[i]), str);
-				lua_pushstring(L, str);
-				break;
-			case Effect::PAR_PHONEME:
-				Effect::getConstant(static_cast<Effect::Phoneme>((int)params[i]), str);
-				lua_pushstring(L, str);
-				break;
-			case Effect::PAR_MAX_ENUM:
-				break;
-			}
+		if (!Effect::getConstant(p.first, keystr, type))
+			Effect::getConstant(p.first, keystr, Effect::TYPE_BASIC);
+
+		lua_pushstring(L, keystr);
+		switch (Effect::getParameterType(p.first))
+		{
+		case Effect::PARAM_FLOAT:
+			lua_pushnumber(L, p.second);
+			break;
+		case Effect::PARAM_BOOL:
+			lua_pushboolean(L, p.second > 0.5 ? true : false);
+			break;
+		case Effect::PARAM_WAVEFORM:
+			Effect::getConstant(static_cast<Effect::Waveform>((int)p.second), valstr);
+			lua_pushstring(L, valstr);
+			break;
+/*
+		case Effect::PARAM_DIRECTION:
+			Effect::getConstant(static_cast<Effect::Direction>((int)p.second), valstr);
+			lua_pushstring(L, valstr);
+			break;
+		case Effect::PARAM_PHONEME:
+			Effect::getConstant(static_cast<Effect::Phoneme>((int)p.second), valstr);
+			lua_pushstring(L, valstr);
+			break;
+*/
+		case Effect::PARAM_TYPE:
+			Effect::getConstant(static_cast<Effect::Type>((int)p.second), valstr);
+			lua_pushstring(L, valstr);
+			break;
+		case Effect::PARAM_MAX_ENUM:
+			break;
+		}
+		lua_rawset(L, -3);
 	}
-	return params.size() + 1;
+	return 1;
 }
 
 int w_getMaxSceneEffects(lua_State *L)