aboutsummaryrefslogtreecommitdiff
path: root/pd/extra/bonk~
diff options
context:
space:
mode:
Diffstat (limited to 'pd/extra/bonk~')
-rw-r--r--pd/extra/bonk~/bonk~-help.pd55
-rw-r--r--pd/extra/bonk~/bonk~.c53
2 files changed, 65 insertions, 43 deletions
diff --git a/pd/extra/bonk~/bonk~-help.pd b/pd/extra/bonk~/bonk~-help.pd
index d66ed5b0..e4bbb827 100644
--- a/pd/extra/bonk~/bonk~-help.pd
+++ b/pd/extra/bonk~/bonk~-help.pd
@@ -1,13 +1,13 @@
-#N canvas 304 143 967 599 10;
-#X obj 370 524 spigot;
+#N canvas 304 143 967 599 12;
+#X obj 358 544 spigot;
#X msg 442 397 bang;
-#X obj 429 488 bonk~;
+#X obj 428 508 bonk~;
#X msg 442 214 learn 1;
#X msg 442 274 learn 0;
-#X msg 437 456 print;
+#X msg 446 451 print;
#X obj 390 437 adc~;
-#X msg 614 538 \; pd dsp 1;
-#X obj 277 524 spigot;
+#X msg 613 558 \; pd dsp 1;
+#X obj 276 544 spigot;
#N canvas 366 126 604 404 synth 0;
#X obj 112 24 r bonk-cooked;
#X obj 112 49 unpack;
@@ -59,14 +59,14 @@
#X connect 21 0 1 0;
#X connect 22 0 6 0;
#X connect 23 0 9 0;
-#X restore 846 555 pd synth;
-#X floatatom 846 532 0 0 0 0 - - -;
-#X msg 846 502 0;
+#X restore 845 575 pd synth;
+#X floatatom 845 552 0 0 0 0 - - -;
+#X msg 845 522 0;
#X msg 442 244 learn 10;
#X msg 442 304 forget;
#X msg 442 334 write templates.txt;
#X msg 442 364 read templates.txt;
-#X msg 877 502 90;
+#X msg 876 522 90;
#X msg 442 81 thresh 6 50;
#X text 8 56 The Bonk object takes an audio signal input and looks
for "attacks" defined as sharp changes in the spectral envelope of
@@ -75,13 +75,13 @@ Bonk check the attack against a collection of stored templates to try
to guess which of two or more instruments was hit. Bonk is described
theoretically in the 1998 ICMC proceedings \, reprinted on http://man104nfs.ucsd.edu/~mpuckett.
;
-#X text 602 504 click here;
-#X text 603 517 to start DSP;
+#X text 601 524 click here;
+#X text 602 537 to start DSP;
#X text 8 377 In this patch \, after starting DSP \, you can print
out the raw or cooked output using the two "spigots" or listen to a
synthesizer output by raising its volume.;
-#X text 747 501 output volume;
-#X text 761 519 (0-100);
+#X text 746 521 output volume;
+#X text 760 539 (0-100);
#X msg 442 150 mask 4 0.7;
#X msg 442 184 debounce 0;
#X text 8 309 Bonk's analysis is carried out on a 256-point window
@@ -89,7 +89,7 @@ synthesizer output by raising its volume.;
The analysis period can be specified as Bonk's creation argument but
must be a multiple of 64;
#X text 532 185 Minimum time (msec) between attacks;
-#X text 532 140 Describes how energy in each frequency band masks later
+#X text 526 136 Describes how energy in each frequency band masks later
energy in the band. Here the masking is total for 4 analysis periods
and then drops by 0.7 each period.;
#X text 530 214 Forget all templates and start learning new ones. The
@@ -101,22 +101,22 @@ to erase and record over a template.;
#X text 595 334 Write templates to a file in text-editable format.
;
#X text 596 364 Read templates from a file.;
-#X text 538 453 Print out all settings and templates.;
+#X text 514 450 Print out all settings and templates.;
#X msg 442 120 minvel 10;
-#X text 538 392 Poll the current spectrum via "raw" outlet \, You can
+#X text 514 392 Poll the current spectrum via "raw" outlet \, You can
set a very high threshold if you don't want attacks mixed in.;
#X msg 437 426 debug 0;
-#X text 538 426 turn debugging on or off.;
-#X obj 326 525 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0
+#X text 514 426 turn debugging on or off.;
+#X obj 325 545 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0
1;
-#X obj 419 525 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0
+#X obj 407 545 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0
1;
-#X obj 370 554 print cooked;
-#X obj 277 554 print raw;
-#X text 253 490 enable printout:;
-#X text 533 121 Minimum "velocity" to output (quieter notes are ignored.)
+#X obj 358 574 print cooked;
+#X obj 276 574 print raw;
+#X text 158 545 enable printout:;
+#X text 530 121 Minimum "velocity" to output (quieter notes are ignored.)
;
-#X obj 462 513 s bonk-cooked;
+#X obj 461 533 s bonk-cooked;
#X text 218 12 BONK~ - an attack detector for small percussion instruments
;
#X text 8 174 Bonk's two outputs are the raw spectrum of the attack
@@ -127,12 +127,14 @@ an instrument number (counting up from zero) and a "velocity". This
bands \, normalized so that 100 is an attack of amplitude of about
1 The instrument number is significant only if Bonk has a "template
set" in memory.;
-#X text 532 52 Set low and high thresholds. Signal growth must exceed
+#X text 531 47 Set low and high thresholds. Signal growth must exceed
the high one and then fall to the low one to make an attack. The unit
is the sum of the proportional growth in the 11 filter bands. Proportional
growth is essentially the logarithmic time derivative.;
#X text 238 27 (NOTE: this documentation does not yet describe new
features for Pd 0.42).;
+#X msg 446 479 print 1;
+#X text 514 481 print out filterbank settings;
#X connect 0 0 40 0;
#X connect 1 0 2 0;
#X connect 2 0 8 0;
@@ -157,3 +159,4 @@ features for Pd 0.42).;
#X connect 36 0 2 0;
#X connect 38 0 8 1;
#X connect 39 0 0 1;
+#X connect 49 0 2 0;
diff --git a/pd/extra/bonk~/bonk~.c b/pd/extra/bonk~/bonk~.c
index ee59cb0f..369d9e38 100644
--- a/pd/extra/bonk~/bonk~.c
+++ b/pd/extra/bonk~/bonk~.c
@@ -95,6 +95,7 @@ static t_class *bonk_class;
#define DEFHALFTONES 6
#define DEFOVERLAP 1
#define DEFFIRSTBIN 1
+#define DEFMINBANDWIDTH 1.5
#define DEFHITHRESH 5
#define DEFLOTHRESH 2.5
#define DEFMASKTIME 4
@@ -122,6 +123,7 @@ typedef struct _filterbank
float b_halftones; /* filter bandwidth in halftones */
float b_overlap; /* overlap; default 1 for 1/2-power pts */
float b_firstbin; /* freq of first filter in bins, default 1 */
+ float b_minbandwidth; /* minimum bandwidth, default 1.5 */
t_filterkernel *b_vec; /* filter kernels */
int b_refcount; /* number of bonk~ objects using this */
struct _filterbank *b_next; /* next in linked list */
@@ -206,7 +208,7 @@ typedef struct _bonk
float x_halftones; /* nominal halftones between filters */
float x_overlap;
float x_firstbin;
-
+ float x_minbandwidth;
float x_hithresh; /* threshold for total growth to trigger */
float x_lothresh; /* threshold for total growth to re-arm */
float x_minvel; /* minimum velocity we output */
@@ -275,10 +277,11 @@ char *strcpy(char *s1, const char *s2);
static void bonk_tick(t_bonk *x);
-#define HALFWIDTH 0.75 /* half peak bandwidth at half power point in bins */
+#define HALFWIDTH 0.75 /* half peak bandwidth at half power point in bins */
+#define SLIDE 0.25 /* relative slide between filter subwindows */
static t_filterbank *bonk_newfilterbank(int npoints, int nfilters,
- float halftones, float overlap, float firstbin)
+ float halftones, float overlap, float firstbin, float minbandwidth)
{
int i, j;
float cf, bw, h, relspace;
@@ -288,6 +291,7 @@ static t_filterbank *bonk_newfilterbank(int npoints, int nfilters,
b->b_halftones = halftones;
b->b_overlap = overlap;
b->b_firstbin = firstbin;
+ b->b_minbandwidth = minbandwidth;
b->b_refcount = 0;
b->b_next = bonk_filterbanklist;
bonk_filterbanklist = b;
@@ -296,17 +300,21 @@ static t_filterbank *bonk_newfilterbank(int npoints, int nfilters,
h = exp((log(2.)/12.)*halftones); /* specced interval between filters */
relspace = (h - 1)/(h + 1); /* nominal spacing-per-f for fbank */
+ if (minbandwidth < 2*HALFWIDTH)
+ minbandwidth = 2*HALFWIDTH;
+ if (firstbin < minbandwidth/(2*HALFWIDTH))
+ firstbin = minbandwidth/(2*HALFWIDTH);
cf = firstbin;
bw = cf * relspace * overlap;
- if (bw < HALFWIDTH)
- bw = HALFWIDTH;
+ if (bw < (0.5*minbandwidth))
+ bw = (0.5*minbandwidth);
for (i = 0; i < nfilters; i++)
{
float *fp, newcf, newbw;
float normalizer = 0;
int filterpoints, skippoints, hoppoints, nhops;
- filterpoints = 0.5 + npoints * HALFWIDTH/bw;
+ filterpoints = npoints * HALFWIDTH/bw;
if (cf > npoints/2)
{
post("bonk~: only using %d filters (ran past Nyquist)", i+1);
@@ -320,7 +328,7 @@ static t_filterbank *bonk_newfilterbank(int npoints, int nfilters,
else if (filterpoints > npoints)
filterpoints = npoints;
- hoppoints = 0.5 + 0.5 * npoints * HALFWIDTH/bw;
+ hoppoints = SLIDE * npoints * HALFWIDTH/bw;
nhops = 1. + (npoints-filterpoints)/(float)hoppoints;
skippoints = 0.5 * (npoints-filterpoints - (nhops-1) * hoppoints);
@@ -343,7 +351,7 @@ static t_filterbank *bonk_newfilterbank(int npoints, int nfilters,
fp[1] = window * sin(phase);
normalizer += window;
}
- normalizer = 1/(normalizer * nhops);
+ normalizer = 1/(normalizer * sqrt(nhops));
for (fp = b->b_vec[i].k_stuff, j = 0;
j < filterpoints; j++, fp+= 2)
fp[0] *= normalizer, fp[1] *= normalizer;
@@ -353,10 +361,10 @@ static t_filterbank *bonk_newfilterbank(int npoints, int nfilters,
#endif
newcf = (cf + bw/overlap)/(1 - relspace);
newbw = newcf * overlap * relspace;
- if (newbw < HALFWIDTH)
+ if (newbw < 0.5*minbandwidth)
{
- newbw = HALFWIDTH;
- newcf = cf + 2 * HALFWIDTH / overlap;
+ newbw = 0.5*minbandwidth;
+ newcf = cf + minbandwidth / overlap;
}
cf = newcf;
bw = newbw;
@@ -387,7 +395,7 @@ static void bonk_freefilterbank(t_filterbank *b)
static void bonk_donew(t_bonk *x, int npoints, int period, int nsig,
int nfilters, float halftones, float overlap, float firstbin,
- float samplerate)
+ float minbandwidth, float samplerate)
{
int i, j;
t_hist *h;
@@ -440,7 +448,8 @@ static void bonk_donew(t_bonk *x, int npoints, int period, int nsig,
fb->b_halftones == x->x_halftones &&
fb->b_firstbin == firstbin &&
fb->b_overlap == overlap &&
- fb->b_npoints == x->x_npoints)
+ fb->b_npoints == x->x_npoints &&
+ fb->b_minbandwidth == minbandwidth)
{
fb->b_refcount++;
x->x_filterbank = fb;
@@ -448,7 +457,7 @@ static void bonk_donew(t_bonk *x, int npoints, int period, int nsig,
}
if (!x->x_filterbank)
x->x_filterbank = bonk_newfilterbank(npoints, nfilters,
- halftones, overlap, firstbin),
+ halftones, overlap, firstbin, minbandwidth),
x->x_filterbank->b_refcount++;
}
@@ -1035,7 +1044,7 @@ static void *bonk_new(t_symbol *s, int argc, t_atom *argv)
int nsig = 1, period = DEFPERIOD, npts = DEFNPOINTS,
nfilters = DEFNFILTERS, j;
float halftones = DEFHALFTONES, overlap = DEFOVERLAP,
- firstbin = DEFFIRSTBIN;
+ firstbin = DEFFIRSTBIN, minbandwidth = DEFMINBANDWIDTH;
t_insig *g;
if (argc > 0 && argv[0].a_type == A_FLOAT)
@@ -1082,6 +1091,11 @@ static void *bonk_new(t_symbol *s, int argc, t_atom *argv)
firstbin = atom_getfloatarg(1, argc, argv);
argc -= 2; argv += 2;
}
+ else if (!strcmp(firstarg->s_name, "-minbandwidth") && argc > 1)
+ {
+ minbandwidth = atom_getfloatarg(1, argc, argv);
+ argc -= 2; argv += 2;
+ }
else if (!strcmp(firstarg->s_name, "-spew") && argc > 1)
{
x->x_spew = (atom_getfloatarg(1, argc, argv) != 0);
@@ -1123,7 +1137,7 @@ static void *bonk_new(t_symbol *s, int argc, t_atom *argv)
}
x->x_cookedout = outlet_new(&x->x_obj, gensym("list"));
bonk_donew(x, npts, period, nsig, nfilters, halftones, overlap,
- firstbin, sys_getsr());
+ firstbin, minbandwidth, sys_getsr());
return (x);
}
@@ -1182,6 +1196,9 @@ int main()
attr = attr_offset_new("firstbin", sym_float32, attrflags, (method)0L, (method)0L, calcoffset(t_bonk, x_firstbin));
class_addattr(c, attr);
+ attr = attr_offset_new("minbandwidth", sym_float32, attrflags, (method)0L, (method)0L, calcoffset(t_bonk, x_minbandwidth));
+ class_addattr(c, attr);
+
attr = attr_offset_new("minvel", sym_float32, attrflags, (method)0L, (method)bonk_minvel_set, calcoffset(t_bonk, x_minvel));
class_addattr(c, attr);
@@ -1250,6 +1267,7 @@ static void *bonk_new(t_symbol *s, long ac, t_atom *av)
x->x_nfilters = DEFNFILTERS;
x->x_halftones = DEFHALFTONES;
x->x_firstbin = DEFFIRSTBIN;
+ x->x_minbandwidth = DEFMINBANDWIDTH;
x->x_overlap = DEFOVERLAP;
x->x_ninsig = 1;
@@ -1305,7 +1323,8 @@ static void *bonk_new(t_symbol *s, long ac, t_atom *av)
x->x_clock = clock_new(x, (method)bonk_tick);
bonk_donew(x, x->x_npoints, x->x_period, x->x_ninsig, x->x_nfilters,
- x->x_halftones, x->x_overlap, x->x_firstbin, sys_getsr());
+ x->x_halftones, x->x_overlap, x->x_firstbin, x->x_minbandwidth,
+ sys_getsr());
}
return (x);
}