1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
|
// ------------------------------------------------------------------------
// audiofx_rcfilter.cpp: Simulation of an 3rd-order 36dB active RC-lowpass
// Copyright (C) 2000 Stefan Fendt, Kai Vehmanen (C++ version)
// Copyright (C) 2012 Kai Vehmanen
//
// 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
// (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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// ------------------------------------------------------------------------
#include <cmath>
#include <kvu_utils.h>
#include "samplebuffer_iterators.h"
#include "eca-logger.h"
#include "audiofx_rcfilter.h"
EFFECT_RC_LOWPASS_FILTER::EFFECT_RC_LOWPASS_FILTER (CHAIN_OPERATOR::parameter_t cutoff,
CHAIN_OPERATOR::parameter_t resonance) {
set_parameter(1, cutoff);
set_parameter(2, resonance);
}
void EFFECT_RC_LOWPASS_FILTER::set_parameter(int param, CHAIN_OPERATOR::parameter_t value) {
switch (param) {
case 1:
cutoff_rep = value;
break;
case 2:
resonance_rep = value;
break;
}
}
CHAIN_OPERATOR::parameter_t EFFECT_RC_LOWPASS_FILTER::get_parameter(int param) const {
switch (param) {
case 1:
return(cutoff_rep);
case 2:
return(resonance_rep);
}
return(0.0);
}
static void priv_resize_buffer(std::vector<SAMPLE_SPECS::sample_t> *buffer, int count, SAMPLE_SPECS::sample_t value)
{
buffer->resize(count);
for(int i = 0; i < count; i++)
(*buffer)[i] = value;
}
void EFFECT_RC_LOWPASS_FILTER::init(SAMPLE_BUFFER *insample) {
i.init(insample);
priv_resize_buffer(&lp1_old, insample->number_of_channels(), 0.0015);
priv_resize_buffer(&lp2_old, insample->number_of_channels(), -0.00067);
priv_resize_buffer(&lp3_old, insample->number_of_channels(), 0.0);
priv_resize_buffer(&hp1_old, insample->number_of_channels(), 0.0);
priv_resize_buffer(&feedback, insample->number_of_channels(), 0.0);
}
void EFFECT_RC_LOWPASS_FILTER::process(void) {
i.begin();
while(!i.end()) {
output_temp = *i.current();
output_temp += (feedback[i.channel()] * resonance_rep);
// --
// The two lines above prevent the filter from clipping if it is
// self-oscillating. This is necessary for a good simulation because
// real analouge RC-filters can't clip when oscillating, too. Clipping
// used to simulate saturation of an amp (as many TB-303-emulators do)
// is dissatisfying ! We should use an Amp-simulation instead to avoid
// digital clipping ...
if (output_temp > SAMPLE_SPECS::impl_max_value)
output_temp = SAMPLE_SPECS::impl_max_value;
else if (output_temp < SAMPLE_SPECS::impl_min_value)
output_temp = SAMPLE_SPECS::impl_min_value;
// --
// Ok, this is the first step of the filter. We simulate an simple
// non-active RC-lowpass ...
lp1_old[i.channel()] = output_temp * cutoff_rep + lp1_old[i.channel()] * (1.0 - cutoff_rep);
lp2_old[i.channel()] = lp1_old[i.channel()] * cutoff_rep + lp2_old[i.channel()] * (1.0 - cutoff_rep);
lp3_old[i.channel()] = lp2_old[i.channel()] * cutoff_rep + lp3_old[i.channel()] * (1.0 - cutoff_rep);
// --
// A simple non-active highpass
hp1_old[i.channel()] = output_temp - lp3_old[i.channel()];
// --
// Now we add a feedback of this bandpass-filtered signal to the
// input of the filter again. (Look some lines above for that!)
feedback[i.channel()] = hp1_old[i.channel()];
// --
// We catch the out-value of the filter after the second lp-filter
// this provides 24-db filtering even with moderate resonance.
*i.current() = lp3_old[i.channel()];
i.next();
}
}
|