annotate modules-and-plug-ins/max-external/btrack~.cpp @ 78:866024f9f95a

Added initial basic Max external and implemented getCurrentTempoEstimate() in BTrack.cpp
author Adam Stark <adamstark.uk@gmail.com>
date Mon, 24 Nov 2014 11:48:08 +0000
parents
children 9fd4075b8f9e
rev   line source
adamstark@78 1 //===========================================================================
adamstark@78 2 /** @file btrack~.cpp
adamstark@78 3 * @brief The btrack~ Max external
adamstark@78 4 * @author Adam Stark
adamstark@78 5 * @copyright Copyright (C) 2008-2014 Queen Mary University of London
adamstark@78 6 *
adamstark@78 7 * This program is free software: you can redistribute it and/or modify
adamstark@78 8 * it under the terms of the GNU General Public License as published by
adamstark@78 9 * the Free Software Foundation, either version 3 of the License, or
adamstark@78 10 * (at your option) any later version.
adamstark@78 11 *
adamstark@78 12 * This program is distributed in the hope that it will be useful,
adamstark@78 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
adamstark@78 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
adamstark@78 15 * GNU General Public License for more details.
adamstark@78 16 *
adamstark@78 17 * You should have received a copy of the GNU General Public License
adamstark@78 18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
adamstark@78 19 */
adamstark@78 20 //===========================================================================
adamstark@78 21
adamstark@78 22 //===========================================================================
adamstark@78 23 #include "ext.h" // standard Max include, always required (except in Jitter)
adamstark@78 24 #include "ext_obex.h" // required for "new" style objects
adamstark@78 25 #include "z_dsp.h" // required for MSP objects
adamstark@78 26
adamstark@78 27 //===========================================================================
adamstark@78 28 // BTrack includes
adamstark@78 29 #include "../../src/BTrack.h"
adamstark@78 30 #include "../../src/OnsetDetectionFunction.h"
adamstark@78 31
adamstark@78 32 //===========================================================================
adamstark@78 33 // struct to represent the object's state
adamstark@78 34 typedef struct _btrack {
adamstark@78 35
adamstark@78 36 // The object itself (t_pxobject in MSP instead of t_object)
adamstark@78 37 t_pxobject ob;
adamstark@78 38
adamstark@78 39 // An instance of the BTrack beat tracker
adamstark@78 40 BTrack *b;
adamstark@78 41
adamstark@78 42 // An outlet for beats
adamstark@78 43 void *beat_outlet;
adamstark@78 44
adamstark@78 45 // An outlet for tempo estimates
adamstark@78 46 void *tempo_outlet;
adamstark@78 47
adamstark@78 48 } t_btrack;
adamstark@78 49
adamstark@78 50
adamstark@78 51 //===========================================================================
adamstark@78 52 // method prototypes
adamstark@78 53 void *btrack_new(t_symbol *s, long argc, t_atom *argv);
adamstark@78 54 void btrack_free(t_btrack *x);
adamstark@78 55 void btrack_assist(t_btrack *x, void *b, long m, long a, char *s);
adamstark@78 56 void btrack_float(t_btrack *x, double f);
adamstark@78 57 void btrack_dsp(t_btrack *x, t_signal **sp, short *count);
adamstark@78 58 void btrack_dsp64(t_btrack *x, t_object *dsp64, short *count, double samplerate, long maxvectorsize, long flags);
adamstark@78 59 t_int *btrack_perform(t_int *w);
adamstark@78 60 void btrack_perform64(t_btrack *x, t_object *dsp64, double **ins, long numins, double **outs, long numouts, long sampleframes, long flags, void *userparam);
adamstark@78 61
adamstark@78 62 //===========================================================================
adamstark@78 63 void btrack_process(t_btrack *x,double* audioFrame);
adamstark@78 64 void outlet_beat(t_btrack *x, t_symbol *s, long argc, t_atom *argv);
adamstark@78 65
adamstark@78 66 // global class pointer variable
adamstark@78 67 static t_class *btrack_class = NULL;
adamstark@78 68
adamstark@78 69
adamstark@78 70
adamstark@78 71
adamstark@78 72 //===========================================================================
adamstark@78 73 int C74_EXPORT main(void)
adamstark@78 74 {
adamstark@78 75 // object initialization, note the use of dsp_free for the freemethod, which is required
adamstark@78 76 // unless you need to free allocated memory, in which case you should call dsp_free from
adamstark@78 77 // your custom free function.
adamstark@78 78
adamstark@78 79 t_class *c = class_new("btrack~", (method)btrack_new, (method)dsp_free, (long)sizeof(t_btrack), 0L, A_GIMME, 0);
adamstark@78 80
adamstark@78 81 class_addmethod(c, (method)btrack_float, "float", A_FLOAT, 0);
adamstark@78 82 class_addmethod(c, (method)btrack_dsp, "dsp", A_CANT, 0); // Old 32-bit MSP dsp chain compilation for Max 5 and earlier
adamstark@78 83 class_addmethod(c, (method)btrack_dsp64, "dsp64", A_CANT, 0); // New 64-bit MSP dsp chain compilation for Max 6
adamstark@78 84 class_addmethod(c, (method)btrack_assist, "assist", A_CANT, 0);
adamstark@78 85
adamstark@78 86 class_dspinit(c);
adamstark@78 87 class_register(CLASS_BOX, c);
adamstark@78 88 btrack_class = c;
adamstark@78 89
adamstark@78 90 return 0;
adamstark@78 91 }
adamstark@78 92
adamstark@78 93
adamstark@78 94 //===========================================================================
adamstark@78 95 void *btrack_new(t_symbol *s, long argc, t_atom *argv)
adamstark@78 96 {
adamstark@78 97 t_btrack *x = (t_btrack *)object_alloc(btrack_class);
adamstark@78 98
adamstark@78 99 if (x) {
adamstark@78 100 dsp_setup((t_pxobject *)x, 1); // MSP inlets: arg is # of inlets and is REQUIRED!
adamstark@78 101 // use 0 if you don't need inlets
adamstark@78 102
adamstark@78 103 object_post((t_object *) x,"v1.0 designed by Adam Stark and Matthew Davies at Queen Mary University of London");
adamstark@78 104
adamstark@78 105 // create detection function and beat tracking objects
adamstark@78 106 x->b = new BTrack();
adamstark@78 107
adamstark@78 108 x->tempo_outlet = floatout(x);
adamstark@78 109 x->beat_outlet = bangout(x);
adamstark@78 110
adamstark@78 111 /*
adamstark@78 112
adamstark@78 113
adamstark@78 114 x->mode = 0;
adamstark@78 115 x->lastbang = 0;
adamstark@78 116
adamstark@78 117 x->dobeats = 1;
adamstark@78 118 x->countin = 4;
adamstark@78 119
adamstark@78 120 x->counttempi[0] = 120;
adamstark@78 121 x->counttempi[1] = 120;
adamstark@78 122 x->counttempi[2] = 120;
adamstark@78 123 */
adamstark@78 124 }
adamstark@78 125 return (x);
adamstark@78 126 }
adamstark@78 127
adamstark@78 128
adamstark@78 129 //===========================================================================
adamstark@78 130 // NOT CALLED!, we use dsp_free for a generic free function
adamstark@78 131 void btrack_free(t_btrack *x)
adamstark@78 132 {
adamstark@78 133 ;
adamstark@78 134 }
adamstark@78 135
adamstark@78 136
adamstark@78 137 //===========================================================================
adamstark@78 138 void btrack_assist(t_btrack *x, void *b, long m, long a, char *s)
adamstark@78 139 {
adamstark@78 140 if (m == ASSIST_INLET) { //inlet
adamstark@78 141 sprintf(s, "I am inlet %ld", a);
adamstark@78 142 }
adamstark@78 143 else { // outlet
adamstark@78 144 sprintf(s, "I am outlet %ld", a);
adamstark@78 145 }
adamstark@78 146 }
adamstark@78 147
adamstark@78 148
adamstark@78 149 //===========================================================================
adamstark@78 150 void btrack_float(t_btrack *x, double f)
adamstark@78 151 {
adamstark@78 152
adamstark@78 153
adamstark@78 154 }
adamstark@78 155
adamstark@78 156 //===========================================================================
adamstark@78 157 // this function is called when the DAC is enabled, and "registers" a function for the signal chain in Max 5 and earlier.
adamstark@78 158 // In this case we register the 32-bit, "btrack_perform" method.
adamstark@78 159 void btrack_dsp(t_btrack *x, t_signal **sp, short *count)
adamstark@78 160 {
adamstark@78 161 int hopSize = (int) sp[0]->s_n;
adamstark@78 162 int frameSize = hopSize*2;
adamstark@78 163
adamstark@78 164 x->b->updateHopAndFrameSize(hopSize, frameSize);
adamstark@78 165
adamstark@78 166 dsp_add(btrack_perform, 3, x, sp[0]->s_vec, sp[0]->s_n);
adamstark@78 167 }
adamstark@78 168
adamstark@78 169
adamstark@78 170 //===========================================================================
adamstark@78 171 // this is the Max 6 version of the dsp method -- it registers a function for the signal chain in Max 6,
adamstark@78 172 // which operates on 64-bit audio signals.
adamstark@78 173 void btrack_dsp64(t_btrack *x, t_object *dsp64, short *count, double samplerate, long maxvectorsize, long flags)
adamstark@78 174 {
adamstark@78 175 int hopSize = (int) maxvectorsize;
adamstark@78 176 int frameSize = hopSize*2;
adamstark@78 177
adamstark@78 178 x->b->updateHopAndFrameSize(hopSize, frameSize);
adamstark@78 179
adamstark@78 180 object_method(dsp64, gensym("dsp_add64"), x, btrack_perform64, 0, NULL);
adamstark@78 181 }
adamstark@78 182
adamstark@78 183
adamstark@78 184 //===========================================================================
adamstark@78 185 // this is the 32-bit perform method for Max 5 and earlier
adamstark@78 186 t_int *btrack_perform(t_int *w)
adamstark@78 187 {
adamstark@78 188 t_btrack *x = (t_btrack *)(w[1]);
adamstark@78 189 t_float *inL = (t_float *)(w[2]);
adamstark@78 190 int n = (int)w[3];
adamstark@78 191
adamstark@78 192 double audioFrame[n];
adamstark@78 193
adamstark@78 194 for (int i = 0;i < n;i++)
adamstark@78 195 {
adamstark@78 196 audioFrame[i] = (double) inL[i];
adamstark@78 197 }
adamstark@78 198
adamstark@78 199 btrack_process(x,audioFrame);
adamstark@78 200
adamstark@78 201 // you have to return the NEXT pointer in the array OR MAX WILL CRASH
adamstark@78 202 return w + 4;
adamstark@78 203 }
adamstark@78 204
adamstark@78 205 //===========================================================================
adamstark@78 206 // this is 64-bit perform method for Max 6
adamstark@78 207 void btrack_perform64(t_btrack *x, t_object *dsp64, double **ins, long numins, double **outs, long numouts, long sampleframes, long flags, void *userparam)
adamstark@78 208 {
adamstark@78 209 t_double *inL = ins[0]; // we get audio for each inlet of the object from the **ins argument
adamstark@78 210 int n = sampleframes;
adamstark@78 211
adamstark@78 212 double audioFrame[n];
adamstark@78 213
adamstark@78 214 for (int i = 0;i < n;i++)
adamstark@78 215 {
adamstark@78 216 audioFrame[i] = (double) inL[i];
adamstark@78 217 }
adamstark@78 218
adamstark@78 219 btrack_process(x,audioFrame);
adamstark@78 220 }
adamstark@78 221
adamstark@78 222 //===========================================================================
adamstark@78 223 void btrack_process(t_btrack *x,double* audioFrame)
adamstark@78 224 {
adamstark@78 225 // process the audio frame
adamstark@78 226 x->b->processAudioFrame(audioFrame);
adamstark@78 227
adamstark@78 228
adamstark@78 229 // if there is a beat in this frame
adamstark@78 230 if (x->b->beatDueInCurrentFrame())
adamstark@78 231 {
adamstark@78 232 // outlet a beat
adamstark@78 233 defer_low((t_object *)x, (method)outlet_beat, NULL, 0, NULL);
adamstark@78 234 }
adamstark@78 235 }
adamstark@78 236
adamstark@78 237 //===========================================================================
adamstark@78 238 void outlet_beat(t_btrack *x, t_symbol *s, long argc, t_atom *argv)
adamstark@78 239 {
adamstark@78 240 // send a bang out of the beat outlet
adamstark@78 241 outlet_bang(x->beat_outlet);
adamstark@78 242
adamstark@78 243 // send the tempo out of the tempo outlet
adamstark@78 244 outlet_float(x->tempo_outlet, (float) x->b->getCurrentTempoEstimate());
adamstark@78 245 }
adamstark@78 246
adamstark@78 247
adamstark@78 248
adamstark@78 249
adamstark@78 250
adamstark@78 251
adamstark@78 252
adamstark@78 253
adamstark@78 254
adamstark@78 255
adamstark@78 256