From 42f89153ae9b095f8d84db9d75153a01e0f6e303 Mon Sep 17 00:00:00 2001 From: Raidho Date: Fri, 6 Jan 2017 08:41:27 +0300 Subject: [PATCH] Named Effect parameters added. Unsupported effects disabled. Unnamed parameter Effect setting is no longer functional. --HG-- branch : minor --- src/modules/audio/Audio.h | 10 +- src/modules/audio/Effect.cpp | 270 ++++++++++++++++++++++++---- src/modules/audio/Effect.h | 190 +++++++++++++++++--- src/modules/audio/null/Audio.cpp | 4 +- src/modules/audio/null/Audio.h | 4 +- src/modules/audio/openal/Audio.cpp | 10 +- src/modules/audio/openal/Audio.h | 4 +- src/modules/audio/openal/Effect.cpp | 252 +++++++++++++------------- src/modules/audio/openal/Effect.h | 12 +- src/modules/audio/wrap_Audio.cpp | 249 ++++++++++++------------- 10 files changed, 683 insertions(+), 322 deletions(-) diff --git a/src/modules/audio/Audio.h b/src/modules/audio/Audio.h index 66d83e04d..0f0a1cd9c 100644 --- a/src/modules/audio/Audio.h +++ b/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 ¶ms) = 0; + virtual bool setSceneEffect(int slot, std::map ¶ms) = 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 ¶ms) = 0; + virtual bool getSceneEffect(int slot, std::map ¶ms) = 0; /** * Gets maximum number of scene EFX effects. diff --git a/src/modules/audio/Effect.cpp b/src/modules/audio/Effect.cpp index 92292d211..c824cfdf4 100644 --- a/src/modules/audio/Effect.cpp +++ b/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); +} -const std::vector &Effect::getParameterTypes(Effect::Type in) +bool Effect::getConstant(Parameter in, const char *&out, Type t) +{ + return parameterNames[t].find(in, out); +} + +Effect::ParameterType Effect::getParameterType(Effect::Parameter in) { return parameterTypes[in]; } @@ -90,11 +100,11 @@ StringMap::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::Entry Effect::waveformEntrie StringMap Effect::waveforms(Effect::waveformEntries, sizeof(Effect::waveformEntries)); +/* StringMap::Entry Effect::directionEntries[] = { {"up", Effect::DIR_UP}, @@ -155,35 +166,224 @@ StringMap::Entry Effect::phonemeEntri }; StringMap Effect::phonemes(Effect::phonemeEntries, sizeof(Effect::phonemeEntries)); +*/ -std::map> Effect::parameterTypes = +#define StringMap LazierAndSlowerButEasilyArrayableStringMap + +std::vector::Entry> Effect::basicParameters = { - //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}}, + {"type", Effect::EFFECT_TYPE}, + {"volume", Effect::EFFECT_VOLUME} +}; + +std::vector::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::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::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::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::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::Entry> Effect::freqshifterParameters = +{ + {"frequency", Effect::FREQSHIFTER_FREQ}, + {"leftdirection", Effect::FREQSHIFTER_LEFTDIR}, + {"rightdirection", Effect::FREQSHIFTER_RIGHTDIR} +}; + +std::vector::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::Entry> Effect::pitchshifterParameters = +{ + {"pitch", Effect::PITCHSHIFTER_PITCH} +}; +*/ +std::vector::Entry> Effect::modulatorParameters = +{ + {"waveform", Effect::MODULATOR_WAVEFORM}, + {"frequency", Effect::MODULATOR_FREQ}, + {"highcut", Effect::MODULATOR_HIGHCUT} +}; +/* +std::vector::Entry> Effect::autowahParameters = +{ + {"attack", Effect::AUTOWAH_ATTACK}, + {"release", Effect::AUTOWAH_RELEASE}, + {"resonance", Effect::AUTOWAH_RESONANCE}, + {"peakgain", Effect::AUTOWAH_PEAKGAIN} +}; +*/ +std::vector::Entry> Effect::compressorParameters = +{ + {"enable", Effect::COMPRESSOR_ENABLE} +}; + +std::vector::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::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::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}, + + {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 diff --git a/src/modules/audio/Effect.h b/src/modules/audio/Effect.h index d4f10d5d6..c39f8f927 100644 --- a/src/modules/audio/Effect.h +++ b/src/modules/audio/Effect.h @@ -26,6 +26,49 @@ #include #include +template +class LazierAndSlowerButEasilyArrayableStringMap +{ +public: + struct Entry + { + const char *key; + T value; + }; + LazierAndSlowerButEasilyArrayableStringMap() + { + } + + LazierAndSlowerButEasilyArrayableStringMap(const std::vector &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 forward; + std::map 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 &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 types; static StringMap::Entry waveformEntries[]; static StringMap waveforms; - static StringMap::Entry directionEntries[]; - static StringMap directions; - static StringMap::Entry phonemeEntries[]; - static StringMap phonemes; - static std::map> parameterTypes; + //static StringMap::Entry directionEntries[]; + //static StringMap directions; + //static StringMap::Entry phonemeEntries[]; + //static StringMap phonemes; +#define StringMap LazierAndSlowerButEasilyArrayableStringMap + static std::vector::Entry> basicParameters; + static std::vector::Entry> reverbParameters; + static std::vector::Entry> chorusParameters; + static std::vector::Entry> distortionParameters; + static std::vector::Entry> echoParameters; + static std::vector::Entry> flangerParameters; + //static std::vector::Entry> freqshifterParameters; + //static std::vector::Entry> morpherParameters; + //static std::vector::Entry> pitchshifterParameters; + static std::vector::Entry> modulatorParameters; + //static std::vector::Entry> autowahParameters; + static std::vector::Entry> compressorParameters; + static std::vector::Entry> equalizerParameters; + static std::map> parameterNames; +#undef StringMap + static std::map parameterTypes; + }; } //audio diff --git a/src/modules/audio/null/Audio.cpp b/src/modules/audio/null/Audio.cpp index 49e82cac7..54486d1c6 100644 --- a/src/modules/audio/null/Audio.cpp +++ b/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 &) +bool Audio::setSceneEffect(int, std::map &) { return false; } @@ -178,7 +178,7 @@ bool Audio::setSceneEffect(int) return false; } -bool Audio::getSceneEffect(int, Effect::Type &, std::vector &) +bool Audio::getSceneEffect(int, std::map &) { return false; } diff --git a/src/modules/audio/null/Audio.h b/src/modules/audio/null/Audio.h index 58e07183c..057d71d2c 100644 --- a/src/modules/audio/null/Audio.h +++ b/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 ¶ms); + bool setSceneEffect(int slot, std::map ¶ms); bool setSceneEffect(int slot); - bool getSceneEffect(int slot, Effect::Type &type, std::vector ¶ms); + bool getSceneEffect(int slot, std::map ¶ms); int getMaxSceneEffects() const; int getMaxSourceEffects() const; bool isEFXsupported() const; diff --git a/src/modules/audio/openal/Audio.cpp b/src/modules/audio/openal/Audio.cpp index e52d1f200..5a7787fff 100644 --- a/src/modules/audio/openal/Audio.cpp +++ b/src/modules/audio/openal/Audio.cpp @@ -445,7 +445,7 @@ const std::vector &Audio::getRecordingDevices() return capture; } -bool Audio::setSceneEffect(int slot, Effect::Type type, std::vector ¶ms) +bool Audio::setSceneEffect(int slot, std::map ¶ms) { if (slot < 0 || slot >= MAX_SCENE_EFFECTS) return false; @@ -453,15 +453,16 @@ bool Audio::setSceneEffect(int slot, Effect::Type type, std::vector ¶ 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 ¶ms) +bool Audio::getSceneEffect(int slot, std::map ¶ms) { if (slot < 0 || slot >= MAX_SCENE_EFFECTS) return false; @@ -498,7 +499,6 @@ bool Audio::getSceneEffect(int slot, Effect::Type &type, std::vector &par if (!effects[slot]) return false; - type = effects[slot]->getType(); params = effects[slot]->getParams(); return true; diff --git a/src/modules/audio/openal/Audio.h b/src/modules/audio/openal/Audio.h index 82a26b1c3..3119ef950 100644 --- a/src/modules/audio/openal/Audio.h +++ b/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 ¶ms); + bool setSceneEffect(int slot, std::map ¶ms); bool setSceneEffect(int slot); - bool getSceneEffect(int slot, Effect::Type &type, std::vector ¶ms); + bool getSceneEffect(int slot, std::map ¶ms); int getMaxSceneEffects() const; int getMaxSourceEffects() const; bool isEFXsupported() const; diff --git a/src/modules/audio/openal/Effect.cpp b/src/modules/audio/openal/Effect.cpp index 8af3e394c..850ae7c48 100644 --- a/src/modules/audio/openal/Effect.cpp +++ b/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 ¶ms) +bool Effect::setParams(const std::map ¶ms) { - this->type = type; this->params = params; + type = static_cast(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 ¶ms) 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 ¶ms) 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 ¶ms) 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(params[1]); - if (wave == Effect::WAVE_SINE) + Waveform wave = static_cast(getValue(CHORUS_WAVEFORM, static_cast(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(params[1]); - if (wave == Effect::WAVE_SINE) + Waveform wave = static_cast(getValue(FLANGER_WAVEFORM, static_cast(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(params[2]); - if (dir == Effect::DIR_NONE) + Direction dir = static_cast(getValue(FREQSHIFTER_LEFTDIR, static_cast(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(params[3]); - if (dir == Effect::DIR_NONE) + dir = static_cast(getValue(FREQSHIFTER_RIGHTDIR, static_cast(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 ¶ms) } case TYPE_MORPHER: { - Effect::Waveform wave = static_cast(params[1]); - if (wave == Effect::WAVE_SINE) + Waveform wave = static_cast(getValue(MORPHER_WAVEFORM, static_cast(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(getValue(MORPHER_PHONEMEA, static_cast(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(params[2])]); + alEffecti(effect, AL_VOCAL_MORPHER_PHONEMEA, phonemeMap[phoneme]); - if (isnanf(params[4])) + phoneme = static_cast(getValue(MORPHER_PHONEMEB, static_cast(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(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) { - 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; - } + 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; } 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(params[1]); - if (wave == Effect::WAVE_SINE) + Waveform wave = static_cast(getValue(MODULATOR_WAVEFORM,static_cast(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(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 ¶ms) #endif //ALC_EXT_EFX } -const std::vector &Effect::getParams() const +const std::map &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 { - 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 : params.at(in); } +int Effect::getValue(Parameter in, int def) const +{ + return params.find(in) == params.end() ? def : static_cast(params.at(in)); +} + +/* std::map Effect::phonemeMap = { {Effect::PHONEME_A, AL_VOCAL_MORPHER_PHONEME_A}, @@ -401,6 +410,7 @@ std::map Effect::phonemeMap = {Effect::PHONEME_V, AL_VOCAL_MORPHER_PHONEME_V}, {Effect::PHONEME_Z, AL_VOCAL_MORPHER_PHONEME_Z} }; +*/ } //openal } //audio diff --git a/src/modules/audio/openal/Effect.h b/src/modules/audio/openal/Effect.h index 52147f225..0512acc7a 100644 --- a/src/modules/audio/openal/Effect.h +++ b/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 ¶ms); - virtual const std::vector &getParams() const; + virtual bool setParams(const std::map ¶ms); + virtual const std::map &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 params; - static std::map phonemeMap; + std::map params; + //static std::map phonemeMap; }; } //openal diff --git a/src/modules/audio/wrap_Audio.cpp b/src/modules/audio/wrap_Audio.cpp index 92423c9bf..ec4e10516 100644 --- a/src/modules/audio/wrap_Audio.cpp +++ b/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 ¶ms) -{ - 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(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(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(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 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) + + 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 params; + params[Effect::EFFECT_TYPE] = static_cast(type); + + // Iterate over the whole table, reading valid parameters and erroring on invalid ones + lua_pushnil(L); + while (lua_next(L, 2)) { - typestr = luaL_checkstring(L, 2); - if (!Effect::getConstant(typestr, type)) - return luaL_error(L, "Invalid effect type: %s", typestr); + const char *keystr = luaL_checkstring(L, -2); + Effect::Parameter param; - params.push_back(luaL_checknumber(L, 3)); - const std::vector ¶mtypes = 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)) - { - if (lua_objlen(L, 2) == 0) //empty table also clears effect + 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(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(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(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 ¶mtypes = 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 params; + std::map 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((int)params[Effect::EFFECT_TYPE]); - const std::vector ¶mtypes = 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((int)params[i]), str); - lua_pushstring(L, str); - break; - case Effect::PAR_DIRECTION: - Effect::getConstant(static_cast((int)params[i]), str); - lua_pushstring(L, str); - break; - case Effect::PAR_PHONEME: - Effect::getConstant(static_cast((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((int)p.second), valstr); + lua_pushstring(L, valstr); + break; +/* + case Effect::PARAM_DIRECTION: + Effect::getConstant(static_cast((int)p.second), valstr); + lua_pushstring(L, valstr); + break; + case Effect::PARAM_PHONEME: + Effect::getConstant(static_cast((int)p.second), valstr); + lua_pushstring(L, valstr); + break; +*/ + case Effect::PARAM_TYPE: + Effect::getConstant(static_cast((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)