From 01314ebc83191b68a8b4b31b7b9efbf531f3b1d9 Mon Sep 17 00:00:00 2001 From: Jamie Bullock Date: Tue, 10 Jan 2006 11:49:01 +0000 Subject: This commit was generated by cvs2svn to compensate for changes in r4382, which included commits to RCS files with non-trunk default branches. svn path=/trunk/externals/postlude/; revision=4383 --- flib/src/bmax~.c | 103 ++++++++++++++++++++++++ flib/src/clean~.c | 87 ++++++++++++++++++++ flib/src/flib.c | 61 ++++++++++++++ flib/src/flib.h | 40 ++++++++++ flib/src/ha~.c | 85 ++++++++++++++++++++ flib/src/hca~.c | 108 +++++++++++++++++++++++++ flib/src/irreg~.c | 70 ++++++++++++++++ flib/src/melf~.c | 218 ++++++++++++++++++++++++++++++++++++++++++++++++++ flib/src/mspec~.c | 89 +++++++++++++++++++++ flib/src/peak~.c | 129 ++++++++++++++++++++++++++++++ flib/src/pp~.c | 70 ++++++++++++++++ flib/src/pspec~.c | 77 ++++++++++++++++++ flib/src/sc~.c | 77 ++++++++++++++++++ flib/src/sfm~.c | 75 +++++++++++++++++ flib/src/ss~.c | 71 +++++++++++++++++ flib/src/trist~.c | 92 +++++++++++++++++++++ flib/src/wdv~.c | 234 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 17 files changed, 1686 insertions(+) create mode 100644 flib/src/bmax~.c create mode 100644 flib/src/clean~.c create mode 100644 flib/src/flib.c create mode 100644 flib/src/flib.h create mode 100644 flib/src/ha~.c create mode 100644 flib/src/hca~.c create mode 100644 flib/src/irreg~.c create mode 100644 flib/src/melf~.c create mode 100644 flib/src/mspec~.c create mode 100644 flib/src/peak~.c create mode 100644 flib/src/pp~.c create mode 100644 flib/src/pspec~.c create mode 100644 flib/src/sc~.c create mode 100644 flib/src/sfm~.c create mode 100644 flib/src/ss~.c create mode 100644 flib/src/trist~.c create mode 100644 flib/src/wdv~.c (limited to 'flib/src') diff --git a/flib/src/bmax~.c b/flib/src/bmax~.c new file mode 100644 index 0000000..e3bb5a1 --- /dev/null +++ b/flib/src/bmax~.c @@ -0,0 +1,103 @@ +/* flib - PD library for feature extraction +Copyright (C) 2005 Jamie Bullock + +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + + + +/* calculates the maximum sample value in each frame*/ + +#include "flib.h" +static t_class *bmax_class; + +typedef struct _bmax { + t_object x_obj; + t_float f,x; + t_int I; /*instances of blockmax to find */ + t_outlet *M_out, *I_out; +} t_bmax; + + +static t_float max(t_float *array, t_int size){ + register t_float t = array[0]; + register t_int i; + for(i = 1; i < size; i++){ + if (t < array[i]) + t = array[i]; + } + return t; +} + +static t_int *bmax_perform(t_int *w) +{ + t_sample *in = (t_sample *)(w[1]); + t_bmax *x = (t_bmax *)(w[2]); + t_int N = (t_int)(w[3]); + t_float blockmax; + t_int maxloc[x->I], i, j; + t_atom argv[x->I]; + + /* argv = getbytes(x->I * sizeof(t_atom)); */ + + blockmax = max(in,N); + + for(i = 0, j = 0; i < N; i++){ + if (in[i] == blockmax && j < x->I) + maxloc[j++] = i; + } + + if (j < x->I) + for(; j < x->I; maxloc[j++] = 0); /* zero out the rest of the array */ + + for(i = 0; i < x->I; i++) + SETFLOAT(argv+i, maxloc[i]); + + outlet_float(x->M_out, blockmax); + outlet_list(x->I_out, &s_list, x->I, argv); + + return (w+5); +} + +static void bmax_dsp(t_bmax *x, t_signal **sp) +{ + dsp_add(bmax_perform, 4, + sp[0]->s_vec, x, sp[0]->s_n); +} + +static void *bmax_new(t_floatarg f) +{ + t_bmax *x = (t_bmax *)pd_new(bmax_class); + if (!f) + x->I = 1; + else + x->I = (t_int)floor(f); + x->M_out = outlet_new(&x->x_obj, &s_float); + x->I_out = outlet_new(&x->x_obj, &s_list); + return (void *)x; +} + + +void bmax_tilde_setup(void) { + bmax_class = class_new(gensym("bmax~"), + (t_newmethod)bmax_new, + 0, sizeof(t_bmax), + CLASS_DEFAULT, A_DEFFLOAT, 0); + + class_addmethod(bmax_class, + (t_method)bmax_dsp, gensym("dsp"), 0); + CLASS_MAINSIGNALIN(bmax_class, t_bmax,f); + class_sethelpsymbol(bmax_class, gensym("help-flib")); +} diff --git a/flib/src/clean~.c b/flib/src/clean~.c new file mode 100644 index 0000000..1261357 --- /dev/null +++ b/flib/src/clean~.c @@ -0,0 +1,87 @@ +/* flib - PD library for feature extraction +Copyright (C) 2005 Jamie Bullock + +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + + + +/* cleans 'nan' 'inf' '-inf' from an audio vector */ + +#include "flib.h" +static t_class *clean_class; + +typedef struct _clean { + t_object x_obj; + t_float f; + t_outlet *out_r; +} t_clean; + +static t_int *clean_perform(t_int *w) +{ + t_sample *in = (t_sample *)(w[1]); + t_sample *out = (t_sample *)(w[2]); + t_int N = (t_int)(w[3]); + t_clean *x = (t_clean *)(w[4]); + + + while(N--){ + if(finite(*in)) + *out++ = *in++; + else + *out++ = 0; + } + return (w+5); +} + +static void clean_dsp(t_clean *x, t_signal **sp) +{ + dsp_add(clean_perform, 4, + sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n, x); +} + +static void clean_float(t_clean *x, t_float f) +{ + x->f = f; + if(!x->f || !finite(x->f)) + outlet_float(x->out_r, 0); + else + outlet_float(x->out_r, x->f); + +} + + + +static void *clean_new(void) +{ + t_clean *x = (t_clean *)pd_new(clean_class); + outlet_new(&x->x_obj, &s_signal); + x->out_r = outlet_new(&x->x_obj, &s_float); + return (void *)x; +} + + +void clean_tilde_setup(void) { + clean_class = class_new(gensym("clean~"), + (t_newmethod)clean_new, + 0, sizeof(t_clean), + CLASS_DEFAULT, 0); + + CLASS_MAINSIGNALIN(clean_class, t_clean,f); + class_addfloat(clean_class, clean_float); + class_addmethod(clean_class, + (t_method)clean_dsp, gensym("dsp"), 0); + class_sethelpsymbol(clean_class, gensym("help-flib")); +} diff --git a/flib/src/flib.c b/flib/src/flib.c new file mode 100644 index 0000000..6bb1015 --- /dev/null +++ b/flib/src/flib.c @@ -0,0 +1,61 @@ +/* flib - PD library for feature extraction +Copyright (C) 2005 Jamie Bullock + +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "flib.h" + +typedef struct flib +{ + t_object t_ob; +} t_flib; + +t_class *flib_class; + +void *flib_new(void) +{ + t_flib *x = (t_flib *)pd_new(flib_class); + return (void *)x; +} + + +void flib_setup(void) +{ + int i; + + char *ext[] = {"sc~\t\tSpectral Centroid", "ss~\t\tSpectral Smoothness", "irreg~\t\tSpectral Irregularity (methods 1 and 2)", "mspec~\t\tMagnitude Spectrum", "peak~\t\tAmplitude and Frequency of Spectral Peaks", "pspec~\t\tPhase Spectrum", "sfm~\t\tSpectral Flatness Measure", "trist~\t\tTristimulus (x,y,z)", "++~\t\tSum of the samples in each block", "bmax~\t\tThe maximum value and location(s) each block", "melf~\t\tGenerate a mel spaced filter for fft", "clean~\t\tRemoves NaN, inf and -inf from a signal vector", "wdv~\t\tCalculate a wavelet dispersion vector (requires creb)", "hca~\t\tHarmonic component analysis"}; + sc_tilde_setup(); + ss_tilde_setup(); + pp_tilde_setup(); + bmax_tilde_setup(); + irreg_tilde_setup(); + mspec_tilde_setup(); + peak_tilde_setup(); + pspec_tilde_setup(); + sfm_tilde_setup(); + trist_tilde_setup(); + melf_tilde_setup(); + clean_tilde_setup(); + wdv_tilde_setup(); + hca_tilde_setup(); + + post("\n\tflib "VERSION" Feature Extraction Library\n\tby Jamie Bullock\n"); + + for(i = 0; i < 14; i++) + post("\t%s",ext[i]); + + flib_class = class_new(gensym("flib"), flib_new, 0, sizeof(t_flib), 0, 0); +} diff --git a/flib/src/flib.h b/flib/src/flib.h new file mode 100644 index 0000000..0cb4b4c --- /dev/null +++ b/flib/src/flib.h @@ -0,0 +1,40 @@ +/* flib - PD library for feature extraction +Copyright (C) 2005 Jamie Bullock + +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "m_pd.h" +#include +#include +#include + +#define VERSION "0.8" + +void sc_tilde_setup(void); +void ss_tilde_setup(void); +void pp_tilde_setup(void); +void bmax_tilde_setup(void); +void irreg_tilde_setup(void); +void mspec_tilde_setup(void); +void peak_tilde_setup(void); +void pspec_tilde_setup(void); +void sfm_tilde_setup(void); +void trist_tilde_setup(void); +void melf_tilde_setup(void); +void clean_tilde_setup(void); +void wdv_tilde_setup(void); +void hca_tilde_setup(void); + diff --git a/flib/src/ha~.c b/flib/src/ha~.c new file mode 100644 index 0000000..39a46d6 --- /dev/null +++ b/flib/src/ha~.c @@ -0,0 +1,85 @@ +/* flib - PD library for feature extraction +Copyright (C) 2005 Jamie Bullock + +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 thcat 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 hcave 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. +*/ + +/* Perform hcarmonic analysis on a signal given the fundamental frequency and the frequency/amplitude spectra */ + +/* Can measure hcarmonicity or ratio of inhcarmonic frequencies to to hcarmonic frequencies, or the relative proportion of some other series such as odd or even hcarmonics */ + + +#include "flib.h" + +static t_class *hca_class; + +typedef struct _hca { + t_object x_obj; + t_float f; + t_int p; +} t_hca; + +static t_int *hca_perform(t_int *w) +{ + t_sample *in1 = (t_sample *)(w[1]); + t_int N = (t_int)(w[2]),n; + t_int p = (t_int)(w[3]); + + + + post("x->p = %.2f", x->p); + + + + return (w+4); +} + +static void hca_dsp(t_hca *x, t_signal **sp) +{ + dsp_add(hca_perform, 3, + sp[0]->s_vec, sp[0]->s_n, x->p); + +} + +static void *hca_new(t_floatarg f) +{ + t_hca *x = (t_hca *)pd_new(hca_class); + if(!f) + x->p = 0; + else + x->p = f; + inlet_new(&x->x_obj, &s_float); + outlet_new(&x->x_obj, &s_float); + return (void *)x; +} + +void hca_float(t_hca *x, t_float f){ + x->p = f; +} + +void hca_tilde_setup(void) { + hca_class = class_new(gensym("hca~"), + (t_newmethod)hca_new, + 0, sizeof(t_hca), + CLASS_DEFAULT, A_DEFFLOAT, 0); + + class_addmethod(hca_class, + (t_method)hca_dsp, gensym("dsp"), 0); + CLASS_MAINSIGNALIN(hca_class, t_hca,f); + + class_addfloat(hca_class, hca_float) + + class_sethelpsymbol(hca_class, gensym("help-flib")); +} diff --git a/flib/src/hca~.c b/flib/src/hca~.c new file mode 100644 index 0000000..2317324 --- /dev/null +++ b/flib/src/hca~.c @@ -0,0 +1,108 @@ +/* flib - PD library for feature extraction +Copyright (C) 2005 Jamie Bullock + +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 thcat 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 hcave 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. +*/ + +/* Perform hcarmonic analysis on a signal given the fundamental frequency and the frequency/amplitude spectra */ + +/* Takes fundamental through right inlet and % allowed deviation from actual harmonic to be considered harmonic as argument. Outputs number of partials, number of harmonics, number of even harmonics */ + +#include "flib.h" + +static t_class *hca_class; + +typedef struct _hca { + t_object x_obj; + t_float f; + t_float fund, deviation; + t_outlet *p_out, *h_out, *e_out; +} t_hca; + +static t_int *hca_perform(t_int *w) +{ + t_sample *in = (t_sample *)(w[1]); + t_int N = (t_int)(w[2]),n; + t_hca *x = (t_hca *)(w[3]); + t_int npartials, nharmonics, neven, harmonic; + t_float partial, harmonicity; + + neven = nharmonics = npartials = 0; + + while(N--){ + if(in[N]){ + npartials++; + partial = in[N] / x->fund; + harmonic = (t_int)rintf(partial); + if(partial <= harmonic + x->deviation && + partial >= harmonic - x->deviation){ + nharmonics++; + if(harmonic / 2.0f == rint(harmonic / 2.0f)) + neven++; + } + } + } + + if(!npartials) + post("hca~: No partials found."); + + + outlet_float(x->p_out, npartials); + outlet_float(x->h_out, nharmonics); + outlet_float(x->e_out, neven); + + return (w+4); +} + +static void hca_dsp(t_hca *x, t_signal **sp) +{ + dsp_add(hca_perform, 3, + sp[0]->s_vec, sp[0]->s_n, x); + +} + +static void *hca_new(t_floatarg f) +{ + t_hca *x = (t_hca *)pd_new(hca_class); + if(!f) + x->deviation = 0; + else + x->deviation = f * .01; + + post("deviation = %.2f", x->deviation); + + if(!x->fund) + x->fund = 0; + + floatinlet_new(&x->x_obj, &x->fund); + x->p_out = outlet_new(&x->x_obj, &s_float); + x->h_out = outlet_new(&x->x_obj, &s_float); + x->e_out = outlet_new(&x->x_obj, &s_float); + return (void *)x; +} + +void hca_tilde_setup(void) { + hca_class = class_new(gensym("hca~"), + (t_newmethod)hca_new, + 0, sizeof(t_hca), + CLASS_DEFAULT, A_DEFFLOAT, 0); + + class_addmethod(hca_class, + (t_method)hca_dsp, gensym("dsp"), 0); + + CLASS_MAINSIGNALIN(hca_class, t_hca,f); + + class_sethelpsymbol(hca_class, gensym("help-flib")); +} diff --git a/flib/src/irreg~.c b/flib/src/irreg~.c new file mode 100644 index 0000000..7616c63 --- /dev/null +++ b/flib/src/irreg~.c @@ -0,0 +1,70 @@ +/* flib - PD library for feature extraction +Copyright (C) 2005 Jamie Bullock + +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + + + +/* calculates the spectral irreg of one frame according to Jensen et al 1999*/ + +#include "flib.h" +static t_class *irreg_class; + +typedef struct _irreg { + t_object x_obj; + t_float f,x; +} t_irreg; + +static t_int *irreg_perform(t_int *w) +{ + t_sample *in = (t_sample *)(w[1]); + t_irreg *x = (t_irreg *)(w[2]); + t_int N = (t_int)(w[3]),M = N >> 1,n; + t_float I = 0, X = 0,Y = 0; + for(n = 1; n < M; n++){ + X += in[n] - in[n+1]; + Y += in[n] * in[n]; + } + I = X / Y; + outlet_float(x->x_obj.ob_outlet, I); + return (w+4); +} + +static void irreg_dsp(t_irreg *x, t_signal **sp) +{ + dsp_add(irreg_perform, 3, + sp[0]->s_vec, x, sp[0]->s_n); +} + +static void *irreg_new(void) +{ + t_irreg *x = (t_irreg *)pd_new(irreg_class); + outlet_new(&x->x_obj, &s_float); + return (void *)x; +} + + +void irreg_tilde_setup(void) { + irreg_class = class_new(gensym("irreg~"), + (t_newmethod)irreg_new, + 0, sizeof(t_irreg), + CLASS_DEFAULT,0); + + class_addmethod(irreg_class, + (t_method)irreg_dsp, gensym("dsp"), 0); + CLASS_MAINSIGNALIN(irreg_class, t_irreg,f); + class_sethelpsymbol(irreg_class, gensym("help-flib")); +} diff --git a/flib/src/melf~.c b/flib/src/melf~.c new file mode 100644 index 0000000..06947dc --- /dev/null +++ b/flib/src/melf~.c @@ -0,0 +1,218 @@ +/* flib - PD library for feature extraction +Copyright (C) 2005 Jamie Bullock + +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + + + +/* calculates a series of freq_bands Mel filters for multiplication by an fft power spectrum */ + +#include "flib.h" +static t_class *melf_class; + +typedef struct _melf { + t_object x_obj; + t_float f; + t_int sr; + t_float nyquist; + t_int freq_bands; + t_int n_filters; + t_int fft_size; + char style; + t_float freq_min; + t_float freq_max; + t_float freq_min_mel; + t_float freq_max_mel; + t_float freq_bw_mel; + t_float norm; + t_float *mel_peak; + t_float *lin_peak; + t_int *fft_peak; + t_float *height_norm; + t_float **fft_tables; /* tables to hold the filters */ + t_outlet *graph_outlet; /*outlet for list of coeffs */ +} t_melf; + +static t_int *melf_perform(t_int *w) +{ + t_sample *in = (t_sample *)(w[1]); + t_melf *x = (t_melf *)(w[3]); + t_int n_filter = x->n_filters; + t_int N = (t_int)(w[2]), n; + t_float out = 0; + t_atom outs[x->n_filters]; + + while(n_filter--){ + t_float *filter = x->fft_tables[n_filter]; + n = N; + while(n--){ + out += in[N - n - 1] * *filter++; + } + SETFLOAT(&outs[n_filter], out); + } + outlet_list(x->graph_outlet, &s_list, x->n_filters, outs); + + return (w+4); +} + +static void melf_dsp(t_melf *x, t_signal **sp) +{ + int n; + dsp_add(melf_perform, 3, + sp[0]->s_vec, sp[0]->s_n, x); +} + +static void *melf_new(t_symbol *s, t_int argc, t_atom *argv) +{ + t_int n,i; + t_float norm_fact, height, inc, val; + t_melf *x = (t_melf *)pd_new(melf_class); + x->n_filters = 0; + + x->sr = (t_int)sys_getsr(); + x->nyquist = x->sr * .5; + + for(i = 0; i < argc; i++, argv++){ + if(argv->a_type == A_FLOAT) + switch(i){ + case 5: x->norm = argv->a_w.w_float; + break; + case 4: x->fft_size = argv->a_w.w_float; + break; + case 3: post("arg 4 should always be 'a' or 'g'"); + break; + case 2: x->freq_max = argv->a_w.w_float; + break; + case 1: x->freq_min = argv->a_w.w_float; + break; + case 0: x->freq_bands = argv->a_w.w_float; + break; + } + else if(argv->a_type == A_SYMBOL){ + x->style = (char)argv->a_w.w_symbol->s_name[0]; + } + } + + if (!x->freq_bands) + x->freq_bands = 60; + + if(!x->freq_min || x->freq_min < 0) + x->freq_min = 0; + + if(!x->freq_max || x->freq_max > x->nyquist) + x->freq_max_mel = x->nyquist; + else + x->freq_max_mel = x->freq_max; + + if(x->style != 'g' && x->style != 'a') + x->style = 'g'; + + if(!x->fft_size || (x->fft_size - 1) & x->fft_size) + x->fft_size = 512; + post("fft size = %d", x->fft_size); + + if(!x->norm || x->norm < 0 || x->norm > 20) + x->norm = 1; + + x->freq_min_mel = 1127 * log10(1 + x->freq_min / 700); + x->freq_bw_mel = (x->freq_max_mel - x->freq_min_mel) / x->freq_bands; + + x->mel_peak = getbytes((x->freq_bands + 2) * sizeof(t_float)); /* +2 for zeros at start and end */ + x->lin_peak = getbytes((x->freq_bands + 2) * sizeof(t_float)); + x->fft_peak = getbytes((x->freq_bands + 2) * sizeof(t_int)); + x->height_norm = getbytes(x->freq_bands * sizeof(t_float)); + + x->mel_peak[0] = x->freq_min_mel; + x->lin_peak[0] = (700 * (exp(x->mel_peak[0]/1127) - 1)); + x->fft_peak[0] = (t_int)rint(x->lin_peak[0]/x->nyquist * (x->fft_size / 2)); + + for (n = 1; n <= x->freq_bands; n++) /*roll out peak locations - mel, linear and linear on fft window scale */ + { + x->mel_peak[n] = x->mel_peak[n - 1] + x->freq_bw_mel; + x->lin_peak[n] = (700 * (exp(x->mel_peak[n]/1127) - 1)); + x->fft_peak[n] = (t_int)rint(x->lin_peak[n]/x->nyquist * (x->fft_size / 2)); + } + + for (n = 0; n <= x->freq_bands && x->lin_peak[n + 1] < x->freq_max_mel; n++) /*roll out normalised gain of each peak*/ + { + if (x->style == 'g'){ + height = 1; + norm_fact = x->norm; + } + else{ + height = 2 / (x->lin_peak[n + 2] - x->lin_peak[n]); + norm_fact = x->norm / (2 / (x->lin_peak[2] - x->lin_peak[0])); + } + x->height_norm[n] = height * norm_fact; + x->n_filters = n; + } + + post("Number of linear mel-spaced filters = %d", x->n_filters); + + x->fft_tables = (float **)getbytes(x->n_filters * sizeof(float *)); + for(n = 0; n < x->n_filters; n++) + x->fft_tables[n] = (float *)getbytes(x->fft_size * sizeof(float)); + + i = 0; + + for(n = 0; n < x->n_filters; n++){ + if(n > 0)/*calculate the rise increment*/ + inc = x->height_norm[n] / (x->fft_peak[n] - x->fft_peak[n - 1]); + else + inc = x->height_norm[n] / x->fft_peak[n]; + val = 0; + for(; i <= x->fft_peak[n]; i++){ /*fill in the 'rise' */ + x->fft_tables[n][i] = val; + val += inc; + } + inc = x->height_norm[n] / (x->fft_peak[n + 1] - x->fft_peak[n]);/*calculate the fall increment */ + val = 0; + for(i = x->fft_peak[n + 1]; i > x->fft_peak[n]; i--){ /*reverse fill the 'fall' */ + x->fft_tables[n][i] = val; + val += inc; + } + } + x->graph_outlet = outlet_new(&x->x_obj, &s_list); + + + return (void *)x; +} + +static void melf_free(t_melf *x){ + int N; + N = x->n_filters; + while(N--) + freebytes(x->fft_tables[N], sizeof(t_float) * x->fft_size); + freebytes(x->fft_tables, sizeof(t_float *) * x->n_filters); + freebytes(x->mel_peak,(x->freq_bands + 2) * sizeof(t_float)); + freebytes(x->lin_peak, (x->freq_bands + 2) * sizeof(t_float)); + freebytes(x->fft_peak, (x->freq_bands + 2) * sizeof(t_int)); + freebytes(x->height_norm, x->freq_bands * sizeof(t_float)); +} + + + +void melf_tilde_setup(void) { + melf_class = class_new(gensym("melf~"), + (t_newmethod)melf_new, + (t_method)melf_free, sizeof(t_melf), + CLASS_DEFAULT, A_GIMME, 0); + + class_addmethod(melf_class, + (t_method)melf_dsp, gensym("dsp"), 0); + CLASS_MAINSIGNALIN(melf_class, t_melf,f); + class_sethelpsymbol(melf_class, gensym("help-mfcc")); +} diff --git a/flib/src/mspec~.c b/flib/src/mspec~.c new file mode 100644 index 0000000..02000cd --- /dev/null +++ b/flib/src/mspec~.c @@ -0,0 +1,89 @@ +/* flib - PD library for feature extraction +Copyright (C) 2005 Jamie Bullock + +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + + + +/* Compute the magnitude spectrum of a signal given the real and imaginary components of an fft. The output maximum is normalised to 1. If an argument of 2 is given, the power spectrum is output */ + +#include "flib.h" +#define SQ(a) (a * a) + +static t_class *mspec_class; + +typedef struct _mspec { + t_object x_obj; + t_float f; + t_int p; +} t_mspec; + +static t_int *mspec_perform(t_int *w) +{ + t_sample *in1 = (t_sample *)(w[1]); + t_sample *in2 = (t_sample *)(w[2]); + t_sample *out = (t_sample *)(w[3]); + t_int N = (t_int)(w[4]),n; + t_int p = (t_int)(w[5]); + if(p == 2){ + for (n = 0; n < N; n++){ + if(in1[n] != 0 && in2[n] != 0) + *out++ = (SQ(in1[n]) + SQ(in2[n])) / N; + else + *out++ = 0; + } + } + else{ + for (n = 0; n < N; n++){ + if(in1[n] != 0 && in2[n] != 0) + *out++ = q8_sqrt(SQ(in1[n]) + SQ(in2[n])) / N; + else + *out++ = 0; + } + } + return (w+6); +} + +static void mspec_dsp(t_mspec *x, t_signal **sp) +{ + dsp_add(mspec_perform, 5, + sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[0]->s_n, x->p); +} + +static void *mspec_new(t_floatarg f) +{ + t_mspec *x = (t_mspec *)pd_new(mspec_class); + if(f == 2) + x->p = 2; + else + x->p = 0; + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal); + outlet_new(&x->x_obj, &s_signal); + return (void *)x; +} + + +void mspec_tilde_setup(void) { + mspec_class = class_new(gensym("mspec~"), + (t_newmethod)mspec_new, + 0, sizeof(t_mspec), + CLASS_DEFAULT, A_DEFFLOAT, 0); + + class_addmethod(mspec_class, + (t_method)mspec_dsp, gensym("dsp"), 0); + CLASS_MAINSIGNALIN(mspec_class, t_mspec,f); + class_sethelpsymbol(mspec_class, gensym("help-flib")); +} diff --git a/flib/src/peak~.c b/flib/src/peak~.c new file mode 100644 index 0000000..fdc1e6a --- /dev/null +++ b/flib/src/peak~.c @@ -0,0 +1,129 @@ +/* flib - PD library for feature extraction +Copyright (C) 2005 Jamie Bullock + +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + + + +/*Outputs amplitude (in dB referenecd to a maximum of 100dB) and frequency of spectral peaks from outlets 1 and 2. A peak is defined as a bin that has a greater magnitude than either of its neighbouring bins. A peak detection threshold is given by the first argument (or right inlet as a float) as a percentage of the frame maximum, i.e. a setting of 100 finds peaks equal to the size of the highest peak, a setting of 0 will output all peaks. Default is 0*/ + +#include "flib.h" +#define SQ(a) (a * a) + +static t_class *peak_class; + +typedef struct _peak { + t_object x_obj; + t_float f, thresh, *buf; + t_int sr,M; +} t_peak; + +static t_float max(t_float *array, t_int size){ + register t_float t = array[0]; + register t_int i; + for(i = 1; i < size; i++){ + if (t < array[i]) + t = array[i]; + } + return t; +} + +static t_int *peak_perform(t_int *w) +{ + t_sample *in1 = (t_sample *)(w[1]); + t_sample *out1 = (t_float *)(w[2]); + t_sample *out2 = (t_float *)(w[3]); + t_int N = (t_int)(w[4]), M = N >> 1,n; + t_float thresh = *(t_float *)(w[5]); + t_peak *x = (t_peak *)(w[6]); + t_float width = (t_float)x->sr / (t_float)N,y,y2,y3,p,t; + + x->M = M; + x->buf = getbytes(M * sizeof(t_float)); + + for(n = 0; n < M; n++){ + if ((t = in1[n] * 100000) >= 1) /* ensure we never take log10(0) */ + x->buf[n] = t; + else + x->buf[n] = 1; + } + + if(thresh < 0 || thresh > 100) + thresh = 0; + else + thresh *= .01 * max(&x->buf[0],M); + + out1[0] = 0; + out2[0] = 0; + + for(n = 1; n < M; n++){ + if(x->buf[n] >= thresh){ + if(x->buf[n] > x->buf[n - 1] && x->buf[n] > x->buf[n + 1]){ + out1[n] = width * (n + (p = .5 * (y = 20 * log10(x->buf[n-1]) - (y3 = 20 * log10(x->buf[n+1]))) / (20 * log10(x->buf[n - 1]) - 2 * (y2 = 20 * log10(x->buf[n])) + 20 * log10(x->buf[n + 1])))); + out2[n] = y2 - .25 * (y - y3) * p; + } + else{ + out1[n] = 0; + out2[n] = 0; + } + } + else{ + out1[n] = 0; + out2[n] = 0; + } + } + + for (;n < N; n++){ + out1[n] = 0; + out2[n] = 0; + } + + return (w+7); + +} + +static void peak_dsp(t_peak *x, t_signal **sp) +{ + dsp_add(peak_perform, 6, sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[0]->s_n,&x->thresh, x); +} + +static void *peak_new(t_symbol *s, t_int argc, t_atom *argv) +{ + t_peak *x = (t_peak *)pd_new(peak_class); + floatinlet_new(&x->x_obj, &x->thresh); + outlet_new(&x->x_obj, &s_signal); + outlet_new(&x->x_obj, &s_signal); + x->sr = (t_int)sys_getsr(); + x->thresh = atom_getfloatarg(0,argc, argv); + + return (void *)x; +} + +static void peak_free(t_peak *x){ + freebytes(x->buf, sizeof(t_float) * x->M); +} + +void peak_tilde_setup(void) { + peak_class = class_new(gensym("peak~"), + (t_newmethod)peak_new, + (t_method)peak_free, sizeof(t_peak), + CLASS_DEFAULT, A_GIMME, 0); + + class_addmethod(peak_class, (t_method)peak_dsp, gensym("dsp"), 0); + CLASS_MAINSIGNALIN(peak_class, t_peak,f); + class_sethelpsymbol(peak_class, gensym("help-flib")); + +} diff --git a/flib/src/pp~.c b/flib/src/pp~.c new file mode 100644 index 0000000..862a51e --- /dev/null +++ b/flib/src/pp~.c @@ -0,0 +1,70 @@ +/* flib - PD library for feature extraction +Copyright (C) 2005 Jamie Bullock + +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + + + +/* calculates the sum of the samples in each frame*/ + +#include "flib.h" +static t_class *pp_class; + +typedef struct _pp { + t_object x_obj; + t_float f,x; +} t_pp; + +static t_int *pp_perform(t_int *w) +{ + t_sample *in = (t_sample *)(w[1]); + t_pp *x = (t_pp *)(w[2]); + t_int N = (t_int)(w[3]); + float sum = 0; + + while(N--) + sum += *in++; + + outlet_float(x->x_obj.ob_outlet, sum); + return (w+4); +} + +static void pp_dsp(t_pp *x, t_signal **sp) +{ + dsp_add(pp_perform, 3, + sp[0]->s_vec, x, sp[0]->s_n); +} + +static void *pp_new(void) +{ + t_pp *x = (t_pp *)pd_new(pp_class); + outlet_new(&x->x_obj, &s_float); + return (void *)x; +} + + +void pp_tilde_setup(void) { + pp_class = class_new(gensym("pp~"), + (t_newmethod)pp_new, + 0, sizeof(t_pp), + CLASS_DEFAULT,0); + + class_addcreator((t_newmethod)pp_new, gensym("++~"), A_DEFFLOAT, 0); + class_addmethod(pp_class, + (t_method)pp_dsp, gensym("dsp"), 0); + CLASS_MAINSIGNALIN(pp_class, t_pp,f); + class_sethelpsymbol(pp_class, gensym("help-flib")); +} diff --git a/flib/src/pspec~.c b/flib/src/pspec~.c new file mode 100644 index 0000000..80512c5 --- /dev/null +++ b/flib/src/pspec~.c @@ -0,0 +1,77 @@ +/* flib - PD library for feature extraction +Copyright (C) 2005 Jamie Bullock + +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + + + +/* Compute the phase (in radians) spectrum of a signal given the real and imaginary components of an fft */ + +#include "flib.h" +#define SQ(a) (a * a) + +static t_class *pspec_class; + +typedef struct _pspec { + t_object x_obj; + t_float f; +} t_pspec; + +static t_int *pspec_perform(t_int *w) +{ + t_sample *in1 = (t_sample *)(w[1]); + t_sample *in2 = (t_sample *)(w[2]); + t_sample *out = (t_sample *)(w[3]); + t_int N = (t_int)(w[4]),n; + t_float piv2 = M_PI * .5; + for (n = 0; n < N; n++){ + if(in1[n] == 0 && in2[n] == 0 || in1[n] == 0) + *out++ = 0; + else if(in2[n] == 0) + *out++ = piv2; + else + *out++ = atanf(in1[n] / in2[n]); + } + return (w+5); +} + +static void pspec_dsp(t_pspec *x, t_signal **sp) +{ + dsp_add(pspec_perform, 4, + sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[0]->s_n); +} + +static void *pspec_new(void) +{ + t_pspec *x = (t_pspec *)pd_new(pspec_class); + + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal); + outlet_new(&x->x_obj, &s_signal); + return (void *)x; +} + + +void pspec_tilde_setup(void) { + pspec_class = class_new(gensym("pspec~"), + (t_newmethod)pspec_new, + 0, sizeof(t_pspec), + CLASS_DEFAULT, 0); + + class_addmethod(pspec_class, + (t_method)pspec_dsp, gensym("dsp"), 0); + CLASS_MAINSIGNALIN(pspec_class, t_pspec,f); + class_sethelpsymbol(pspec_class, gensym("help-flib")); +} diff --git a/flib/src/sc~.c b/flib/src/sc~.c new file mode 100644 index 0000000..47c69f5 --- /dev/null +++ b/flib/src/sc~.c @@ -0,0 +1,77 @@ +/* flib - PD library for feature extraction +Copyright (C) 2005 Jamie Bullock + +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + + + +/* calculates the spectral sc of one frame, given peak frequency and amplitude to first and second inputs respectively */ + +#include "flib.h" + +static t_class *sc_class; + +typedef struct _sc { + t_object x_obj; + t_float f, x; +} t_sc; + +static t_int *sc_perform(t_int *w) +{ + t_sample *in1 = (t_sample *)(w[1]); + t_sample *in2 = (t_sample *)(w[2]); + t_sc *x = (t_sc *)(w[3]); + t_int N = (t_int)(w[4]),M = N >> 1,n; + t_float FA = 0,A = 0,C; + for (n = 0; n < M; n++){ + if (in2[n] != 0){ + FA += in1[n] * in2[n]; + A += in2[n]; + } + } + C = FA / A; + outlet_float(x->x_obj.ob_outlet, C); + return (w+5); +} + +static void sc_dsp(t_sc *x, t_signal **sp) +{ + dsp_add(sc_perform, 4, + sp[0]->s_vec, sp[1]->s_vec, x, sp[0]->s_n); +} + +static void *sc_new(void) +{ + t_sc *x = (t_sc *)pd_new(sc_class); + + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal); + outlet_new(&x->x_obj, &s_float); + return (void *)x; +} + + +void sc_tilde_setup(void) { + sc_class = class_new(gensym("sc~"), + (t_newmethod)sc_new, + 0, sizeof(t_sc), + CLASS_DEFAULT, + A_DEFFLOAT, 0); + + class_addmethod(sc_class, + (t_method)sc_dsp, gensym("dsp"), 0); + CLASS_MAINSIGNALIN(sc_class, t_sc,f); + class_sethelpsymbol(sc_class, gensym("help-flib")); +} diff --git a/flib/src/sfm~.c b/flib/src/sfm~.c new file mode 100644 index 0000000..ee745c2 --- /dev/null +++ b/flib/src/sfm~.c @@ -0,0 +1,75 @@ +/* flib - PD library for feature extraction +Copyright (C) 2005 Jamie Bullock + +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + + + +/* calculates spectral flatness measure as described by Tae Hong Park*/ + +#include "m_pd.h" +#include + +static t_class *sfm_class; + +typedef struct _sfm { + t_object x_obj; + t_float f,x; +} t_sfm; + +static t_int *sfm_perform(t_int *w) +{ + t_sample *in = (t_sample *)(w[1]); + t_sfm *x = (t_sfm *)(w[2]); + t_int N = (t_int)(w[3]),M = (N >> 1) - 1,n; + t_float F, A = 0, G = 1; + t_float iM = 1 / (float)M; + for(n = 0; n < M; n++){ + if(in[n] !=0){ + G *= in[n]; + A += in[n]; + } + } + F = 10 * log10(pow(G, iM) / (iM * A)); + outlet_float(x->x_obj.ob_outlet, F); + return (w+4); +} + +static void sfm_dsp(t_sfm *x, t_signal **sp) +{ + dsp_add(sfm_perform, 3, + sp[0]->s_vec, x, sp[0]->s_n); +} + +static void *sfm_new(void) +{ + t_sfm *x = (t_sfm *)pd_new(sfm_class); + outlet_new(&x->x_obj, &s_float); + return (void *)x; +} + + +void sfm_tilde_setup(void) { + sfm_class = class_new(gensym("sfm~"), + (t_newmethod)sfm_new, + 0, sizeof(t_sfm), + CLASS_DEFAULT,0); + + class_addmethod(sfm_class, + (t_method)sfm_dsp, gensym("dsp"), 0); + CLASS_MAINSIGNALIN(sfm_class, t_sfm,f); + class_sethelpsymbol(sfm_class, gensym("help-flib")); +} diff --git a/flib/src/ss~.c b/flib/src/ss~.c new file mode 100644 index 0000000..8ad1caa --- /dev/null +++ b/flib/src/ss~.c @@ -0,0 +1,71 @@ +/* flib - PD library for feature extraction +Copyright (C) 2005 Jamie Bullock + +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + + + +/* calculates the spectral smoothness of one frame according to Krimphoff et al. 1994*/ + +#include "flib.h" +static t_class *ss_class; + +typedef struct _ss { + t_object x_obj; + t_float f,x; +} t_ss; + +static t_int *ss_perform(t_int *w) +{ + t_sample *in = (t_sample *)(w[1]); + t_ss *x = (t_ss *)(w[2]); + t_int N = (t_int)(w[3]),M = N >> 1,n; + t_float I = 0, buf[M]; + for(n = 0; n < M; buf[n++] = *in++); + for(n = 2; n < M - 1; n++){ + if(buf[n] != 0 && buf[n-1] != 0 && buf[n+1] != 0) + I += (buf[n] - (buf[n-1] + buf[n] + buf[n+1]) / 3); + } + + outlet_float(x->x_obj.ob_outlet, I); + return (w+4); +} + +static void ss_dsp(t_ss *x, t_signal **sp) +{ + dsp_add(ss_perform, 3, + sp[0]->s_vec, x, sp[0]->s_n); +} + +static void *ss_new(void) +{ + t_ss *x = (t_ss *)pd_new(ss_class); + outlet_new(&x->x_obj, &s_float); + return (void *)x; +} + + +void ss_tilde_setup(void) { + ss_class = class_new(gensym("ss~"), + (t_newmethod)ss_new, + 0, sizeof(t_ss), + CLASS_DEFAULT,0); + + class_addmethod(ss_class, + (t_method)ss_dsp, gensym("dsp"), 0); + CLASS_MAINSIGNALIN(ss_class, t_ss,f); + class_sethelpsymbol(ss_class, gensym("help-flib")); +} diff --git a/flib/src/trist~.c b/flib/src/trist~.c new file mode 100644 index 0000000..93fd3b9 --- /dev/null +++ b/flib/src/trist~.c @@ -0,0 +1,92 @@ +/* flib - PD library for feature extraction +Copyright (C) 2005 Jamie Bullock + +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + + + +/* calculates tristimulus of one frame according to method outlined by Pollard and Jansson. First argument determines method used (x,y, or z) */ + +#include "flib.h" +static t_class *trist_class; + +typedef struct _trist { + t_object x_obj; + t_float f,x; + t_symbol *t; +} t_trist; + +static t_int *trist_perform(t_int *w) +{ + t_sample *in = (t_sample *)(w[1]); + t_trist *x = (t_trist *)(w[2]); + t_int N = (t_int)(w[3]),M = (N >> 1) - 1,n,i = 0; + t_float T, A = 0,p1 = 0,p2 = 0,p3 = 0,p4 = 0,p5 = 0; + + for(n = 0; n < M; n++){ + A += in[n]; + if (in[n] != 0 && i < 5){ + switch(i){ + case 4: p5 = in[n]; i++; + break; + case 3: p4 = in[n]; i++; + break; + case 2: p3 = in[n]; i++; + break; + case 1: p2 = in[n]; i++; + break; + case 0: p1 = in[n]; i++; + break; + } + } + } + if (*x->t->s_name == 'z') + T = p1 / A; + else if (*x->t->s_name == 'y') + T = (p2 + p3 + p4) / A; + else + T = (A - p1 + p2 + p3 + p4 + p5) / A; + + outlet_float(x->x_obj.ob_outlet, T); + return (w+4); +} + +static void trist_dsp(t_trist *x, t_signal **sp) +{ + dsp_add(trist_perform, 3, + sp[0]->s_vec, x, sp[0]->s_n); +} + +static void *trist_new(t_symbol *s) +{ + t_trist *x = (t_trist *)pd_new(trist_class); + x->t = s; + outlet_new(&x->x_obj, &s_float); + return (void *)x; +} + + +void trist_tilde_setup(void) { + trist_class = class_new(gensym("trist~"), + (t_newmethod)trist_new, + 0, sizeof(t_trist), + CLASS_DEFAULT, A_DEFSYMBOL, 0); + + class_addmethod(trist_class, + (t_method)trist_dsp, gensym("dsp"), 0); + CLASS_MAINSIGNALIN(trist_class, t_trist,f); + class_sethelpsymbol(trist_class, gensym("help-flib")); +} diff --git a/flib/src/wdv~.c b/flib/src/wdv~.c new file mode 100644 index 0000000..dfca9fd --- /dev/null +++ b/flib/src/wdv~.c @@ -0,0 +1,234 @@ +/* flib - PD library for feature extraction +Copyright (C) 2005 Jamie Bullock + +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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + + + +/* calculates the wavelet dispersion vector from the output of dwt from creb*/ + +/* First argument gives the DSP block size, second argument gives the amount of data reduction in the output vector as a percentage */ + +#include "flib.h" + +#define ISPOWEROFTWO(n) (!((n-1) & n)) + + +static t_class *wdv_class; + +typedef struct _coeff { + t_int scale; + t_float val; +} t_coeff; + +static void divisi(t_float *, t_coeff **, int , int ); + +typedef struct _wdv { + t_object x_obj; + t_float f; + t_coeff **ranktab; + t_int **histo, *vector; + t_int N, M, scales, vecsize, offset; + t_outlet *out_vec; +} t_wdv; + + +static t_int compare(t_coeff *x, t_coeff *y){ /*sorts in descending order */ + if( x->val > y->val) + return -1; + else if (x->val < y->val) + return 1; + else + return 0; +} + +static t_int bitcount(t_int x){ + t_int i=0; + while(!(x & 01)){ + i++; + x >>= 1; + } + return i; +} + +static void divisi(t_float *arrayin, t_coeff **arrayout, int N, int scales){ + + t_int row, elements, nelements, n, p, i, j, col; + t_float scaling; + row = N / 2; + col = scales; + nelements = elements = row; + n = N - 1; + + scaling = arrayin[0] / scales; /* hmmm - include this or not ? */ + + for(i = 0; i < row; i++) + arrayout[i][0].val = scaling; + /* Copy the scaling function to all rows */ + + while(col--){ + row = 0; + for(i = 0; i < elements; i++, n--){ + p = nelements / elements; + for(j = 0; j < p; j++) + arrayout[row++][col].val = + arrayin[n] / (t_float)(scales - col); + /* divide by reverse scale no. to avg over the block */ + } + + elements /= 2; + } + +} + +static t_int *wdv_perform(t_int *w) +{ + t_sample *in = (t_sample *)(w[1]); + t_int N = (t_int)(w[2]); + t_wdv *x = (t_wdv *)(w[3]); + t_int i, j, k, n, scale; + t_atom atom_list_out[x->vecsize]; + + + /* ensure our blocksize matches block~ size */ + + if(N != x->N){ + post("First argument must equal DSP block size!"); + return (w+4); + } + + + /* Zero histogram and populate scale entries */ + + for (i = 0; i < x->scales; i++) + memset(&x->histo[i][0], 0, x->scales * sizeof(t_int)); + + + for(i = 0; i < x->M; i++){ + for(j = 0, scale = x->scales; j < x->scales; j++, scale--) + x->ranktab[i][j].scale = scale; + } + + + /* Tabulate data and average scales accross columns */ + + divisi(&in[0], &x->ranktab[0], x->N, x->scales); + + + /* Calulate the rank value for each scale in place. Array index gives rank */ + + for(i = 0; i < x->M; i++) + qsort(&x->ranktab[i][0], x->scales, + sizeof(t_coeff), (void *)compare); + + + + /* Create rank/scale matrix */ + + for(i = 0; i < x->scales; i++){ + for(j = 0; j < x->M; j++) + x->histo[x->ranktab[j][i].scale - 1][i]++; + } + + + /* Generate output vector */ + + k = x->scales - x->offset; + + for(n = 0, i = x->offset; i < k; i++){ + for(j = 0; j < x->scales; j++) + x->vector[n++] = x->histo[i][j]; + } + + for(i = 0; i < x->vecsize; i++) + SETFLOAT(atom_list_out+i, x->vector[i]); + + outlet_list(x->out_vec, &s_list, x->vecsize, atom_list_out); + + return (w+4); +} + +static void wdv_dsp(t_wdv *x, t_signal **sp) +{ + dsp_add(wdv_perform, 3, + sp[0]->s_vec, sp[0]->s_n, x); +} + +static void *wdv_new(t_symbol *s, t_int argc, t_atom *argv) +{ + t_wdv *x = (t_wdv *)pd_new(wdv_class); + x->out_vec = outlet_new(&x->x_obj, &s_list); + + t_int i, j, m, scale, rowsize, compression; + + x->N = (t_int)atom_getfloatarg(0, argc, argv); + x->M = x->N * .5f; + x->scales = bitcount(x->N) + 1; + compression = (t_int)atom_getfloatarg(1, argc, argv); + x->offset = rintf((100 - compression) * x->scales * .01 * .5); + x->vecsize = (x->scales - x->offset * 2) * x->scales; + rowsize = scale = x->scales; + m = x->M; + + if(!ISPOWEROFTWO(x->N)) + post("invalid blocksize, must be a power of two"); + else + post("blocksize = %d, scales = %d, vectorsize = %d, offset = %d", + x->N, x->scales, x->vecsize, x->offset); + + x->vector = (t_int *)getbytes(x->vecsize * sizeof(t_int)); + + x->ranktab = (t_coeff **)getbytes(x->M * sizeof(t_coeff *)); + + while(m--) + x->ranktab[m] = (t_coeff *)getbytes(x->scales * sizeof(t_coeff)); + + x->histo = (t_int **)getbytes(x->scales * sizeof(t_int *)); + + while(scale--) + x->histo[scale] = (t_int *)getbytes(x->scales * sizeof(t_int)); + + + return (void *)x; +} + +static void wdv_tilde_free(t_wdv *x){ + t_int i; + + for(i = 0; i < x->M; i++) + free(x->ranktab[i]); + free(x->ranktab); + + for(i = 0; i < x->scales; i++) + free(x->histo[i]); + free(x->histo); + + free(x->vector); + +/* freebytes(x->buf, x->blocks * sizeof(t_coeff)); */ +} + + +void wdv_tilde_setup(void) { + wdv_class = class_new(gensym("wdv~"), + (t_newmethod)wdv_new, + 0, sizeof(t_wdv), + CLASS_DEFAULT, A_GIMME, 0); + + class_addmethod(wdv_class, (t_method)wdv_dsp, gensym("dsp"), 0); + CLASS_MAINSIGNALIN(wdv_class, t_wdv,f); + class_sethelpsymbol(wdv_class, gensym("help-flib")); +} -- cgit v1.2.1