/* * Copyright (c) 2019 Christian Schoenebeck * * http://www.linuxsampler.org * * This file is part of LinuxSampler and released under the same terms. * See README file for details. */ #include "LFO.h" #include "common/LFOAll.h" #include // for std::is_same namespace LinuxSampler { enum lfo_class_t { lfo_class_sine_signed, lfo_class_sine_unsigned, lfo_class_triangle_signed, lfo_class_triangle_unsigned, lfo_class_saw_signed, lfo_class_saw_unsigned, lfo_class_square_signed, lfo_class_square_unsigned, }; struct LFOPriv { LFOPOD* lfo = NULL; lfo_class_t lfoClass = (lfo_class_t) -1; // some invalid value virtual ~LFOPriv() { if (lfo) delete lfo; } }; LFO::LFO() { SELF = new LFOPriv; } LFO::~LFO() { if (SELF) delete SELF; } template static T* createLFO(LFOPriv* SELF, const LFO::SetupOpt& opt) { if (SELF->lfo) { delete SELF->lfo; SELF->lfo = NULL; } const bool flipPolarity = (opt.flipPolarity) ? *opt.flipPolarity : false; const float maxValue = (opt.maxValue) ? *opt.maxValue : 1.0; const float frequency = (opt.frequency) ? *opt.frequency : 1.0; const LFO::start_level_t startLevel = (opt.startLevel) ? *opt.startLevel : LFO::start_level_mid; const uint16_t internalDepth = (opt.internalDepth) ? *opt.internalDepth : 0; const uint16_t midiCtrlDepth = (opt.midiControllerDepth) ? *opt.midiControllerDepth : 0; const float samplerate = (opt.samplerate) ? *opt.samplerate : 44100; T* lfo = new T(maxValue); SELF->lfo = lfo; lfo->trigger(frequency, startLevel, internalDepth, midiCtrlDepth, flipPolarity, samplerate); if (opt.phase) lfo->setPhase( *opt.phase ); lfo->updateByMIDICtrlValue(0); if (std::is_same::value) SELF->lfoClass = lfo_class_sine_signed; else if (std::is_same::value) SELF->lfoClass = lfo_class_sine_unsigned; else if (std::is_same::value) SELF->lfoClass = lfo_class_triangle_signed; else if (std::is_same::value) SELF->lfoClass = lfo_class_triangle_unsigned; else if (std::is_same::value) SELF->lfoClass = lfo_class_saw_signed; else if (std::is_same::value) SELF->lfoClass = lfo_class_saw_unsigned; else if (std::is_same::value) SELF->lfoClass = lfo_class_square_signed; else if (std::is_same::value) SELF->lfoClass = lfo_class_square_unsigned; else assert(false); return lfo; } void LFO::setup(const SetupOpt& opt) { const wave_t wave = (opt.waveType) ? *opt.waveType : wave_sine; const bool isSigned = (opt.rangeType) ? (*opt.rangeType == range_signed) : false; switch (wave) { case wave_sine: if (isSigned) createLFO(SELF, opt); else createLFO(SELF, opt); break; case wave_triangle: if (isSigned) createLFO(SELF, opt); else createLFO(SELF, opt); break; case wave_saw: if (isSigned) createLFO(SELF, opt); else createLFO(SELF, opt); break; case wave_square: if (isSigned) createLFO(SELF, opt); else createLFO(SELF, opt); break; default: assert(false); } } template inline float renderLFO(LFOPriv* SELF) { return static_cast(SELF->lfo)->render(); } float LFO::render() { switch (SELF->lfoClass) { case lfo_class_sine_signed: return renderLFO(SELF); case lfo_class_sine_unsigned: return renderLFO(SELF); case lfo_class_triangle_signed: return renderLFO(SELF); case lfo_class_triangle_unsigned: return renderLFO(SELF); case lfo_class_saw_signed: return renderLFO(SELF); case lfo_class_saw_unsigned: return renderLFO(SELF); case lfo_class_square_signed: return renderLFO(SELF); case lfo_class_square_unsigned: return renderLFO(SELF); } return 0; } template inline void setLFOMidiCtrlValue(LFOPriv* SELF, uint16_t value) { return static_cast(SELF->lfo)->updateByMIDICtrlValue(value); } void LFO::setMIDICtrlValue(uint8_t midiCCValue) { switch (SELF->lfoClass) { case lfo_class_sine_signed: return setLFOMidiCtrlValue(SELF, midiCCValue); case lfo_class_sine_unsigned: return setLFOMidiCtrlValue(SELF, midiCCValue); case lfo_class_triangle_signed: return setLFOMidiCtrlValue(SELF, midiCCValue); case lfo_class_triangle_unsigned: return setLFOMidiCtrlValue(SELF, midiCCValue); case lfo_class_saw_signed: return setLFOMidiCtrlValue(SELF, midiCCValue); case lfo_class_saw_unsigned: return setLFOMidiCtrlValue(SELF, midiCCValue); case lfo_class_square_signed: return setLFOMidiCtrlValue(SELF, midiCCValue); case lfo_class_square_unsigned: return setLFOMidiCtrlValue(SELF, midiCCValue); } } } // namespace LinuxSampler