From 32e228d1ca60d479025f5c10479ac866208e11ae Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Wed, 27 Aug 2008 22:27:30 +0000 Subject: merged in relevant changes from the v0-40 pd-extended release branch svn path=/trunk/externals/creb/; revision=10266 --- modules++/biquadseries.cc | 128 -------- modules++/biquadseries~.cc | 128 ++++++++ modules++/blosc.cc | 782 --------------------------------------------- modules++/blosc~.cc | 773 ++++++++++++++++++++++++++++++++++++++++++++ modules++/filterortho.cc | 133 -------- modules++/filterortho~.cc | 133 ++++++++ 6 files changed, 1034 insertions(+), 1043 deletions(-) delete mode 100644 modules++/biquadseries.cc create mode 100644 modules++/biquadseries~.cc delete mode 100644 modules++/blosc.cc create mode 100644 modules++/blosc~.cc delete mode 100644 modules++/filterortho.cc create mode 100644 modules++/filterortho~.cc (limited to 'modules++') diff --git a/modules++/biquadseries.cc b/modules++/biquadseries.cc deleted file mode 100644 index 40b3aef..0000000 --- a/modules++/biquadseries.cc +++ /dev/null @@ -1,128 +0,0 @@ -/* - * biquadseries.cc - second order section filter pd interface - * Copyright (c) 2000-2003 by Tom Schouten - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - - -#include "m_pd.h" -#include - -#include "DSPIcomplex.h" -#include "DSPIfilters.h" - - - -typedef struct biquadseries_struct -{ - t_object x_obj; - t_float x_f; - DSPIfilterSeries* biquadseries; -} t_biquadseries; - -void biquadseries_bang(t_biquadseries *x) -{ - -} - -void biquadseries_butterLP(t_biquadseries *x, t_floatarg f) -{ - x->biquadseries->setButterLP(f / sys_getsr()); -} - -void biquadseries_butterHP(t_biquadseries *x, t_floatarg f) -{ - x->biquadseries->setButterHP(f / sys_getsr()); -} - - - -static t_int *biquadseries_perform(t_int *w) -{ - - - t_float *in = (float *)(w[3]); - t_float *out = (float *)(w[4]); - DSPIfilterSeries* biquadseries = (DSPIfilterSeries *)(w[1]); - t_int n = (t_int)(w[2]); - t_int i; - t_float x; - - // dit kan beter - float smooth = .01; - //1.0f - pow(.9f,1.0f/(float)(n)); - - for (i = 0; i < n; i++) - { - x = *in++; - biquadseries->BangSmooth(x, x, smooth); - *out++ = x; - } - - return (w+5); -} - -static void biquadseries_dsp(t_biquadseries *x, t_signal **sp) -{ - dsp_add(biquadseries_perform, 4, x->biquadseries, sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec); - -} -void biquadseries_free(void) -{ - -} - -t_class *biquadseries_class; - -void *biquadseries_new(t_floatarg fsections) -{ - t_biquadseries *x = (t_biquadseries *)pd_new(biquadseries_class); - - int sections = (int)fsections; - if (sections < 1) sections = 1; - // post("biquadseries~: %d sections", sections); - x->biquadseries = new DSPIfilterSeries(sections); - - // inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("freq")); - outlet_new(&x->x_obj, gensym("signal")); - - biquadseries_butterLP(x, 10000); - - return (void *)x; -} - - -extern "C" { - -void biquadseries_tilde_setup(void) -{ - //post("biquadseries~ v0.1"); - - biquadseries_class = class_new(gensym("biquadseries~"), (t_newmethod)biquadseries_new, - (t_method)biquadseries_free, sizeof(t_biquadseries), 0, A_DEFFLOAT, 0); - - CLASS_MAINSIGNALIN(biquadseries_class, t_biquadseries, x_f); - - class_addmethod(biquadseries_class, (t_method)biquadseries_bang, gensym("bang"), (t_atomtype)0); - - class_addmethod(biquadseries_class, (t_method)biquadseries_dsp, gensym("dsp"), (t_atomtype)0); - - class_addmethod(biquadseries_class, (t_method)biquadseries_butterLP, gensym("butterLP"), A_FLOAT, A_NULL); - class_addmethod(biquadseries_class, (t_method)biquadseries_butterHP, gensym("butterHP"), A_FLOAT, A_NULL); - -} - -} diff --git a/modules++/biquadseries~.cc b/modules++/biquadseries~.cc new file mode 100644 index 0000000..40b3aef --- /dev/null +++ b/modules++/biquadseries~.cc @@ -0,0 +1,128 @@ +/* + * biquadseries.cc - second order section filter pd interface + * Copyright (c) 2000-2003 by Tom Schouten + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +#include "m_pd.h" +#include + +#include "DSPIcomplex.h" +#include "DSPIfilters.h" + + + +typedef struct biquadseries_struct +{ + t_object x_obj; + t_float x_f; + DSPIfilterSeries* biquadseries; +} t_biquadseries; + +void biquadseries_bang(t_biquadseries *x) +{ + +} + +void biquadseries_butterLP(t_biquadseries *x, t_floatarg f) +{ + x->biquadseries->setButterLP(f / sys_getsr()); +} + +void biquadseries_butterHP(t_biquadseries *x, t_floatarg f) +{ + x->biquadseries->setButterHP(f / sys_getsr()); +} + + + +static t_int *biquadseries_perform(t_int *w) +{ + + + t_float *in = (float *)(w[3]); + t_float *out = (float *)(w[4]); + DSPIfilterSeries* biquadseries = (DSPIfilterSeries *)(w[1]); + t_int n = (t_int)(w[2]); + t_int i; + t_float x; + + // dit kan beter + float smooth = .01; + //1.0f - pow(.9f,1.0f/(float)(n)); + + for (i = 0; i < n; i++) + { + x = *in++; + biquadseries->BangSmooth(x, x, smooth); + *out++ = x; + } + + return (w+5); +} + +static void biquadseries_dsp(t_biquadseries *x, t_signal **sp) +{ + dsp_add(biquadseries_perform, 4, x->biquadseries, sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec); + +} +void biquadseries_free(void) +{ + +} + +t_class *biquadseries_class; + +void *biquadseries_new(t_floatarg fsections) +{ + t_biquadseries *x = (t_biquadseries *)pd_new(biquadseries_class); + + int sections = (int)fsections; + if (sections < 1) sections = 1; + // post("biquadseries~: %d sections", sections); + x->biquadseries = new DSPIfilterSeries(sections); + + // inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("freq")); + outlet_new(&x->x_obj, gensym("signal")); + + biquadseries_butterLP(x, 10000); + + return (void *)x; +} + + +extern "C" { + +void biquadseries_tilde_setup(void) +{ + //post("biquadseries~ v0.1"); + + biquadseries_class = class_new(gensym("biquadseries~"), (t_newmethod)biquadseries_new, + (t_method)biquadseries_free, sizeof(t_biquadseries), 0, A_DEFFLOAT, 0); + + CLASS_MAINSIGNALIN(biquadseries_class, t_biquadseries, x_f); + + class_addmethod(biquadseries_class, (t_method)biquadseries_bang, gensym("bang"), (t_atomtype)0); + + class_addmethod(biquadseries_class, (t_method)biquadseries_dsp, gensym("dsp"), (t_atomtype)0); + + class_addmethod(biquadseries_class, (t_method)biquadseries_butterLP, gensym("butterLP"), A_FLOAT, A_NULL); + class_addmethod(biquadseries_class, (t_method)biquadseries_butterHP, gensym("butterHP"), A_FLOAT, A_NULL); + +} + +} diff --git a/modules++/blosc.cc b/modules++/blosc.cc deleted file mode 100644 index f2b13d8..0000000 --- a/modules++/blosc.cc +++ /dev/null @@ -1,782 +0,0 @@ -/* - * blosc.c - bandlimited oscillators - * using minimum phase impulse, step & ramp - * Copyright (c) 2000-2003 by Tom Schouten - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - - -#include "m_pd.h" -#include -#include -#include -#include - - -#include "DSPIcomplex.h" -#include "DSPIfilters.h" - -/* work around old bug in Apple compilers */ -//#if MAC_OS_X_VERSION < MAC_OS_X_VERSION_10_4 // arg, this didn't work -#ifndef isnan -extern "C" int isnan(double); -#endif -#ifndef isinf -extern "C" int isinf(double); -#endif - -typedef unsigned long long u64; -typedef unsigned long u32; - - - -#define LPHASOR (8*sizeof(u32)) // the phasor logsize -#define VOICES 8 // the number of waveform voices -#define LLENGTH 6 // the loglength of a fractional delayed basic waveform -#define LOVERSAMPLE 6 // the log of the oversampling factor (nb of fract delayed waveforms) -#define LPAD 1 // the log of the time padding factor (to reduce time aliasing) -#define LTABLE (LLENGTH+LOVERSAMPLE) -#define N (1< 1 = rect) -#define CUTOFF 0.8f // fraction of nyquist for impulse cutoff -#define NBPERIODS ((float)(L) * CUTOFF / 2.0f) - -/* sample buffers */ -static float bli[N]; // band limited impulse -static float bls[N]; // band limited step -static float blr[N]; // band limited ramp - - -typedef struct bloscctl -{ - t_int c_index[VOICES]; // array of indices in sample table - t_float c_frac[VOICES]; // array of fractional indices - t_float c_vscale[VOICES]; // array of scale factors - t_int c_next_voice; // next voice to steal (round robin) - u32 c_phase; // phase of main oscillator - u32 c_phase2; // phase of secondairy oscillator - t_float c_state; // state of the square wave - t_float c_prev_amp; // previous input of comparator - t_float c_phase_inc_scale; - t_float c_scale; - t_float c_scale_update; - DSPIfilterSeries* c_butter; // the series filter - t_symbol *c_waveform; - -} t_bloscctl; - -typedef struct blosc -{ - t_object x_obj; - t_float x_f; - t_bloscctl x_ctl; -} t_blosc; - - -/* phase converters */ -static inline float _phase_to_float(u32 p){return ((float)p) * (1.0f / 4294967296.0f);} -static inline u32 _float_to_phase(float f){return ((u32)(f * 4294967296.0f)) & ~(S-1);} - - -/* flat table: better for linear interpolation */ -static inline float _play_voice_lint(float *table, t_int *index, float frac, float scale) -{ - t_int i = *index; - - /* perform linear interpolation */ - float f = (((1.0f - frac) * table[i]) + (table[i+1] * frac)) * scale; - - /* increment phase index if next 2 elements will still be inside table - if not there's no increment and the voice will keep playing the same sample */ - - i += (((i+S+1) >> LTABLE) ^ 1) << LOVERSAMPLE; - - *index = i; - return f; -} - -/* get one sample from the bandlimited discontinuity wavetable playback syth */ -static inline t_float _get_bandlimited_discontinuity(t_bloscctl *ctl, float *table) -{ - float sum = 0.0f; - int i; - /* sum all voices */ - for (i=0; ic_index+i, ctl->c_frac[i], ctl->c_vscale[i]); - } - - return sum; -} - - -/* update waveplayers on zero cross */ -static void _bang_comparator(t_bloscctl *ctl, float prev, float curr) -{ - - /* check for sign change */ - if ((prev * curr) < 0.0f){ - - int voice; - - /* determine the location of the discontinuity (in oversampled coordiates - using linear interpolation */ - - float f = (float)S * curr / (curr - prev); - - /* get the offset in the oversample table */ - - u32 table_index = (u32)f; - - /* determine the fractional part (in oversampled coordinates) - for linear interpolation */ - - float table_frac_index = f - (float)table_index; - - /* set state (+ or -) */ - - ctl->c_state = (curr > 0.0f) ? 0.5f : -0.5f; - - /* steal the oldest voice */ - - voice = ctl->c_next_voice++; - ctl->c_next_voice &= VOICES-1; - - /* initialize the new voice index and interpolation fraction */ - - ctl->c_index[voice] = table_index; - ctl->c_frac[voice] = table_frac_index; - ctl->c_vscale[voice] = -ctl->c_scale * 2.0f * ctl->c_state; - - } - -} - - -/* advance phasor and update waveplayers on phase wrap */ -static void _bang_phasor(t_bloscctl *ctl, float freq) -{ - u32 phase = ctl->c_phase; - u32 phase_inc; - u32 oldphase; - int voice; - float scale = ctl->c_scale; - - /* get increment */ - float inc = freq * ctl->c_phase_inc_scale; - - /* calculate new phase - the increment (and the phase) should be a multiple of S */ - if (inc < 0.0f) inc = -inc; - phase_inc = ((u32)inc) & ~(S-1); - oldphase = phase; - phase += phase_inc; - - - /* check for phase wrap */ - if (phase < oldphase){ - u32 phase_inc_decimated = phase_inc >> LOVERSAMPLE; - u32 table_index; - u32 table_phase; - - /* steal the oldest voice if we have a phase wrap */ - - voice = ctl->c_next_voice++; - ctl->c_next_voice &= VOICES-1; - - /* determine the location of the discontinuity (in oversampled coordinates) - which is S * (new phase) / (increment) */ - - table_index = phase / phase_inc_decimated; - - /* determine the fractional part (in oversampled coordinates) - for linear interpolation */ - - table_phase = phase - (table_index * phase_inc_decimated); - - /* use it to initialize the new voice index and interpolation fraction */ - - ctl->c_index[voice] = table_index; - ctl->c_frac[voice] = (float)table_phase / (float)phase_inc_decimated; - ctl->c_vscale[voice] = scale; - scale = scale * ctl->c_scale_update; - - } - - /* save state */ - ctl->c_phase = phase; - ctl->c_scale = scale; -} - - -/* the 2 oscillator version: - the second osc can reset the first osc's phase (hence it determines the pitch) - the first osc determines the waveform */ - -static void _bang_hardsync_phasor(t_bloscctl *ctl, float freq, float freq2) -{ - u32 phase = ctl->c_phase; - u32 phase2 = ctl->c_phase2; - u32 phase_inc; - u32 phase_inc2; - u32 oldphase; - u32 oldphase2; - int voice; - float scale = ctl->c_scale; - - - /* get increment */ - float inc = freq * ctl->c_phase_inc_scale; - float inc2 = freq2 * ctl->c_phase_inc_scale; - - /* calculate new phases - the increment (and the phase) should be a multiple of S */ - - /* save previous phases */ - oldphase = phase; - oldphase2 = phase2; - - /* update second osc */ - if (inc2 < 0.0f) inc2 = -inc2; - phase_inc2 = ((u32)inc2) & ~(S-1); - phase2 += phase_inc2; - - /* update first osc (freq should be >= freq of sync osc */ - if (inc < 0.0f) inc = -inc; - phase_inc = ((u32)inc) & ~(S-1); - if (phase_inc < phase_inc2) phase_inc = phase_inc2; - phase += phase_inc; - - - /* check for sync discontinuity (osc 2) */ - if (phase2 < oldphase2) { - - /* adjust phase depending on the location of the discontinuity in phase2: - phase/phase_inc == phase2/phase_inc2 */ - - u64 pi = phase_inc >> LOVERSAMPLE; - u64 pi2 = phase_inc2 >> LOVERSAMPLE; - u64 lphase = ((u64)phase2 * pi) / pi2; - phase = lphase & ~(S-1); - } - - - /* check for phase discontinuity (osc 1) */ - if (phase < oldphase){ - u32 phase_inc_decimated = phase_inc >> LOVERSAMPLE; - u32 table_index; - u32 table_phase; - float stepsize; - - /* steal the oldest voice if we have a phase wrap */ - - voice = ctl->c_next_voice++; - ctl->c_next_voice &= VOICES-1; - - /* determine the location of the discontinuity (in oversampled coordinates) - which is S * (new phase) / (increment) */ - - table_index = phase / phase_inc_decimated; - - /* determine the fractional part (in oversampled coordinates) - for linear interpolation */ - - table_phase = phase - (table_index * phase_inc_decimated); - - /* determine the step size - as opposed to saw/impulse waveforms, the step is not always equal to one. it is: - oldphase - phase + phase_inc - but for the unit step this will overflow to zero, so we - reduce the bit depth to prevent overflow */ - - stepsize = _phase_to_float(((oldphase-phase) >> LOVERSAMPLE) - + phase_inc_decimated) * (float)S; - - /* use it to initialize the new voice index and interpolation fraction */ - - ctl->c_index[voice] = table_index; - ctl->c_frac[voice] = (float)table_phase / (float)phase_inc_decimated; - ctl->c_vscale[voice] = scale * stepsize; - scale = scale * ctl->c_scale_update; - - } - - /* save state */ - ctl->c_phase = phase; - ctl->c_phase2 = phase2; - ctl->c_scale = scale; -} - - -static t_int *blosc_perform_hardsync_saw(t_int *w) -{ - t_float *freq = (float *)(w[3]); - t_float *freq2 = (float *)(w[4]); - t_float *out = (float *)(w[5]); - t_bloscctl *ctl = (t_bloscctl *)(w[1]); - t_int n = (t_int)(w[2]); - t_int i; - - /* set postfilter cutoff */ - ctl->c_butter->setButterHP(0.85f * (*freq / sys_getsr())); - - while (n--) { - float frequency = *freq++; - float frequency2 = *freq2++; - - /* get the bandlimited discontinuity */ - float sample = _get_bandlimited_discontinuity(ctl, bls); - - /* add aliased sawtooth wave */ - sample += _phase_to_float(ctl->c_phase) - 0.5f; - - /* highpass filter output to remove DC offset and low frequency aliasing */ - ctl->c_butter->BangSmooth(sample, sample, 0.05f); - - /* send to output */ - *out++ = sample; - - /* advance phasor */ - _bang_hardsync_phasor(ctl, frequency2, frequency); - - } - - return (w+6); -} - -static t_int *blosc_perform_saw(t_int *w) -{ - t_float *freq = (float *)(w[3]); - t_float *out = (float *)(w[4]); - t_bloscctl *ctl = (t_bloscctl *)(w[1]); - t_int n = (t_int)(w[2]); - t_int i; - - while (n--) { - float frequency = *freq++; - - /* get the bandlimited discontinuity */ - float sample = _get_bandlimited_discontinuity(ctl, bls); - - /* add aliased sawtooth wave */ - sample += _phase_to_float(ctl->c_phase) - 0.5f; - - /* send to output */ - *out++ = sample; - - /* advance phasor */ - _bang_phasor(ctl, frequency); - - } - - return (w+5); -} - - - -static t_int *blosc_perform_pulse(t_int *w) -{ - t_float *freq = (float *)(w[3]); - t_float *out = (float *)(w[4]); - t_bloscctl *ctl = (t_bloscctl *)(w[1]); - t_int n = (t_int)(w[2]); - t_int i; - - - /* set postfilter cutoff */ - ctl->c_butter->setButterHP(0.85f * (*freq / sys_getsr())); - - while (n--) { - float frequency = *freq++; - - /* get the bandlimited discontinuity */ - float sample = _get_bandlimited_discontinuity(ctl, bli); - - /* highpass filter output to remove DC offset and low frequency aliasing */ - ctl->c_butter->BangSmooth(sample, sample, 0.05f); - - /* send to output */ - *out++ = sample; - - /* advance phasor */ - _bang_phasor(ctl, frequency); - - } - - return (w+5); -} - -static t_int *blosc_perform_comparator(t_int *w) -{ - t_float *amp = (float *)(w[3]); - t_float *out = (float *)(w[4]); - t_bloscctl *ctl = (t_bloscctl *)(w[1]); - t_int n = (t_int)(w[2]); - t_int i; - t_float prev_amp = ctl->c_prev_amp; - - while (n--) { - float curr_amp = *amp++; - - /* exact zero won't work for zero detection (sic) */ - if (curr_amp == 0.0f) curr_amp = 0.0000001f; - - /* get the bandlimited discontinuity */ - float sample = _get_bandlimited_discontinuity(ctl, bls); - - /* add the block wave state */ - sample += ctl->c_state; - - /* send to output */ - *out++ = sample; - - /* advance phasor */ - _bang_comparator(ctl, prev_amp, curr_amp); - - prev_amp = curr_amp; - - } - - ctl->c_prev_amp = prev_amp; - - return (w+5); -} - -static void blosc_phase(t_blosc *x, t_float f) -{ - x->x_ctl.c_phase = _float_to_phase(f); - x->x_ctl.c_phase2 = _float_to_phase(f); -} - -static void blosc_phase1(t_blosc *x, t_float f) -{ - x->x_ctl.c_phase = _float_to_phase(f); -} - -static void blosc_phase2(t_blosc *x, t_float f) -{ - x->x_ctl.c_phase2 = _float_to_phase(f); -} - -static void blosc_dsp(t_blosc *x, t_signal **sp) -{ - int n = sp[0]->s_n; - - /* set sampling rate scaling for phasors */ - x->x_ctl.c_phase_inc_scale = 4.0f * (float)(1<<(LPHASOR-2)) / sys_getsr(); - - - /* setup & register the correct process routine depending on the waveform */ - - /* 2 osc */ - if (x->x_ctl.c_waveform == gensym("syncsaw")){ - x->x_ctl.c_scale = 1.0f; - x->x_ctl.c_scale_update = 1.0f; - dsp_add(blosc_perform_hardsync_saw, 5, &x->x_ctl, sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec); - } - - /* 1 osc */ - else if (x->x_ctl.c_waveform == gensym("pulse")){ - x->x_ctl.c_scale = 1.0f; - x->x_ctl.c_scale_update = 1.0f; - dsp_add(blosc_perform_pulse, 4, &x->x_ctl, sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec); - } - else if (x->x_ctl.c_waveform == gensym("pulse2")){ - x->x_ctl.c_phase_inc_scale *= 2; - x->x_ctl.c_scale = 1.0f; - x->x_ctl.c_scale_update = -1.0f; - dsp_add(blosc_perform_pulse, 4, &x->x_ctl, sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec); - } - else if (x->x_ctl.c_waveform == gensym("comparator")){ - x->x_ctl.c_scale = 1.0f; - x->x_ctl.c_scale_update = 1.0f; - dsp_add(blosc_perform_comparator, 4, &x->x_ctl, sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec); - } - else{ - x->x_ctl.c_scale = 1.0f; - x->x_ctl.c_scale_update = 1.0f; - dsp_add(blosc_perform_saw, 4, &x->x_ctl, sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec); - } - - - -} -static void blosc_free(t_blosc *x) -{ - delete x->x_ctl.c_butter; -} - -t_class *blosc_class; - -static void *blosc_new(t_symbol *s) -{ - t_blosc *x = (t_blosc *)pd_new(blosc_class); - int i; - - /* out 1 */ - outlet_new(&x->x_obj, gensym("signal")); - - /* optional signal inlets */ - if (s == gensym("syncsaw")){ - inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("signal"), gensym("signal")); - } - - /* optional phase inlet */ - if (s != gensym("comparator")){ - inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("phase")); - } - - /* create the postfilter */ - x->x_ctl.c_butter = new DSPIfilterSeries(3); - - /* init oscillators */ - for (i=0; ix_ctl.c_index[i] = N-2; - x->x_ctl.c_frac[i] = 0.0f; - } - - /* init rest of state data */ - blosc_phase(x, 0); - blosc_phase2(x, 0); - x->x_ctl.c_state = 0.0; - x->x_ctl.c_prev_amp = 0.0; - x->x_ctl.c_next_voice = 0; - x->x_ctl.c_scale = 1.0f; - x->x_ctl.c_scale_update = 1.0f; - x->x_ctl.c_waveform = s; - - return (void *)x; -} - - - - - - - -/* CLASS DATA INIT (tables) */ - - -/* some vector ops */ - -/* clear a buffer */ -static inline void _clear(float *array, int size) -{ - memset(array, 0, sizeof(float)*size); -} - -/* compute complex log */ -static inline void _clog(float *real, float *imag, int size) -{ - int k; - for (k=0; k pi, -pi -> 0] */ -static inline float _i2theta(int i, int size){ - float p = 2.0f * M_PI * (float)i / (float)size; - if (p >= M_PI) p -= 2.0f * M_PI; - return p; -} - - -/* print matlab array */ -static void _printm(float *array, char *name, int size) -{ - int i; - fprintf(stderr, "%s = [", name); - for (i=0; i=N (time padding to reduce time aliasing) */ - - /* we work in the complex domain to eliminate the need to avoid - negative spectral components */ - - float real[M]; - float imag[M]; - float sum,scale; - int i,j; - - - /* create windowed sinc */ - _clear(imag, M); - real[0] = 1.0f; - for (i=1; iM-1] - and work with the first N samples */ - - /* normalize impulse (integral = 1) */ - sum = 0.0f; - for (i=0; i0 */ - sum = 0.0f; - for (i=0; i +#include +#include +#include + + +#include "DSPIcomplex.h" +#include "DSPIfilters.h" + +typedef unsigned long long u64; +typedef unsigned long u32; + + + +#define LPHASOR (8*sizeof(u32)) // the phasor logsize +#define VOICES 8 // the number of waveform voices +#define LLENGTH 6 // the loglength of a fractional delayed basic waveform +#define LOVERSAMPLE 6 // the log of the oversampling factor (nb of fract delayed waveforms) +#define LPAD 1 // the log of the time padding factor (to reduce time aliasing) +#define LTABLE (LLENGTH+LOVERSAMPLE) +#define N (1< 1 = rect) +#define CUTOFF 0.8f // fraction of nyquist for impulse cutoff +#define NBPERIODS ((float)(L) * CUTOFF / 2.0f) + +/* sample buffers */ +static float bli[N]; // band limited impulse +static float bls[N]; // band limited step +static float blr[N]; // band limited ramp + + +typedef struct bloscctl +{ + t_int c_index[VOICES]; // array of indices in sample table + t_float c_frac[VOICES]; // array of fractional indices + t_float c_vscale[VOICES]; // array of scale factors + t_int c_next_voice; // next voice to steal (round robin) + u32 c_phase; // phase of main oscillator + u32 c_phase2; // phase of secondairy oscillator + t_float c_state; // state of the square wave + t_float c_prev_amp; // previous input of comparator + t_float c_phase_inc_scale; + t_float c_scale; + t_float c_scale_update; + DSPIfilterSeries* c_butter; // the series filter + t_symbol *c_waveform; + +} t_bloscctl; + +typedef struct blosc +{ + t_object x_obj; + t_float x_f; + t_bloscctl x_ctl; +} t_blosc; + + +/* phase converters */ +static inline float _phase_to_float(u32 p){return ((float)p) * (1.0f / 4294967296.0f);} +static inline u32 _float_to_phase(float f){return ((u32)(f * 4294967296.0f)) & ~(S-1);} + + +/* flat table: better for linear interpolation */ +static inline float _play_voice_lint(float *table, t_int *index, float frac, float scale) +{ + int i = *index; + + /* perform linear interpolation */ + float f = (((1.0f - frac) * table[i]) + (table[i+1] * frac)) * scale; + + /* increment phase index if next 2 elements will still be inside table + if not there's no increment and the voice will keep playing the same sample */ + + i += (((i+S+1) >> LTABLE) ^ 1) << LOVERSAMPLE; + + *index = i; + return f; +} + +/* get one sample from the bandlimited discontinuity wavetable playback syth */ +static inline t_float _get_bandlimited_discontinuity(t_bloscctl *ctl, float *table) +{ + float sum = 0.0f; + int i; + /* sum all voices */ + for (i=0; ic_index+i, ctl->c_frac[i], ctl->c_vscale[i]); + } + + return sum; +} + + +/* update waveplayers on zero cross */ +static void _bang_comparator(t_bloscctl *ctl, float prev, float curr) +{ + + /* check for sign change */ + if ((prev * curr) < 0.0f){ + + int voice; + + /* determine the location of the discontinuity (in oversampled coordiates + using linear interpolation */ + + float f = (float)S * curr / (curr - prev); + + /* get the offset in the oversample table */ + + u32 table_index = (u32)f; + + /* determine the fractional part (in oversampled coordinates) + for linear interpolation */ + + float table_frac_index = f - (float)table_index; + + /* set state (+ or -) */ + + ctl->c_state = (curr > 0.0f) ? 0.5f : -0.5f; + + /* steal the oldest voice */ + + voice = ctl->c_next_voice++; + ctl->c_next_voice &= VOICES-1; + + /* initialize the new voice index and interpolation fraction */ + + ctl->c_index[voice] = table_index; + ctl->c_frac[voice] = table_frac_index; + ctl->c_vscale[voice] = -ctl->c_scale * 2.0f * ctl->c_state; + + } + +} + + +/* advance phasor and update waveplayers on phase wrap */ +static void _bang_phasor(t_bloscctl *ctl, float freq) +{ + u32 phase = ctl->c_phase; + u32 phase_inc; + u32 oldphase; + int voice; + float scale = ctl->c_scale; + + /* get increment */ + float inc = freq * ctl->c_phase_inc_scale; + + /* calculate new phase + the increment (and the phase) should be a multiple of S */ + if (inc < 0.0f) inc = -inc; + phase_inc = ((u32)inc) & ~(S-1); + oldphase = phase; + phase += phase_inc; + + + /* check for phase wrap */ + if (phase < oldphase){ + u32 phase_inc_decimated = phase_inc >> LOVERSAMPLE; + u32 table_index; + u32 table_phase; + + /* steal the oldest voice if we have a phase wrap */ + + voice = ctl->c_next_voice++; + ctl->c_next_voice &= VOICES-1; + + /* determine the location of the discontinuity (in oversampled coordinates) + which is S * (new phase) / (increment) */ + + table_index = phase / phase_inc_decimated; + + /* determine the fractional part (in oversampled coordinates) + for linear interpolation */ + + table_phase = phase - (table_index * phase_inc_decimated); + + /* use it to initialize the new voice index and interpolation fraction */ + + ctl->c_index[voice] = table_index; + ctl->c_frac[voice] = (float)table_phase / (float)phase_inc_decimated; + ctl->c_vscale[voice] = scale; + scale = scale * ctl->c_scale_update; + + } + + /* save state */ + ctl->c_phase = phase; + ctl->c_scale = scale; +} + + +/* the 2 oscillator version: + the second osc can reset the first osc's phase (hence it determines the pitch) + the first osc determines the waveform */ + +static void _bang_hardsync_phasor(t_bloscctl *ctl, float freq, float freq2) +{ + u32 phase = ctl->c_phase; + u32 phase2 = ctl->c_phase2; + u32 phase_inc; + u32 phase_inc2; + u32 oldphase; + u32 oldphase2; + int voice; + float scale = ctl->c_scale; + + + /* get increment */ + float inc = freq * ctl->c_phase_inc_scale; + float inc2 = freq2 * ctl->c_phase_inc_scale; + + /* calculate new phases + the increment (and the phase) should be a multiple of S */ + + /* save previous phases */ + oldphase = phase; + oldphase2 = phase2; + + /* update second osc */ + if (inc2 < 0.0f) inc2 = -inc2; + phase_inc2 = ((u32)inc2) & ~(S-1); + phase2 += phase_inc2; + + /* update first osc (freq should be >= freq of sync osc */ + if (inc < 0.0f) inc = -inc; + phase_inc = ((u32)inc) & ~(S-1); + if (phase_inc < phase_inc2) phase_inc = phase_inc2; + phase += phase_inc; + + + /* check for sync discontinuity (osc 2) */ + if (phase2 < oldphase2) { + + /* adjust phase depending on the location of the discontinuity in phase2: + phase/phase_inc == phase2/phase_inc2 */ + + u64 pi = phase_inc >> LOVERSAMPLE; + u64 pi2 = phase_inc2 >> LOVERSAMPLE; + u64 lphase = ((u64)phase2 * pi) / pi2; + phase = lphase & ~(S-1); + } + + + /* check for phase discontinuity (osc 1) */ + if (phase < oldphase){ + u32 phase_inc_decimated = phase_inc >> LOVERSAMPLE; + u32 table_index; + u32 table_phase; + float stepsize; + + /* steal the oldest voice if we have a phase wrap */ + + voice = ctl->c_next_voice++; + ctl->c_next_voice &= VOICES-1; + + /* determine the location of the discontinuity (in oversampled coordinates) + which is S * (new phase) / (increment) */ + + table_index = phase / phase_inc_decimated; + + /* determine the fractional part (in oversampled coordinates) + for linear interpolation */ + + table_phase = phase - (table_index * phase_inc_decimated); + + /* determine the step size + as opposed to saw/impulse waveforms, the step is not always equal to one. it is: + oldphase - phase + phase_inc + but for the unit step this will overflow to zero, so we + reduce the bit depth to prevent overflow */ + + stepsize = _phase_to_float(((oldphase-phase) >> LOVERSAMPLE) + + phase_inc_decimated) * (float)S; + + /* use it to initialize the new voice index and interpolation fraction */ + + ctl->c_index[voice] = table_index; + ctl->c_frac[voice] = (float)table_phase / (float)phase_inc_decimated; + ctl->c_vscale[voice] = scale * stepsize; + scale = scale * ctl->c_scale_update; + + } + + /* save state */ + ctl->c_phase = phase; + ctl->c_phase2 = phase2; + ctl->c_scale = scale; +} + + +static t_int *blosc_perform_hardsync_saw(t_int *w) +{ + t_float *freq = (float *)(w[3]); + t_float *freq2 = (float *)(w[4]); + t_float *out = (float *)(w[5]); + t_bloscctl *ctl = (t_bloscctl *)(w[1]); + t_int n = (t_int)(w[2]); + t_int i; + + /* set postfilter cutoff */ + ctl->c_butter->setButterHP(0.85f * (*freq / sys_getsr())); + + while (n--) { + float frequency = *freq++; + float frequency2 = *freq2++; + + /* get the bandlimited discontinuity */ + float sample = _get_bandlimited_discontinuity(ctl, bls); + + /* add aliased sawtooth wave */ + sample += _phase_to_float(ctl->c_phase) - 0.5f; + + /* highpass filter output to remove DC offset and low frequency aliasing */ + ctl->c_butter->BangSmooth(sample, sample, 0.05f); + + /* send to output */ + *out++ = sample; + + /* advance phasor */ + _bang_hardsync_phasor(ctl, frequency2, frequency); + + } + + return (w+6); +} + +static t_int *blosc_perform_saw(t_int *w) +{ + t_float *freq = (float *)(w[3]); + t_float *out = (float *)(w[4]); + t_bloscctl *ctl = (t_bloscctl *)(w[1]); + t_int n = (t_int)(w[2]); + t_int i; + + while (n--) { + float frequency = *freq++; + + /* get the bandlimited discontinuity */ + float sample = _get_bandlimited_discontinuity(ctl, bls); + + /* add aliased sawtooth wave */ + sample += _phase_to_float(ctl->c_phase) - 0.5f; + + /* send to output */ + *out++ = sample; + + /* advance phasor */ + _bang_phasor(ctl, frequency); + + } + + return (w+5); +} + + + +static t_int *blosc_perform_pulse(t_int *w) +{ + t_float *freq = (float *)(w[3]); + t_float *out = (float *)(w[4]); + t_bloscctl *ctl = (t_bloscctl *)(w[1]); + t_int n = (t_int)(w[2]); + t_int i; + + + /* set postfilter cutoff */ + ctl->c_butter->setButterHP(0.85f * (*freq / sys_getsr())); + + while (n--) { + float frequency = *freq++; + + /* get the bandlimited discontinuity */ + float sample = _get_bandlimited_discontinuity(ctl, bli); + + /* highpass filter output to remove DC offset and low frequency aliasing */ + ctl->c_butter->BangSmooth(sample, sample, 0.05f); + + /* send to output */ + *out++ = sample; + + /* advance phasor */ + _bang_phasor(ctl, frequency); + + } + + return (w+5); +} + +static t_int *blosc_perform_comparator(t_int *w) +{ + t_float *amp = (float *)(w[3]); + t_float *out = (float *)(w[4]); + t_bloscctl *ctl = (t_bloscctl *)(w[1]); + t_int n = (t_int)(w[2]); + t_int i; + t_float prev_amp = ctl->c_prev_amp; + + while (n--) { + float curr_amp = *amp++; + + /* exact zero won't work for zero detection (sic) */ + if (curr_amp == 0.0f) curr_amp = 0.0000001f; + + /* get the bandlimited discontinuity */ + float sample = _get_bandlimited_discontinuity(ctl, bls); + + /* add the block wave state */ + sample += ctl->c_state; + + /* send to output */ + *out++ = sample; + + /* advance phasor */ + _bang_comparator(ctl, prev_amp, curr_amp); + + prev_amp = curr_amp; + + } + + ctl->c_prev_amp = prev_amp; + + return (w+5); +} + +static void blosc_phase(t_blosc *x, t_float f) +{ + x->x_ctl.c_phase = _float_to_phase(f); + x->x_ctl.c_phase2 = _float_to_phase(f); +} + +static void blosc_phase1(t_blosc *x, t_float f) +{ + x->x_ctl.c_phase = _float_to_phase(f); +} + +static void blosc_phase2(t_blosc *x, t_float f) +{ + x->x_ctl.c_phase2 = _float_to_phase(f); +} + +static void blosc_dsp(t_blosc *x, t_signal **sp) +{ + int n = sp[0]->s_n; + + /* set sampling rate scaling for phasors */ + x->x_ctl.c_phase_inc_scale = 4.0f * (float)(1<<(LPHASOR-2)) / sys_getsr(); + + + /* setup & register the correct process routine depending on the waveform */ + + /* 2 osc */ + if (x->x_ctl.c_waveform == gensym("syncsaw")){ + x->x_ctl.c_scale = 1.0f; + x->x_ctl.c_scale_update = 1.0f; + dsp_add(blosc_perform_hardsync_saw, 5, &x->x_ctl, sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec); + } + + /* 1 osc */ + else if (x->x_ctl.c_waveform == gensym("pulse")){ + x->x_ctl.c_scale = 1.0f; + x->x_ctl.c_scale_update = 1.0f; + dsp_add(blosc_perform_pulse, 4, &x->x_ctl, sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec); + } + else if (x->x_ctl.c_waveform == gensym("pulse2")){ + x->x_ctl.c_phase_inc_scale *= 2; + x->x_ctl.c_scale = 1.0f; + x->x_ctl.c_scale_update = -1.0f; + dsp_add(blosc_perform_pulse, 4, &x->x_ctl, sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec); + } + else if (x->x_ctl.c_waveform == gensym("comparator")){ + x->x_ctl.c_scale = 1.0f; + x->x_ctl.c_scale_update = 1.0f; + dsp_add(blosc_perform_comparator, 4, &x->x_ctl, sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec); + } + else{ + x->x_ctl.c_scale = 1.0f; + x->x_ctl.c_scale_update = 1.0f; + dsp_add(blosc_perform_saw, 4, &x->x_ctl, sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec); + } + + + +} +static void blosc_free(t_blosc *x) +{ + delete x->x_ctl.c_butter; +} + +t_class *blosc_class; + +static void *blosc_new(t_symbol *s) +{ + t_blosc *x = (t_blosc *)pd_new(blosc_class); + int i; + + /* out 1 */ + outlet_new(&x->x_obj, gensym("signal")); + + /* optional signal inlets */ + if (s == gensym("syncsaw")){ + inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("signal"), gensym("signal")); + } + + /* optional phase inlet */ + if (s != gensym("comparator")){ + inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("phase")); + } + + /* create the postfilter */ + x->x_ctl.c_butter = new DSPIfilterSeries(3); + + /* init oscillators */ + for (i=0; ix_ctl.c_index[i] = N-2; + x->x_ctl.c_frac[i] = 0.0f; + } + + /* init rest of state data */ + blosc_phase(x, 0); + blosc_phase2(x, 0); + x->x_ctl.c_state = 0.0; + x->x_ctl.c_prev_amp = 0.0; + x->x_ctl.c_next_voice = 0; + x->x_ctl.c_scale = 1.0f; + x->x_ctl.c_scale_update = 1.0f; + x->x_ctl.c_waveform = s; + + return (void *)x; +} + + + + + + + +/* CLASS DATA INIT (tables) */ + + +/* some vector ops */ + +/* clear a buffer */ +static inline void _clear(float *array, int size) +{ + memset(array, 0, sizeof(float)*size); +} + +/* compute complex log */ +static inline void _clog(float *real, float *imag, int size) +{ + int k; + for (k=0; k pi, -pi -> 0] */ +static inline float _i2theta(int i, int size){ + float p = 2.0f * M_PI * (float)i / (float)size; + if (p >= M_PI) p -= 2.0f * M_PI; + return p; +} + + +/* print matlab array */ +static void _printm(float *array, char *name, int size) +{ + int i; + fprintf(stderr, "%s = [", name); + for (i=0; i=N (time padding to reduce time aliasing) */ + + /* we work in the complex domain to eliminate the need to avoid + negative spectral components */ + + float real[M]; + float imag[M]; + float sum,scale; + int i,j; + + + /* create windowed sinc */ + _clear(imag, M); + real[0] = 1.0f; + for (i=1; iM-1] + and work with the first N samples */ + + /* normalize impulse (integral = 1) */ + sum = 0.0f; + for (i=0; i0 */ + sum = 0.0f; + for (i=0; i - -#include "DSPIcomplex.h" -#include "DSPIfilters.h" - - - -typedef struct filterortho_struct -{ - t_object x_obj; - t_float x_f; - DSPIfilterOrtho *filterortho; -} t_filterortho; - -void filterortho_bang(t_filterortho *x) -{ - -} - - -static t_int *filterortho_perform(t_int *w) -{ - - - t_float *in = (float *)(w[3]); - t_float *out = (float *)(w[4]); - DSPIfilterOrtho* filterortho = (DSPIfilterOrtho *)(w[1]); - t_int n = (t_int)(w[2]); - t_int i; - t_float x; - - - // dit kan beter - float smooth = 1.0f - pow(.05f,1.0f/(float)(n)); - - for (i = 0; i < n; i++) - { - x = *in++; - filterortho->BangSmooth(x, x, smooth); - *out++ = x; - } - - filterortho->killDenormals(); - - return (w+5); -} - -static void filterortho_dsp(t_filterortho *x, t_signal **sp) -{ - dsp_add(filterortho_perform, 4, x->filterortho, sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec); - -} -void filterortho_free(t_filterortho *x) -{ - delete x->filterortho; - -} - -t_class *filterortho_class; - - - -void setLP(t_filterortho *x, t_floatarg f, t_floatarg Q) {x->filterortho->setLP(f / sys_getsr(), Q);} -void setHP(t_filterortho *x, t_floatarg f, t_floatarg Q) {x->filterortho->setHP(f / sys_getsr(), Q);} -void setBP(t_filterortho *x, t_floatarg f, t_floatarg Q) {x->filterortho->setBP(f / sys_getsr(), Q);} -void setBR(t_filterortho *x, t_floatarg f, t_floatarg Q) {x->filterortho->setBR(f / sys_getsr(), Q);} -void setAP(t_filterortho *x, t_floatarg f, t_floatarg Q) {x->filterortho->setAP(f / sys_getsr(), Q);} - -void setLS(t_filterortho *x, t_floatarg f, t_floatarg A) {x->filterortho->setLS(f / sys_getsr(), A);} -void setHS(t_filterortho *x, t_floatarg f, t_floatarg A) {x->filterortho->setHS(f / sys_getsr(), A);} - -void setEQ(t_filterortho *x, t_floatarg f, t_floatarg Q, t_floatarg A) {x->filterortho->setEQ(f / sys_getsr(), Q, A);} - - -void *filterortho_new() -{ - t_filterortho *x = (t_filterortho *)pd_new(filterortho_class); - x->filterortho = new DSPIfilterOrtho(); - outlet_new(&x->x_obj, gensym("signal")); - setLP(x, 10000, 2); - return (void *)x; -} - - - -extern "C" { - -void filterortho_tilde_setup(void) -{ - //post("filterortho~ v0.1"); - filterortho_class = class_new(gensym("filterortho~"), (t_newmethod)filterortho_new, - (t_method)filterortho_free, sizeof(t_filterortho), 0, A_NULL); - - CLASS_MAINSIGNALIN(filterortho_class, t_filterortho, x_f); - - - class_addmethod(filterortho_class, (t_method)filterortho_bang, gensym("bang"), A_NULL); - - class_addmethod(filterortho_class, (t_method)filterortho_dsp, gensym("dsp"), A_NULL); - - class_addmethod(filterortho_class, (t_method)setLP, gensym("setLP"), A_FLOAT, A_FLOAT, A_NULL); - class_addmethod(filterortho_class, (t_method)setHP, gensym("setHP"), A_FLOAT, A_FLOAT, A_NULL); - class_addmethod(filterortho_class, (t_method)setBP, gensym("setBP"), A_FLOAT, A_FLOAT, A_NULL); - class_addmethod(filterortho_class, (t_method)setBR, gensym("setBR"), A_FLOAT, A_FLOAT, A_NULL); - class_addmethod(filterortho_class, (t_method)setAP, gensym("setAP"), A_FLOAT, A_FLOAT, A_NULL); - class_addmethod(filterortho_class, (t_method)setLS, gensym("setLS"), A_FLOAT, A_FLOAT, A_NULL); - class_addmethod(filterortho_class, (t_method)setHS, gensym("setHS"), A_FLOAT, A_FLOAT, A_NULL); - class_addmethod(filterortho_class, (t_method)setEQ, gensym("setEQ"), A_FLOAT, A_FLOAT, A_FLOAT, A_NULL); - -} - -} diff --git a/modules++/filterortho~.cc b/modules++/filterortho~.cc new file mode 100644 index 0000000..c80552b --- /dev/null +++ b/modules++/filterortho~.cc @@ -0,0 +1,133 @@ +/* + * filterortho.cc - orthogonal biquad filter pd interface + * Copyright (c) 2000-2003 by Tom Schouten + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +#include "m_pd.h" +#include + +#include "DSPIcomplex.h" +#include "DSPIfilters.h" + + + +typedef struct filterortho_struct +{ + t_object x_obj; + t_float x_f; + DSPIfilterOrtho *filterortho; +} t_filterortho; + +void filterortho_bang(t_filterortho *x) +{ + +} + + +static t_int *filterortho_perform(t_int *w) +{ + + + t_float *in = (float *)(w[3]); + t_float *out = (float *)(w[4]); + DSPIfilterOrtho* filterortho = (DSPIfilterOrtho *)(w[1]); + t_int n = (t_int)(w[2]); + t_int i; + t_float x; + + + // dit kan beter + float smooth = 1.0f - pow(.05f,1.0f/(float)(n)); + + for (i = 0; i < n; i++) + { + x = *in++; + filterortho->BangSmooth(x, x, smooth); + *out++ = x; + } + + filterortho->killDenormals(); + + return (w+5); +} + +static void filterortho_dsp(t_filterortho *x, t_signal **sp) +{ + dsp_add(filterortho_perform, 4, x->filterortho, sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec); + +} +void filterortho_free(t_filterortho *x) +{ + delete x->filterortho; + +} + +t_class *filterortho_class; + + + +void setLP(t_filterortho *x, t_floatarg f, t_floatarg Q) {x->filterortho->setLP(f / sys_getsr(), Q);} +void setHP(t_filterortho *x, t_floatarg f, t_floatarg Q) {x->filterortho->setHP(f / sys_getsr(), Q);} +void setBP(t_filterortho *x, t_floatarg f, t_floatarg Q) {x->filterortho->setBP(f / sys_getsr(), Q);} +void setBR(t_filterortho *x, t_floatarg f, t_floatarg Q) {x->filterortho->setBR(f / sys_getsr(), Q);} +void setAP(t_filterortho *x, t_floatarg f, t_floatarg Q) {x->filterortho->setAP(f / sys_getsr(), Q);} + +void setLS(t_filterortho *x, t_floatarg f, t_floatarg A) {x->filterortho->setLS(f / sys_getsr(), A);} +void setHS(t_filterortho *x, t_floatarg f, t_floatarg A) {x->filterortho->setHS(f / sys_getsr(), A);} + +void setEQ(t_filterortho *x, t_floatarg f, t_floatarg Q, t_floatarg A) {x->filterortho->setEQ(f / sys_getsr(), Q, A);} + + +void *filterortho_new() +{ + t_filterortho *x = (t_filterortho *)pd_new(filterortho_class); + x->filterortho = new DSPIfilterOrtho(); + outlet_new(&x->x_obj, gensym("signal")); + setLP(x, 10000, 2); + return (void *)x; +} + + + +extern "C" { + +void filterortho_tilde_setup(void) +{ + //post("filterortho~ v0.1"); + filterortho_class = class_new(gensym("filterortho~"), (t_newmethod)filterortho_new, + (t_method)filterortho_free, sizeof(t_filterortho), 0, A_NULL); + + CLASS_MAINSIGNALIN(filterortho_class, t_filterortho, x_f); + + + class_addmethod(filterortho_class, (t_method)filterortho_bang, gensym("bang"), A_NULL); + + class_addmethod(filterortho_class, (t_method)filterortho_dsp, gensym("dsp"), A_NULL); + + class_addmethod(filterortho_class, (t_method)setLP, gensym("setLP"), A_FLOAT, A_FLOAT, A_NULL); + class_addmethod(filterortho_class, (t_method)setHP, gensym("setHP"), A_FLOAT, A_FLOAT, A_NULL); + class_addmethod(filterortho_class, (t_method)setBP, gensym("setBP"), A_FLOAT, A_FLOAT, A_NULL); + class_addmethod(filterortho_class, (t_method)setBR, gensym("setBR"), A_FLOAT, A_FLOAT, A_NULL); + class_addmethod(filterortho_class, (t_method)setAP, gensym("setAP"), A_FLOAT, A_FLOAT, A_NULL); + class_addmethod(filterortho_class, (t_method)setLS, gensym("setLS"), A_FLOAT, A_FLOAT, A_NULL); + class_addmethod(filterortho_class, (t_method)setHS, gensym("setHS"), A_FLOAT, A_FLOAT, A_NULL); + class_addmethod(filterortho_class, (t_method)setEQ, gensym("setEQ"), A_FLOAT, A_FLOAT, A_FLOAT, A_NULL); + +} + +} -- cgit v1.2.1