/* * Wobble Juice Plugin * Copyright (C) 2014 Andre Sklenar , www.juicelab.cz * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * For a full copy of the GNU General Public License see the doc/GPL.txt file. */ #include "WobbleJuicePlugin.hpp" START_NAMESPACE_DISTRHO // ----------------------------------------------------------------------- WobbleJuicePlugin::WobbleJuicePlugin() : Plugin(paramCount, 1, 0) // 1 program, 0 states { // set default values loadProgram(0); } // ----------------------------------------------------------------------- // Init void WobbleJuicePlugin::initParameter(uint32_t index, Parameter& parameter) { switch (index) { case paramDivision: parameter.hints = kParameterIsAutomable|kParameterIsInteger; parameter.name = "Division"; parameter.symbol = "div"; parameter.unit = "x"; parameter.ranges.def = 4.0f; parameter.ranges.min = 1.0f; parameter.ranges.max = 16.0f; break; case paramReso: parameter.hints = kParameterIsAutomable; parameter.name = "Resonance"; parameter.symbol = "reso"; parameter.unit = ""; parameter.ranges.def = 0.1f; parameter.ranges.min = 0.0f; parameter.ranges.max = 0.2f; break; case paramRange: parameter.hints = kParameterIsAutomable; parameter.name = "Range"; parameter.symbol = "rng"; parameter.unit = "Hz"; parameter.ranges.def = 16000.0f; parameter.ranges.min = 500.0f; parameter.ranges.max = 16000.0f; break; case paramPhase: parameter.hints = kParameterIsAutomable; parameter.name = "Phase"; parameter.symbol = "phs"; parameter.unit = "Deg"; parameter.ranges.def = 0.0f; parameter.ranges.min = -1.0f; parameter.ranges.max = 1.0f; break; case paramWave: parameter.hints = kParameterIsAutomable; parameter.name = "Wave"; parameter.symbol = "wav"; parameter.unit = ""; parameter.ranges.def = 2.0f; parameter.ranges.min = 1.0f; parameter.ranges.max = 4.0f; break; case paramDrive: parameter.hints = kParameterIsAutomable; parameter.name = "Drive"; parameter.symbol = "drv"; parameter.unit = ""; parameter.ranges.def = 0.5f; parameter.ranges.min = 0.0f; parameter.ranges.max = 1.0f; break; } } void WobbleJuicePlugin::initProgramName(uint32_t index, String& programName) { if (index != 0) return; programName = "Default"; } // ----------------------------------------------------------------------- // Internal data float WobbleJuicePlugin::getParameterValue(uint32_t index) const { switch (index) { case paramDivision: return division; case paramReso: return reso; case paramRange: return range; case paramPhase: return phase; case paramWave: return wave; case paramDrive: return drive; default: return 0.0f; } } void WobbleJuicePlugin::setParameterValue(uint32_t index, float value) { switch (index) { case paramDivision: division = value; break; case paramReso: reso = value; break; case paramRange: range = value; break; case paramPhase: phase = value; break; case paramWave: wave = value; break; case paramDrive: drive = value; break; } } void WobbleJuicePlugin::loadProgram(uint32_t index) { if (index != 0) return; /* Default parameter values */ division = 4.0f; reso = 0.1f; range = 16000.0f; phase = 0.0f; wave = 2.0f; drive = 0.5f; /* Default variable values */ bar=tick=tickOffset=percentage=phaseOffset=currentPhaseL=0.0f; currentPhaseR=posL=posR=cutoffL=cutoffR=0.0f; waveType=2.0f; /* reset filter values */ activate(); } // ----------------------------------------------------------------------- // Process void WobbleJuicePlugin::activate() { sinePos = 0.0; } void WobbleJuicePlugin::run(const float** inputs, float** outputs, uint32_t frames) { //fetch the timepos struct from host; const TimePosition& time(getTimePosition()); /* sample count for one bar */ bar = ((120.0/(time.bbt.valid ? time.bbt.beatsPerMinute : 120.0))*(getSampleRate())); //ONE, two, three, four tick = bar/(std::round(division)); //size of one target wob phaseOffset = phase*M_PI; //2pi = 1 whole cycle /* if rolling then sync to timepos */ if (time.playing) { tickOffset = time.frame-std::floor(time.frame/tick)*tick; //how much after last tick if (tickOffset!=0) { //TODO: why do we need this?? percentage = tickOffset/tick; } else { percentage = 0; } sinePos = (M_PI*2)*percentage; if (sinePos>2*M_PI) { //TODO: can this ever happen?? sinePos = 0; } } /* else just keep on wobblin' */ else { sinePos += (M_PI)/(tick/2000); //wtf, but works if (sinePos>2*M_PI) { sinePos = 0; } } /* phase of 0..1 filter = 500..16k */ currentPhaseL = getBlendedPhase(sinePos+phaseOffset, wave); currentPhaseR = getBlendedPhase(sinePos-phaseOffset, wave); /* logarithmic */ cutoffL = std::exp((std::log(range)-std::log(500))*currentPhaseL+std::log(500)); cutoffR = std::exp((std::log(range)-std::log(500))*currentPhaseR+std::log(500)); //output filtered signal filterL.recalc(cutoffL, reso*4, getSampleRate(), drive); filterR.recalc(cutoffR, reso*4, getSampleRate(), drive); filterL.process(frames, inputs[0], outputs[0]); filterR.process(frames, inputs[1], outputs[1]); } // ----------------------------------------------------------------------- Plugin* createPlugin() { return new WobbleJuicePlugin(); } // ----------------------------------------------------------------------- END_NAMESPACE_DISTRHO