Added Dexed PluginFx code again - just for testing the 4pole filter.

pull/4/head
Holger Wirtz 6 years ago
parent 1b965c0975
commit 1866ed69a1
  1. 13
      MicroDexed.ino
  2. 216
      PluginFx.cpp
  3. 72
      PluginFx.h
  4. 7
      config.h
  5. 11
      dexed.cpp
  6. 2
      dexed.h

@ -34,7 +34,7 @@
#include <limits.h>
#include "dexed.h"
#include "dexed_sysex.h"
#include "PluginFx.h"
#ifdef I2C_DISPLAY // selecting sounds by encoder, button and display
#include "UI.h"
#include <Bounce.h>
@ -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;

@ -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 <math.h>
#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<sampleSize; i++) {
t_fd = work[i];
work[i] = work[i] - dc_id + dc_r * work[i-1];
dc_id = t_fd;
}
dc_od = work[sampleSize-1];
if ( uiGain != 1 ) {
for(int i=0; i < sampleSize; i++ )
work[i] *= uiGain;
}
// don't apply the LPF if the cutoff is to maximum
if ( uiCutoff == 1 )
return;
if ( uiCutoff != pCutoff || uiReso != pReso ) {
rReso = (0.991-logsc(1-uiReso,0,0.991));
R24 = 3.5 * rReso;
float cutoffNorm = logsc(uiCutoff,60,19000);
rCutoff = (float)tan(cutoffNorm * sampleRateInv * M_PI);
pCutoff = uiCutoff;
pReso = uiReso;
R = 1 - rReso;
}
// THIS IS MY FAVORITE 4POLE OBXd filter
// maybe smooth this value
float g = rCutoff;
float lpc = g / (1 + g);
for(int i=0; i < sampleSize; i++ ) {
float s = work[i];
s = s - 0.45*tptlpupw(c,s,15,sampleRateInv);
s = tptpc(d,s,bright);
float y0 = NR24(s,g,lpc);
//first low pass in cascade
double v = (y0 - s1) * lpc;
double res = v + s1;
s1 = res + v;
//damping
s1 =atan(s1*rcor24)*rcor24Inv;
float y1= res;
float y2 = tptpc(s2,y1,g);
float y3 = tptpc(s3,y2,g);
float y4 = tptpc(s4,y3,g);
float mc=0.0;
switch(mmch) {
case 0:
mc = ((1 - mmt) * y4 + (mmt) * y3);
break;
case 1:
mc = ((1 - mmt) * y3 + (mmt) * y2);
break;
case 2:
mc = ((1 - mmt) * y2 + (mmt) * y1);
break;
case 3:
mc = y1;
break;
}
//half volume comp
work[i] = mc * (1 + R24 * 0.45);
}
}
/*
// THIS IS THE 2POLE FILTER
for(int i=0; i < sampleSize; i++ ) {
float s = work[i];
s = s - 0.45*tptlpupw(c,s,15,sampleRateInv);
s = tptpc(d,s,bright);
//float v = ((sample- R * s1*2 - g2*s1 - s2)/(1+ R*g1*2 + g1*g2));
float v = NR(s,g);
float y1 = v*g + s1;
//damping
s1 = atan(s1 * rcor) * rcorInv;
float y2 = y1*g + s2;
s2 = y2 + y1*g;
double mc;
if(!bandPassSw)
mc = (1-mm)*y2 + (mm)*v;
else
{
mc =2 * ( mm < 0.5 ?
((0.5 - mm) * y2 + (mm) * y1):
((1-mm) * y1 + (mm-0.5) * v)
);
}
work[i] = mc;
}
*/

@ -0,0 +1,72 @@
/**
Copyright (c) 2013 Pascal Gauthier.
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
*/
#ifndef PLUGINFX_H_INCLUDED
#define PLUGINFX_H_INCLUDED
class PluginFx {
float s1, s2, s3, s4;
float sampleRate;
float sampleRateInv;
float d, c;
float R24;
float rcor24, rcor24Inv;
float bright;
// 24 db multimode
float mm;
float mmt;
int mmch;
inline float NR24(float sample, float g, float lpc);
// preprocess values taken the UI
float rCutoff;
float rReso;
float rGain;
// thread values; if these are different from the UI,
// it needs to be recalculated.
float pReso;
float pCutoff;
float pGain;
// I am still keeping the 2pole w/multimode filter
inline float NR(float sample, float g);
bool bandPassSw;
float rcor, rcorInv;
int R;
float dc_id;
float dc_od;
float dc_r;
public:
PluginFx();
// this is set directly by the ui / parameter
float uiCutoff;
float uiReso;
float uiGain;
void init(int sampleRate);
void process(float *work, int sampleSize);
};
#endif // PLUGINFX_H_INCLUDED

@ -60,7 +60,6 @@
//* DEXED AND EFECTS SETTINGS
//*************************************************************************************************
#define DEXED_ENGINE DEXED_ENGINE_MODERN // DEXED_ENGINE_MARKI // DEXED_ENGINE_OPL
#define CONTROL_RATE_MS 200
// EFFECTS
#define FILTER_MAX_FREQ 10000
@ -90,6 +89,11 @@
#endif
#define SAMPLE_RATE 44100
//*************************************************************************************************
//* UI AND DATA-STORE SETTINGS
//*************************************************************************************************
#define CONTROL_RATE_MS 200
#define TIMER_UI_HANDLING_MS 100
//*************************************************************************************************
//* DEBUG OUTPUT SETTINGS
@ -121,7 +125,6 @@
#define ENC_DELAY_TIME_STEPS 50
#define ENC_DELAY_FB_STEPS 35
#define ENC_DELAY_VOLUME_STEPS 50
#define TIMER_UI_HANDLING_MS 100
#define NUM_ENCODER 2
#define ENC_L_PIN_A 3
#define ENC_L_PIN_B 2

@ -33,6 +33,7 @@
#include "sin.h"
#include "freqlut.h"
#include "controllers.h"
#include "PluginFx.h"
#include <unistd.h>
#include <limits.h>
#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<float>(buffer[i] / 0x8000);
}
fx.process(fbuffer, n_samples);
for (i = 0; i < n_samples; ++i) {
buffer[i] = static_cast<int16_t>(fbuffer[i] * 0x8000);
}
}
void Dexed::keydown(uint8_t pitch, uint8_t velo) {

@ -34,6 +34,7 @@
#include "fm_core.h"
#include "EngineMkI.h"
#include "EngineOpl.h"
#include "PluginFx.h"
#include <Audio.h>
#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

Loading…
Cancel
Save