diff --git a/MicroDexed.ino b/MicroDexed.ino index f714d8a..3979a61 100644 --- a/MicroDexed.ino +++ b/MicroDexed.ino @@ -34,7 +34,7 @@ #include #include "dexed.h" #include "dexed_sysex.h" - +#include "PluginFx.h" #ifdef I2C_DISPLAY // selecting sounds by encoder, button and display #include "UI.h" #include @@ -240,6 +240,11 @@ void setup() mixer2.gain(1, mapfloat(effect_delay_volume, 0, ENC_DELAY_VOLUME_STEPS, 0.0, 1.0)); // delayed signal (including feedback) mixer2.gain(2, mapfloat(effect_delay_volume, 0, ENC_DELAY_VOLUME_STEPS, 0.0, 1.0)); // only delayed signal (without feedback) + // just for testing: + dexed->fx.uiReso=0.5; + dexed->fx.uiGain=0.5; + dexed->fx.uiCutoff=0.5; + // load default SYSEX data load_sysex(configuration.bank, configuration.voice); } @@ -327,15 +332,17 @@ void loop() // MIDI input handling check_midi_devices(); - // Shutdown unused voices + // CONTROL-RATE-EVENT-HANDLING if (control_rate > CONTROL_RATE_MS) { control_rate = 0; + + // Shutdown unused voices active_voices = dexed->getNumNotesPlaying(); } #ifdef I2C_DISPLAY - // UI + // UI-HANDLING if (master_timer >= TIMER_UI_HANDLING_MS) { master_timer -= TIMER_UI_HANDLING_MS; diff --git a/PluginFx.cpp b/PluginFx.cpp new file mode 100644 index 0000000..c474565 --- /dev/null +++ b/PluginFx.cpp @@ -0,0 +1,216 @@ +/** + * + * Copyright (c) 2013-2014 Pascal Gauthier. + * Copyright (c) 2013-2014 Filatov Vadim. + * + * Filter taken from the Obxd project : + * https://github.com/2DaT/Obxd + * + * 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 3 of the License, or + * (at your option) 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#define _USE_MATH_DEFINES +#include +#include "PluginFx.h" + +const float dc = 1e-18; + +inline static float tptpc(float& state,float inp,float cutoff) { + double v = (inp - state) * cutoff / (1 + cutoff); + double res = v + state; + state = res + v; + return res; +} + +inline static float tptlpupw(float & state , float inp , float cutoff , float srInv) { + cutoff = (cutoff * srInv)*M_PI; + double v = (inp - state) * cutoff / (1 + cutoff); + double res = v + state; + state = res + v; + return res; +} + +//static float linsc(float param,const float min,const float max) { +// return (param) * (max - min) + min; +//} + +static float logsc(float param, const float min,const float max,const float rolloff = 19.0f) { + return ((expf(param * logf(rolloff+1)) - 1.0f) / (rolloff)) * (max-min) + min; +} + +PluginFx::PluginFx() { + uiCutoff = 1; + uiReso = 0; + uiGain = 1; +} + +void PluginFx::init(int sr) { + mm=0; + s1=s2=s3=s4=c=d=0; + R24=0; + + mmch = (int)(mm * 3); + mmt = mm*3-mmch; + + sampleRate = sr; + sampleRateInv = 1/sampleRate; + float rcrate =sqrt((44000/sampleRate)); + rcor24 = (970.0 / 44000)*rcrate; + rcor24Inv = 1 / rcor24; + + bright = tan((sampleRate*0.5f-10) * M_PI * sampleRateInv); + + R = 1; + rcor = (480.0 / 44000)*rcrate; + rcorInv = 1 / rcor; + bandPassSw = false; + + pCutoff = -1; + pReso = -1; + + dc_r = 1.0-(126.0/sr); + dc_id = 0; + dc_od = 0; +} + +inline float PluginFx::NR24(float sample,float g,float lpc) { + float ml = 1 / (1+g); + float S = (lpc*(lpc*(lpc*s1 + s2) + s3) +s4)*ml; + float G = lpc*lpc*lpc*lpc; + float y = (sample - R24 * S) / (1 + R24*G); + return y + 1e-8; +}; + +inline float PluginFx::NR(float sample, float g) { + float y = ((sample- R * s1*2 - g*s1 - s2)/(1+ g*(2*R + g))) + dc; + return y; +} + +void PluginFx::process(float *work, int sampleSize) { + // very basic DC filter + float t_fd = work[0]; + work[0] = work[0] - dc_id + dc_r * dc_od; + dc_id = t_fd; + for (int i=1; i #include #ifdef USE_TEENSY_DSP @@ -51,6 +52,7 @@ Dexed::Dexed(int rate) Lfo::init(rate); PitchEnv::init(rate); Env::init_sr(rate); + fx.init(rate); engineMkI = new EngineMkI; engineOpl = new EngineOpl; @@ -188,6 +190,15 @@ void Dexed::getSamples(uint16_t n_samples, int16_t* buffer) } #endif } + + float fbuffer[n_samples]; + for (i = 0; i < n_samples; ++i) { + fbuffer[i] = static_cast(buffer[i] / 0x8000); + } + fx.process(fbuffer, n_samples); + for (i = 0; i < n_samples; ++i) { + buffer[i] = static_cast(fbuffer[i] * 0x8000); + } } void Dexed::keydown(uint8_t pitch, uint8_t velo) { diff --git a/dexed.h b/dexed.h index de22102..6188f1e 100644 --- a/dexed.h +++ b/dexed.h @@ -34,6 +34,7 @@ #include "fm_core.h" #include "EngineMkI.h" #include "EngineOpl.h" +#include "PluginFx.h" #include #include "config.h" @@ -164,6 +165,7 @@ class Dexed ProcessorVoice voices[MAX_NOTES]; Controllers controllers; + PluginFx fx; uint8_t data[173] = { 95, 29, 20, 50, 99, 95, 00, 00, 41, 00, 19, 00, 00, 03, 00, 06, 79, 00, 01, 00, 14, // OP6 eg_rate_1-4, level_1-4, kbd_lev_scl_brk_pt, kbd_lev_scl_lft_depth, kbd_lev_scl_rht_depth, kbd_lev_scl_lft_curve, kbd_lev_scl_rht_curve, kbd_rate_scaling, amp_mod_sensitivity, key_vel_sensitivity, operator_output_level, osc_mode, osc_freq_coarse, osc_freq_fine, osc_detune