aboutsummaryrefslogtreecommitdiff
path: root/flib/src
diff options
context:
space:
mode:
Diffstat (limited to 'flib/src')
-rw-r--r--flib/src/bmax~.c103
-rw-r--r--flib/src/clean~.c87
-rw-r--r--flib/src/flib.c61
-rw-r--r--flib/src/flib.h40
-rw-r--r--flib/src/ha~.c85
-rw-r--r--flib/src/hca~.c108
-rw-r--r--flib/src/irreg~.c70
-rw-r--r--flib/src/melf~.c218
-rw-r--r--flib/src/mspec~.c89
-rw-r--r--flib/src/peak~.c129
-rw-r--r--flib/src/pp~.c70
-rw-r--r--flib/src/pspec~.c77
-rw-r--r--flib/src/sc~.c77
-rw-r--r--flib/src/sfm~.c75
-rw-r--r--flib/src/ss~.c71
-rw-r--r--flib/src/trist~.c92
-rw-r--r--flib/src/wdv~.c234
17 files changed, 1686 insertions, 0 deletions
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 <math.h>
+#include <stdlib.h>
+#include <string.h>
+
+#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 <math.h>
+
+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"));
+}