- Timestamp:
- Sep 15, 2009, 5:02:45 PM (15 years ago)
- Branches:
- feature/autosink, feature/cnn, feature/cnn_org, feature/constantq, feature/crepe, feature/crepe_org, feature/pitchshift, feature/pydocstrings, feature/timestretch, fix/ffmpeg5, master, pitchshift, sampler, timestretch, yinfft+
- Children:
- 06cae6c
- Parents:
- 6f1727f
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/tempo/beattracking.c
r6f1727f r7bf3dcb 1 1 /* 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 2 Copyright (C) 2005 Matthew Davies and Paul Brossier 3 4 This program is free software; you can redistribute it and/or modify 5 it under the terms of the GNU General Public License as published by 6 the Free Software Foundation; either version 2 of the License, or 7 (at your option) any later version. 8 9 This program is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 GNU General Public License for more details. 13 14 You should have received a copy of the GNU General Public License 15 along with this program; if not, write to the Free Software 16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 17 17 18 18 */ … … 23 23 #include "tempo/beattracking.h" 24 24 25 uint_t fvec_gettimesig(fvec_t * acf, uint_t acflen, uint_t gp); 26 void aubio_beattracking_checkstate(aubio_beattracking_t * bt); 27 28 struct _aubio_beattracking_t { 29 fvec_t * rwv; /** rayleigh weighting for beat period in general model */ 30 fvec_t * dfwv; /** exponential weighting for beat alignment in general model */ 31 fvec_t * gwv; /** gaussian weighting for beat period in context dependant model */ 32 fvec_t * phwv; /** gaussian weighting for beat alignment in context dependant model */ 33 fvec_t * dfrev; /** reversed onset detection function */ 34 fvec_t * acf; /** vector for autocorrelation function (of current detection function frame) */ 35 fvec_t * acfout; /** store result of passing acf through s.i.c.f.b. */ 36 fvec_t * phout; 37 uint_t timesig; /** time signature of input, set to zero until context dependent model activated */ 38 uint_t step; 39 uint_t rayparam; /** Rayleigh parameter */ 40 smpl_t lastbeat; 41 sint_t counter; 42 uint_t flagstep; 43 smpl_t g_var; 44 smpl_t gp; 45 smpl_t bp; 46 smpl_t rp; 47 smpl_t rp1; 48 smpl_t rp2; 25 uint_t fvec_gettimesig (fvec_t * acf, uint_t acflen, uint_t gp); 26 void aubio_beattracking_checkstate (aubio_beattracking_t * bt); 27 28 struct _aubio_beattracking_t 29 { 30 fvec_t *rwv; /** rayleigh weighting for beat period in general model */ 31 fvec_t *dfwv; /** exponential weighting for beat alignment in general model */ 32 fvec_t *gwv; /** gaussian weighting for beat period in context dependant model */ 33 fvec_t *phwv; /** gaussian weighting for beat alignment in context dependant model */ 34 fvec_t *dfrev; /** reversed onset detection function */ 35 fvec_t *acf; /** vector for autocorrelation function (of current detection function frame) */ 36 fvec_t *acfout; /** store result of passing acf through s.i.c.f.b. */ 37 fvec_t *phout; 38 uint_t timesig; /** time signature of input, set to zero until context dependent model activated */ 39 uint_t step; 40 uint_t rayparam; /** Rayleigh parameter */ 41 smpl_t lastbeat; 42 sint_t counter; 43 uint_t flagstep; 44 smpl_t g_var; 45 smpl_t gp; 46 smpl_t bp; 47 smpl_t rp; 48 smpl_t rp1; 49 smpl_t rp2; 49 50 }; 50 51 51 aubio_beattracking_t * new_aubio_beattracking(uint_t winlen, 52 uint_t channels) { 53 54 aubio_beattracking_t * p = AUBIO_NEW(aubio_beattracking_t); 55 uint_t i = 0; 56 /* parameter for rayleigh weight vector - sets preferred tempo to 57 * 120bpm [43] */ 58 smpl_t rayparam = 48./512. * winlen; 59 smpl_t dfwvnorm = EXP((LOG(2.0)/rayparam)*(winlen+2)); 60 /** length over which beat period is found [128] */ 61 uint_t laglen = winlen/4; 62 /** step increment - both in detection function samples -i.e. 11.6ms or 63 * 1 onset frame [128] */ 64 uint_t step = winlen/4; /* 1.5 seconds */ 65 66 p->lastbeat = 0; 67 p->counter = 0; 68 p->flagstep = 0; 69 p->g_var = 3.901; // constthresh empirically derived! 70 p->rp = 1; 71 p->gp = 0; 72 73 p->rayparam = rayparam; 74 p->step = step; 75 p->rwv = new_fvec(laglen,1); 76 p->gwv = new_fvec(laglen,1); 77 p->dfwv = new_fvec(winlen,1); 78 p->dfrev = new_fvec(winlen,channels); 79 p->acf = new_fvec(winlen,channels); 80 p->acfout = new_fvec(laglen,channels); 81 p->phwv = new_fvec(2*laglen,1); 82 p->phout = new_fvec(winlen,channels); 83 84 p->timesig = 0; 85 86 /* exponential weighting, dfwv = 0.5 when i = 43 */ 87 for (i=0;i<winlen;i++) { 88 p->dfwv->data[0][i] = (EXP((LOG(2.0)/rayparam)*(i+1))) 89 / dfwvnorm; 90 } 91 92 for (i=0;i<(laglen);i++){ 93 p->rwv->data[0][i] = ((smpl_t)(i+1.) / SQR((smpl_t)rayparam)) * 94 EXP((-SQR((smpl_t)(i+1.)) / (2.*SQR((smpl_t)rayparam)))); 52 aubio_beattracking_t * 53 new_aubio_beattracking (uint_t winlen, uint_t channels) 54 { 55 56 aubio_beattracking_t *p = AUBIO_NEW (aubio_beattracking_t); 57 uint_t i = 0; 58 /* parameter for rayleigh weight vector - sets preferred tempo to 59 * 120bpm [43] */ 60 smpl_t rayparam = 48. / 512. * winlen; 61 smpl_t dfwvnorm = EXP ((LOG (2.0) / rayparam) * (winlen + 2)); 62 /* length over which beat period is found [128] */ 63 uint_t laglen = winlen / 4; 64 /* step increment - both in detection function samples -i.e. 11.6ms or 65 * 1 onset frame [128] */ 66 uint_t step = winlen / 4; /* 1.5 seconds */ 67 68 p->lastbeat = 0; 69 p->counter = 0; 70 p->flagstep = 0; 71 p->g_var = 3.901; // constthresh empirically derived! 72 p->rp = 1; 73 p->gp = 0; 74 75 p->rayparam = rayparam; 76 p->step = step; 77 p->rwv = new_fvec (laglen, 1); 78 p->gwv = new_fvec (laglen, 1); 79 p->dfwv = new_fvec (winlen, 1); 80 p->dfrev = new_fvec (winlen, channels); 81 p->acf = new_fvec (winlen, channels); 82 p->acfout = new_fvec (laglen, channels); 83 p->phwv = new_fvec (2 * laglen, 1); 84 p->phout = new_fvec (winlen, channels); 85 86 p->timesig = 0; 87 88 /* exponential weighting, dfwv = 0.5 when i = 43 */ 89 for (i = 0; i < winlen; i++) { 90 p->dfwv->data[0][i] = (EXP ((LOG (2.0) / rayparam) * (i + 1))) 91 / dfwvnorm; 92 } 93 94 for (i = 0; i < (laglen); i++) { 95 p->rwv->data[0][i] = ((smpl_t) (i + 1.) / SQR ((smpl_t) rayparam)) * 96 EXP ((-SQR ((smpl_t) (i + 1.)) / (2. * SQR ((smpl_t) rayparam)))); 97 } 98 99 return p; 100 101 } 102 103 void 104 del_aubio_beattracking (aubio_beattracking_t * p) 105 { 106 del_fvec (p->rwv); 107 del_fvec (p->gwv); 108 del_fvec (p->dfwv); 109 del_fvec (p->dfrev); 110 del_fvec (p->acf); 111 del_fvec (p->acfout); 112 del_fvec (p->phwv); 113 del_fvec (p->phout); 114 AUBIO_FREE (p); 115 } 116 117 118 void 119 aubio_beattracking_do (aubio_beattracking_t * bt, fvec_t * dfframe, 120 fvec_t * output) 121 { 122 123 uint_t i, k; 124 uint_t step = bt->step; 125 uint_t laglen = bt->rwv->length; 126 uint_t winlen = bt->dfwv->length; 127 uint_t maxindex = 0; 128 //number of harmonics in shift invariant comb filterbank 129 uint_t numelem = 4; 130 131 smpl_t phase; // beat alignment (step - lastbeat) 132 smpl_t beat; // beat position 133 smpl_t bp; // beat period 134 uint_t a, b; // used to build shift invariant comb filterbank 135 uint_t kmax; // number of elements used to find beat phase 136 137 /* copy dfframe, apply detection function weighting, and revert */ 138 fvec_copy (dfframe, bt->dfrev); 139 fvec_weight (bt->dfrev, bt->dfwv); 140 fvec_rev (bt->dfrev); 141 142 /* compute autocorrelation function */ 143 aubio_autocorr (dfframe, bt->acf); 144 145 /* if timesig is unknown, use metrically unbiased version of filterbank */ 146 if (!bt->timesig) { 147 numelem = 4; 148 } else { 149 numelem = bt->timesig; 150 } 151 152 /* first and last output values are left intentionally as zero */ 153 fvec_zeros (bt->acfout); 154 155 /* compute shift invariant comb filterbank */ 156 for (i = 1; i < laglen - 1; i++) { 157 for (a = 1; a <= numelem; a++) { 158 for (b = (1 - a); b < a; b++) { 159 bt->acfout->data[0][i] += bt->acf->data[0][a * (i + 1) + b - 1] 160 * 1. / (2. * a - 1.); 161 } 162 } 163 } 164 /* apply Rayleigh weight */ 165 fvec_weight (bt->acfout, bt->rwv); 166 167 /* find non-zero Rayleigh period */ 168 maxindex = vec_max_elem (bt->acfout); 169 bt->rp = maxindex ? vec_quadint (bt->acfout, maxindex, 1) : 1; 170 //rp = (maxindex==127) ? 43 : maxindex; //rayparam 171 bt->rp = (maxindex == bt->acfout->length - 1) ? bt->rayparam : maxindex; //rayparam 172 173 /* activate biased filterbank */ 174 aubio_beattracking_checkstate (bt); 175 #if 0 // debug metronome mode 176 bt->bp = 36.9142; 177 #endif 178 bp = bt->bp; 179 /* end of biased filterbank */ 180 181 182 /* deliberate integer operation, could be set to 3 max eventually */ 183 kmax = FLOOR (winlen / bp); 184 185 /* initialize output */ 186 fvec_zeros (bt->phout); 187 for (i = 0; i < bp; i++) { 188 for (k = 0; k < kmax; k++) { 189 bt->phout->data[0][i] += bt->dfrev->data[0][i + (uint_t) ROUND (bp * k)]; 190 } 191 } 192 fvec_weight (bt->phout, bt->phwv); 193 194 /* find Rayleigh period */ 195 maxindex = vec_max_elem (bt->phout); 196 if (maxindex == winlen) 197 maxindex = 0; 198 phase = 1. + vec_quadint (bt->phout, maxindex, 1); 199 #if 0 // debug metronome mode 200 phase = step - bt->lastbeat; 201 #endif 202 203 /* reset output */ 204 fvec_zeros (output); 205 206 i = 1; 207 beat = bp - phase; 208 /* start counting the beats */ 209 if (beat >= 0) { 210 output->data[0][i] = beat; 211 i++; 212 } 213 214 while (beat + bp <= step) { 215 beat += bp; 216 output->data[0][i] = beat; 217 i++; 218 } 219 220 bt->lastbeat = beat; 221 /* store the number of beat found in this frame as the first element */ 222 output->data[0][0] = i; 223 } 224 225 uint_t 226 fvec_gettimesig (fvec_t * acf, uint_t acflen, uint_t gp) 227 { 228 sint_t k = 0; 229 smpl_t three_energy = 0., four_energy = 0.; 230 if (acflen > 6 * gp + 2) { 231 for (k = -2; k < 2; k++) { 232 three_energy += acf->data[0][3 * gp + k]; 233 four_energy += acf->data[0][4 * gp + k]; 234 } 235 } else { 236 /*Expanded to be more accurate in time sig estimation */ 237 for (k = -2; k < 2; k++) { 238 three_energy += acf->data[0][3 * gp + k] + acf->data[0][6 * gp + k]; 239 four_energy += acf->data[0][4 * gp + k] + acf->data[0][2 * gp + k]; 240 } 241 } 242 return (three_energy > four_energy) ? 3 : 4; 243 } 244 245 void 246 aubio_beattracking_checkstate (aubio_beattracking_t * bt) 247 { 248 uint_t i, j, a, b; 249 uint_t flagconst = 0; 250 sint_t counter = bt->counter; 251 uint_t flagstep = bt->flagstep; 252 smpl_t gp = bt->gp; 253 smpl_t bp = bt->bp; 254 smpl_t rp = bt->rp; 255 smpl_t rp1 = bt->rp1; 256 smpl_t rp2 = bt->rp2; 257 uint_t laglen = bt->rwv->length; 258 uint_t acflen = bt->acf->length; 259 uint_t step = bt->step; 260 fvec_t *acf = bt->acf; 261 fvec_t *acfout = bt->acfout; 262 263 if (gp) { 264 // doshiftfbank again only if context dependent model is in operation 265 //acfout = doshiftfbank(acf,gwv,timesig,laglen,acfout); 266 //don't need acfout now, so can reuse vector 267 // gwv is, in first loop, definitely all zeros, but will have 268 // proper values when context dependent model is activated 269 fvec_zeros (acfout); 270 for (i = 1; i < laglen - 1; i++) { 271 for (a = 1; a <= bt->timesig; a++) { 272 for (b = (1 - a); b < a; b++) { 273 acfout->data[0][i] += acf->data[0][a * (i + 1) + b - 1]; 95 274 } 96 97 return p; 98 99 } 100 101 void del_aubio_beattracking(aubio_beattracking_t * p) { 102 del_fvec(p->rwv); 103 del_fvec(p->gwv); 104 del_fvec(p->dfwv); 105 del_fvec(p->dfrev); 106 del_fvec(p->acf); 107 del_fvec(p->acfout); 108 del_fvec(p->phwv); 109 del_fvec(p->phout); 110 AUBIO_FREE(p); 111 } 112 113 114 void aubio_beattracking_do(aubio_beattracking_t * bt, fvec_t * dfframe, fvec_t * output) { 115 116 uint_t i,k; 117 uint_t step = bt->step; 118 uint_t laglen = bt->rwv->length; 119 uint_t winlen = bt->dfwv->length; 120 uint_t maxindex = 0; 121 //number of harmonics in shift invariant comb filterbank 122 uint_t numelem = 4; 123 124 smpl_t phase; // beat alignment (step - lastbeat) 125 smpl_t beat; // beat position 126 smpl_t bp; // beat period 127 uint_t a,b; // used to build shift invariant comb filterbank 128 uint_t kmax; // number of elements used to find beat phase 129 130 /* copy dfframe, apply detection function weighting, and revert */ 131 fvec_copy(dfframe, bt->dfrev); 132 fvec_weight(bt->dfrev, bt->dfwv); 133 fvec_rev(bt->dfrev); 134 135 /* compute autocorrelation function */ 136 aubio_autocorr(dfframe,bt->acf); 137 138 /* if timesig is unknown, use metrically unbiased version of filterbank */ 139 if(!bt->timesig) { 140 numelem = 4; 141 } else { 142 numelem = bt->timesig; 143 } 144 145 /* first and last output values are left intentionally as zero */ 146 fvec_zeros(bt->acfout); 147 148 /* compute shift invariant comb filterbank */ 149 for(i=1;i<laglen-1;i++){ 150 for (a=1; a<=numelem; a++){ 151 for(b=(1-a); b<a; b++){ 152 bt->acfout->data[0][i] += bt->acf->data[0][a*(i+1)+b-1] 153 * 1./(2.*a-1.); 154 } 155 } 156 } 157 /* apply Rayleigh weight */ 158 fvec_weight(bt->acfout, bt->rwv); 159 160 /* find non-zero Rayleigh period */ 161 maxindex = vec_max_elem(bt->acfout); 162 bt->rp = maxindex ? vec_quadint(bt->acfout, maxindex, 1) : 1; 163 //rp = (maxindex==127) ? 43 : maxindex; //rayparam 164 bt->rp = (maxindex==bt->acfout->length-1) ? bt->rayparam : maxindex; //rayparam 165 166 /* activate biased filterbank */ 167 aubio_beattracking_checkstate(bt); 168 #if 0 // debug metronome mode 169 bt->bp = 36.9142; 170 #endif 171 bp = bt->bp; 172 /* end of biased filterbank */ 173 174 175 /* deliberate integer operation, could be set to 3 max eventually */ 176 kmax = FLOOR(winlen/bp); 177 178 /* initialize output */ 179 fvec_zeros(bt->phout); 180 for(i=0;i<bp;i++){ 181 for(k=0;k<kmax;k++){ 182 bt->phout->data[0][i] += bt->dfrev->data[0][i+(uint_t)ROUND(bp*k)]; 183 } 184 } 185 fvec_weight(bt->phout, bt->phwv); 186 187 /* find Rayleigh period */ 188 maxindex = vec_max_elem(bt->phout); 189 if (maxindex == winlen) maxindex = 0; 190 phase = 1. + vec_quadint(bt->phout, maxindex, 1); 191 #if 0 // debug metronome mode 192 phase = step - bt->lastbeat; 193 #endif 194 195 /* reset output */ 196 fvec_zeros(output); 197 198 i = 1; 199 beat = bp - phase; 200 /* start counting the beats */ 201 if(beat >= 0) { 202 output->data[0][i] = beat; 203 i++; 204 } 205 206 while( beat + bp <= step) { 207 beat += bp; 208 output->data[0][i] = beat; 209 i++; 210 } 211 212 bt->lastbeat = beat; 213 /* store the number of beat found in this frame as the first element */ 214 output->data[0][0] = i; 215 } 216 217 uint_t fvec_gettimesig(fvec_t * acf, uint_t acflen, uint_t gp){ 218 sint_t k = 0; 219 smpl_t three_energy = 0., four_energy = 0.; 220 if( acflen > 6 * gp + 2 ){ 221 for(k=-2;k<2;k++){ 222 three_energy += acf->data[0][3*gp+k]; 223 four_energy += acf->data[0][4*gp+k]; 224 } 225 } 226 else{ /*Expanded to be more accurate in time sig estimation*/ 227 for(k=-2;k<2;k++){ 228 three_energy += acf->data[0][3*gp+k]+acf->data[0][6*gp+k]; 229 four_energy += acf->data[0][4*gp+k]+acf->data[0][2*gp+k]; 230 } 231 } 232 return (three_energy > four_energy) ? 3 : 4; 233 } 234 235 void aubio_beattracking_checkstate(aubio_beattracking_t * bt) { 236 uint_t i,j,a,b; 237 uint_t flagconst = 0; 238 sint_t counter = bt->counter; 239 uint_t flagstep = bt->flagstep; 240 smpl_t gp = bt->gp; 241 smpl_t bp = bt->bp; 242 smpl_t rp = bt->rp; 243 smpl_t rp1 = bt->rp1; 244 smpl_t rp2 = bt->rp2; 245 uint_t laglen = bt->rwv->length; 246 uint_t acflen = bt->acf->length; 247 uint_t step = bt->step; 248 fvec_t * acf = bt->acf; 249 fvec_t * acfout = bt->acfout; 250 251 if (gp) { 252 // doshiftfbank again only if context dependent model is in operation 253 //acfout = doshiftfbank(acf,gwv,timesig,laglen,acfout); 254 //don't need acfout now, so can reuse vector 255 // gwv is, in first loop, definitely all zeros, but will have 256 // proper values when context dependent model is activated 257 fvec_zeros(acfout); 258 for(i=1;i<laglen-1;i++){ 259 for (a=1;a<=bt->timesig;a++){ 260 for(b=(1-a);b<a;b++){ 261 acfout->data[0][i] += acf->data[0][a*(i+1)+b-1]; 262 } 263 } 264 } 265 fvec_weight(acfout, bt->gwv); 266 gp = vec_quadint(acfout, vec_max_elem(acfout), 1); 267 /* 268 while(gp<32) gp =gp*2; 269 while(gp>64) gp = gp/2; 270 */ 271 } else { 272 //still only using general model 273 gp = 0; 274 } 275 276 //now look for step change - i.e. a difference between gp and rp that 277 // is greater than 2*constthresh - always true in first case, since gp = 0 278 if(counter == 0){ 279 if(ABS(gp - rp) > 2.*bt->g_var) { 280 flagstep = 1; // have observed step change. 281 counter = 3; // setup 3 frame counter 282 } else { 283 flagstep = 0; 284 } 285 } 286 287 //i.e. 3rd frame after flagstep initially set 288 if (counter==1 && flagstep==1) { 289 //check for consistency between previous beatperiod values 290 if(ABS(2.*rp - rp1 -rp2) < bt->g_var) { 291 //if true, can activate context dependent model 292 flagconst = 1; 293 counter = 0; // reset counter and flagstep 294 } else { 295 //if not consistent, then don't flag consistency! 296 flagconst = 0; 297 counter = 2; // let it look next time 298 } 299 } else if (counter > 0) { 300 //if counter doesn't = 1, 301 counter = counter-1; 302 } 303 304 rp2 = rp1; rp1 = rp; 305 306 if (flagconst) { 307 /* first run of new hypothesis */ 308 gp = rp; 309 bt->timesig = fvec_gettimesig(acf,acflen, gp); 310 for(j=0;j<laglen;j++) 311 bt->gwv->data[0][j] = EXP(-.5*SQR((smpl_t)(j+1.-gp))/SQR(bt->g_var)); 312 flagconst = 0; 313 bp = gp; 314 /* flat phase weighting */ 315 fvec_ones(bt->phwv); 316 } else if (bt->timesig) { 317 /* context dependant model */ 318 bp = gp; 319 /* gaussian phase weighting */ 320 if (step > bt->lastbeat) { 321 for(j=0;j<2*laglen;j++) { 322 bt->phwv->data[0][j] = EXP(-.5*SQR((smpl_t)(1.+j-step+bt->lastbeat))/(bp/8.)); 323 } 324 } else { 325 //AUBIO_DBG("NOT using phase weighting as step is %d and lastbeat %d \n", 326 // step,bt->lastbeat); 327 fvec_ones(bt->phwv); 328 } 329 } else { 330 /* initial state */ 331 bp = rp; 332 /* flat phase weighting */ 333 fvec_ones(bt->phwv); 334 } 335 336 /* do some further checks on the final bp value */ 337 338 /* if tempo is > 206 bpm, half it */ 339 while (bp < 25) { 340 //AUBIO_DBG("warning, doubling the beat period from %d\n", bp); 341 //AUBIO_DBG("warning, halving the tempo from %f\n", 60.*samplerate/hopsize/bp); 342 bp = bp*2; 343 } 344 345 //AUBIO_DBG("tempo:\t%3.5f bpm | ", 5168./bp); 346 347 /* smoothing */ 348 //bp = (uint_t) (0.8 * (smpl_t)bp + 0.2 * (smpl_t)bp2); 349 //AUBIO_DBG("tempo:\t%3.5f bpm smoothed | bp2 %d | bp %d | ", 5168./bp, bp2, bp); 350 //bp2 = bp; 351 //AUBIO_DBG("time signature: %d \n", bt->timesig); 352 bt->counter = counter; 353 bt->flagstep = flagstep; 354 bt->gp = gp; 355 bt->bp = bp; 356 bt->rp1 = rp1; 357 bt->rp2 = rp2; 358 359 } 360 361 smpl_t aubio_beattracking_get_bpm(aubio_beattracking_t * bt) { 362 if (bt->timesig != 0 && bt->counter == 0 && bt->flagstep == 0) { 363 return 5168. / vec_quadint(bt->acfout, bt->bp, 1); 364 } else { 365 return 0.; 366 } 367 } 368 369 smpl_t aubio_beattracking_get_confidence(aubio_beattracking_t * bt) { 370 if (bt->gp) return vec_max(bt->acfout); 371 else return 0.; 372 } 275 } 276 } 277 fvec_weight (acfout, bt->gwv); 278 gp = vec_quadint (acfout, vec_max_elem (acfout), 1); 279 /* 280 while(gp<32) gp =gp*2; 281 while(gp>64) gp = gp/2; 282 */ 283 } else { 284 //still only using general model 285 gp = 0; 286 } 287 288 //now look for step change - i.e. a difference between gp and rp that 289 // is greater than 2*constthresh - always true in first case, since gp = 0 290 if (counter == 0) { 291 if (ABS (gp - rp) > 2. * bt->g_var) { 292 flagstep = 1; // have observed step change. 293 counter = 3; // setup 3 frame counter 294 } else { 295 flagstep = 0; 296 } 297 } 298 //i.e. 3rd frame after flagstep initially set 299 if (counter == 1 && flagstep == 1) { 300 //check for consistency between previous beatperiod values 301 if (ABS (2. * rp - rp1 - rp2) < bt->g_var) { 302 //if true, can activate context dependent model 303 flagconst = 1; 304 counter = 0; // reset counter and flagstep 305 } else { 306 //if not consistent, then don't flag consistency! 307 flagconst = 0; 308 counter = 2; // let it look next time 309 } 310 } else if (counter > 0) { 311 //if counter doesn't = 1, 312 counter = counter - 1; 313 } 314 315 rp2 = rp1; 316 rp1 = rp; 317 318 if (flagconst) { 319 /* first run of new hypothesis */ 320 gp = rp; 321 bt->timesig = fvec_gettimesig (acf, acflen, gp); 322 for (j = 0; j < laglen; j++) 323 bt->gwv->data[0][j] = 324 EXP (-.5 * SQR ((smpl_t) (j + 1. - gp)) / SQR (bt->g_var)); 325 flagconst = 0; 326 bp = gp; 327 /* flat phase weighting */ 328 fvec_ones (bt->phwv); 329 } else if (bt->timesig) { 330 /* context dependant model */ 331 bp = gp; 332 /* gaussian phase weighting */ 333 if (step > bt->lastbeat) { 334 for (j = 0; j < 2 * laglen; j++) { 335 bt->phwv->data[0][j] = 336 EXP (-.5 * SQR ((smpl_t) (1. + j - step + 337 bt->lastbeat)) / (bp / 8.)); 338 } 339 } else { 340 //AUBIO_DBG("NOT using phase weighting as step is %d and lastbeat %d \n", 341 // step,bt->lastbeat); 342 fvec_ones (bt->phwv); 343 } 344 } else { 345 /* initial state */ 346 bp = rp; 347 /* flat phase weighting */ 348 fvec_ones (bt->phwv); 349 } 350 351 /* do some further checks on the final bp value */ 352 353 /* if tempo is > 206 bpm, half it */ 354 while (bp < 25) { 355 //AUBIO_DBG("warning, doubling the beat period from %d\n", bp); 356 //AUBIO_DBG("warning, halving the tempo from %f\n", 60.*samplerate/hopsize/bp); 357 bp = bp * 2; 358 } 359 360 //AUBIO_DBG("tempo:\t%3.5f bpm | ", 5168./bp); 361 362 /* smoothing */ 363 //bp = (uint_t) (0.8 * (smpl_t)bp + 0.2 * (smpl_t)bp2); 364 //AUBIO_DBG("tempo:\t%3.5f bpm smoothed | bp2 %d | bp %d | ", 5168./bp, bp2, bp); 365 //bp2 = bp; 366 //AUBIO_DBG("time signature: %d \n", bt->timesig); 367 bt->counter = counter; 368 bt->flagstep = flagstep; 369 bt->gp = gp; 370 bt->bp = bp; 371 bt->rp1 = rp1; 372 bt->rp2 = rp2; 373 } 374 375 smpl_t 376 aubio_beattracking_get_bpm (aubio_beattracking_t * bt) 377 { 378 if (bt->timesig != 0 && bt->counter == 0 && bt->flagstep == 0) { 379 return 5168. / vec_quadint (bt->acfout, bt->bp, 1); 380 } else { 381 return 0.; 382 } 383 } 384 385 smpl_t 386 aubio_beattracking_get_confidence (aubio_beattracking_t * bt) 387 { 388 if (bt->gp) { 389 return vec_max (bt->acfout); 390 } else { 391 return 0.; 392 } 393 }
Note: See TracChangeset
for help on using the changeset viewer.