aboutsummaryrefslogtreecommitdiff
path: root/pd/extra/pique
diff options
context:
space:
mode:
Diffstat (limited to 'pd/extra/pique')
-rw-r--r--pd/extra/pique/help-pique.pd33
-rw-r--r--pd/extra/pique/makefile8
-rw-r--r--pd/extra/pique/pique.c.old148
3 files changed, 184 insertions, 5 deletions
diff --git a/pd/extra/pique/help-pique.pd b/pd/extra/pique/help-pique.pd
new file mode 100644
index 00000000..1689c95b
--- /dev/null
+++ b/pd/extra/pique/help-pique.pd
@@ -0,0 +1,33 @@
+#N canvas 143 0 729 407 12;
+#X obj 47 11 pique;
+#X text 105 12 -- find peaks in an FFT spectrum;
+#X obj 214 174 rfft~;
+#X obj 131 129 osc~ 2000;
+#X graph graph2 0 -64 63 64 519 179 719 39;
+#X array fft-real 64 float;
+#X pop;
+#X graph graph3 0 -64 63 64 519 327 719 187;
+#X array fft-imag 64 float;
+#X pop;
+#X obj 214 215 tabwrite~ fft-real;
+#X obj 245 240 tabwrite~ fft-imag;
+#X obj 315 158 metro 1000;
+#X obj 315 116 loadbang;
+#X msg 315 138 1;
+#X obj 91 349 pique;
+#X msg 91 322 64 fft-real fft-imag 10;
+#X obj 91 376 print;
+#X obj 205 132 osc~ 5000;
+#X text 25 37 pique takes unwindowed FFT analyses as input (they should be stored in arrays) and outputs a list of peaks \, giving their peak number \, frequency \, amplitude \, and phase (as a cosine/sine pair.);
+#X text 13 289 message argumnets: number of FFT points \, fft real part \, fft imaginary part \, maximum number of peaks to report.;
+#X text 578 387 updated for Pd 0.31.;
+#X connect 2 0 6 0;
+#X connect 2 1 7 0;
+#X connect 3 0 2 0;
+#X connect 8 0 6 0;
+#X connect 8 0 7 0;
+#X connect 9 0 10 0;
+#X connect 10 0 8 0;
+#X connect 11 0 13 0;
+#X connect 12 0 11 0;
+#X connect 14 0 2 0;
diff --git a/pd/extra/pique/makefile b/pd/extra/pique/makefile
index 47a7463e..8158e7cd 100644
--- a/pd/extra/pique/makefile
+++ b/pd/extra/pique/makefile
@@ -70,8 +70,7 @@ LINUXINCLUDE = -I../../src
cc $(LINUXCFLAGS) $(LINUXINCLUDE) -o $*.o -c $*.c
ld -export_dynamic -shared -o $*.pd_linux $*.o -lc -lm
strip --strip-unneeded $*.pd_linux
- rm -f $*.o ../$*.pd_linux
- ln -s $*/$*.pd_linux ..
+ rm -f $*.o
# ----------------------- Mac OSX -----------------------
@@ -84,9 +83,8 @@ DARWINCFLAGS = -DPD -O2 -Wall -W -Wshadow -Wstrict-prototypes \
.c.pd_darwin:
cc $(DARWINCFLAGS) $(LINUXINCLUDE) -o $*.o -c $*.c
- cc -bundle -undefined suppress -flat_namespace -o $*.pd_darwin $*.o
- rm -f $*.o ../$*.pd_darwin
- ln -s $*/$*.pd_darwin ..
+ cc -bundle -undefined suppress -flat_namespace -o $*.pd_darwin $*.o
+ rm -f $*.o
# ----------------------------------------------------------
diff --git a/pd/extra/pique/pique.c.old b/pd/extra/pique/pique.c.old
new file mode 100644
index 00000000..75afc38c
--- /dev/null
+++ b/pd/extra/pique/pique.c.old
@@ -0,0 +1,148 @@
+/* Copyright (c) 1998 The Regents of the University of California. The
+contents of this file are free for any use, but BOTH THE AUTHOR AND UCSD
+DISCLAIM ALL WARRANTIES related to it. Although not written in Java, this
+still should not be used to control any machinery containing a sharp blade or
+combustible materiel, or as part of any life support system or weapon. */
+
+#include "m_pd.h"
+#include <math.h>
+
+static t_class *pique_class;
+
+typedef struct _pique
+{
+ t_object x_obj;
+} t_pique;
+
+static void *pique_new(void)
+{
+ t_pique *x = (t_pique *)pd_new(pique_class);
+ return (x);
+}
+
+ /* we aren't measuring phase yet */
+static void pique_doit(int npts, t_float *fpreal, t_float *fpimag,
+ int npeak, t_float *fpfreq, t_float *fpamp)
+{
+ float srate = sys_getsr(); /* not sure how to get this correctly */
+ float oneovern = 1.0/ (float)npts;
+ float fperbin = srate * oneovern;
+ float pow1, pow2 = 0, pow3 = 0, pow4 = 0, pow5 = 0;
+ float re1, re2 = 0, re3 = *fpreal;
+ float im1, im2 = 0, im3 = 0, powthresh;
+ int count, peakcount = 0, n2 = (npts >> 1);
+ float *fp1, *fp2;
+ for (count = n2, fp1 = fpreal, fp2 = fpimag, powthresh = 0;
+ count--; fp1++, fp2++)
+ powthresh += (*fp1) * (*fp1) + (*fp2) * (*fp2) ;
+ powthresh *= 0.00001;
+ for (count = 1; count < n2; count++)
+ {
+ float windreal, windimag, pi = 3.14159;
+ float detune, pidetune, ampcorrect, freqout, ampout;
+ float rpeak, rpeaknext, rpeakprev;
+ float ipeak, ipeaknext, ipeakprev;
+ fpreal++;
+ fpimag++;
+ re1 = re2;
+ re2 = re3;
+ re3 = *fpreal;
+ im1 = im2;
+ im2 = im3;
+ im3 = *fpimag;
+ if (count < 2) continue;
+ pow1 = pow2;
+ pow2 = pow3;
+ pow3 = pow4;
+ pow4 = pow5;
+ /* get Hanning-windowed spectrum by convolution */
+ windreal = re2 - 0.5 * (re1 + re3);
+ windimag = im2 - 0.5 * (im1 + im3);
+ pow5 = windreal * windreal + windimag * windimag;
+ /* if (count < 30) post("power %f", pow5); */
+ if (count < 5) continue;
+ /* check for a peak. The actual bin is count-3. */
+ if (pow3 <= pow2 || pow3 <= pow4 || pow3 <= pow1 || pow3 <= pow5
+ || pow3 < powthresh)
+ continue;
+ /* go back for the raw FFT values around the peak. */
+ rpeak = fpreal[-3];
+ rpeaknext = fpreal[-2];
+ rpeakprev = fpreal[-4];
+ ipeak = fpimag[-3];
+ ipeaknext = fpimag[-2];
+ ipeakprev = fpimag[-4];
+
+ detune = ((rpeakprev - rpeaknext) *
+ (2.0 * rpeak - rpeakprev - rpeaknext) +
+ (ipeakprev - ipeaknext) *
+ (2.0 * ipeak - ipeakprev - ipeaknext)) /
+ (4.0 * pow3);
+ /* if (count < 30) post("detune %f", detune); */
+ if (detune > 0.7 || detune < -0.7) continue;
+ /* the frequency is the sum of the bin frequency and detuning */
+ freqout = fperbin * ((float)(count-3) + detune);
+ *fpfreq++ = freqout;
+ pidetune = pi * detune;
+ if (pidetune < 0.01 && pidetune > -0.01) ampcorrect = 1;
+ else ampcorrect = 1.0 / (sin(pidetune)/pidetune + 0.5 *
+ (sin(pidetune + pi)/(pidetune+pi) +
+ sin(pidetune-pi)/(pidetune-pi)));
+ /* amplitude is peak height, corrected for Hanning window shape.
+ Multiply by 2 to get real-sinusoid peak amplitude */
+ ampout = 2. * oneovern * sqrt(pow3) * ampcorrect;
+ *fpamp++ = ampout;
+ /* post("peak %f %f", freqout, ampout); */
+ if (++peakcount == npeak) break;
+ }
+ while (peakcount < npeak)
+ {
+ *fpfreq++ = 0;
+ *fpamp++ = 0;
+ peakcount++;
+ }
+}
+
+static void pique_list(t_pique *x, t_symbol *s, int argc, t_atom *argv)
+{
+ int npts = atom_getintarg(0, argc, argv);
+ t_symbol *symreal = atom_getsymbolarg(1, argc, argv);
+ t_symbol *symimag = atom_getsymbolarg(2, argc, argv);
+ int npeak = atom_getintarg(3, argc, argv);
+ t_symbol *symfreq = atom_getsymbolarg(4, argc, argv);
+ t_symbol *symamp = atom_getsymbolarg(5, argc, argv);
+ t_garray *a, *afreq, *aamp;
+ int n;
+ t_float *fpreal, *fpimag, *fpfreq, *fpamp, *fpphase;
+ if (npts < 8 || npeak < 1) error("pique: bad npoints or npeak");
+ else if (!(a = (t_garray *)pd_findbyclass(symreal, garray_class)) ||
+ !garray_getfloatarray(a, &n, &fpreal) ||
+ n < npts)
+ error("%s: missing or bad array", symreal->s_name);
+ else if (!(a = (t_garray *)pd_findbyclass(symimag, garray_class)) ||
+ !garray_getfloatarray(a, &n, &fpimag) ||
+ n < npts)
+ error("%s: missing or bad array", symimag->s_name);
+ else if (!(afreq = (t_garray *)pd_findbyclass(symfreq, garray_class)) ||
+ !garray_getfloatarray(afreq, &n, &fpfreq) ||
+ n < npeak)
+ error("%s: missing or bad array", symfreq->s_name);
+ else if (!(aamp = (t_garray *)pd_findbyclass(symamp, garray_class)) ||
+ !garray_getfloatarray(aamp, &n, &fpamp) ||
+ n < npeak)
+ error("%s: missing or bad array", symamp->s_name);
+ else
+ {
+ pique_doit(npts, fpreal, fpimag, npeak, fpfreq, fpamp);
+ garray_redraw(afreq);
+ garray_redraw(aamp);
+ }
+}
+
+void pique_setup(void)
+{
+ pique_class = class_new(gensym("pique"), pique_new, 0,
+ sizeof(t_pique), 0, 0);
+ class_addlist(pique_class, pique_list);
+}
+