1 /*
2 SuperCollider real time audio synthesis system
3 Copyright (c) 2002 James McCartney. All rights reserved.
4 http://www.audiosynth.com
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21 //This file is part of The BBCut Library. Copyright (C) 2001 Nick M.Collins distributed under the terms of the GNU General Public License full notice in file BBCutLibrary.help
22
23 //last revisions pre release 1.0 Nick Collins 15 June 2004
24
25 #include "SC_PlugIn.h"
26 #include "SC_fftlib.h"
27 #include <stdio.h>
28
29 //helpful constants
30 #define PI 3.1415926535898f
31 #define TWOPI 6.28318530717952646f
32
33 //FFT data
34 #define N 1024 //FFT size
35 #define NOVER2 512 //FFT size
36 #define NOVER4 256 //FFT size
37 #define OVERLAP 512
38 #define OVERLAPINDEX 512
39 #define HOPSIZE 512
40 #define FS 44100 //assumes fixed sampling rate
41 #define FRAMESR 86.1328
42 #define FRAMEPERIOD 0.01161 //seconds
43
44 //algorithm quantities NR tempo hypotheses, ND num phase hypotheses
45
46 //used to be TEMPOLOW 90 TEMPOHIGH 180 TEMPOSTEP 0.9 INTEGRATIONTIME 3.4 LOUDNESSFRAMESSTORED 293
47 //used to be TEMPOLOW 80 TEMPOHIGH 200 TEMPOSTEP 1.2 INTEGRATIONTIME 4 LOUDNESSFRAMESSTORED 350
48 #define TEMPOLOW 90
49 //#define TEMPOHIGH 190
50 #define NR 100
51 #define ND 20
52 #define NDOVER2 10
53 #define NRD 2000
54 #define NDRECIP 0.05
55 #define TEMPOSTEP 1.0
56 #define INTEGRATIONTIME 3.4
57 //#define NUMBEATS 4
58
59 //MINPERIOD 0.33 MAXPERIOD 0.66 MINDIFF 28 MAXDIFF 58
60 //MINPERIOD 0.3 MAXPERIOD 0.75 MINDIFF 25 MAXDIFF 65
61 #define MINPERIOD 0.315
62 #define MAXPERIOD 0.66
63 #define MINDIFF 27
64 #define MAXDIFF 58
65
66
67 //ceil(INTEGRATIONTIME*FRAMESR)
68 #define LOUDNESSFRAMESSTORED 293
69 //can calculate after frame 293 then
70
71 //these values assume TEMPOLOW 90 and sample rate 44100 with 1024 FFT
72 //#define FFTSTOREMEM 350
73 //#define FFTSTORESIZE 8400
74 //about 4 seconds of FFT powers stored between 0 and 1000 Hz (bin indices 1 to 24 for aforementioned FFT size)
75
76 //about once per second, now made quicker update
77
78 //old values SKIP 28 TIMEELAPSED 0.3250794
79 #define SKIP 24
80 //28/86.1328
81 #define TIMEELAPSED 0.2786395
82 //just quicker than one beat at 180bpm 1.9969164 //0.9984582
83
84 #define tempoconsistency 2
85 #define phaseconsistency 2
86 //#define tempotestvalue 0.25
87 //#define phasetestvalue 0.4
88
89 #define MAXONSETS 50
90
91 //const int toptempi=5;
92
93 const float subbeats[8]= {0.0,0.5,1.0,1.5,2.0,2.5,3.0,3.5};
94 //const float subbeats[2][16]= {{0.0,0.25,0.5,0.75,1.0,1.25,1.5,1.75,2.0,2.25,2.5,2.75,3.0,3.25,3.5,3.75},{0.0,0.32,0.5,0.82,1.0,1.32,1.5,1.82,2.0,2.32,2.5,2.82,3.0,3.32,3.5,3.82}};
95 //const float subbeats[16]={0.0,0.25,0.5,0.75,1.0,1.25,1.5,1.75,2.0,2.25,2.5,2.75,3.0,3.25,3.5,3.75};
96 const float beats[4]= {0.0,1.0,2.0,3.0};
97
98 //weights
99 const float sbtemplate[8]= {1.0,0.5,1.0,0.5,1.0,0.5,1.0,0.5};
100
101 //could be different templates based on a parameter
102 //const float sbtemplate[16]= {1.0,0.1,0.8,0.2,1.0,0.1,0.8,0.2,1.0,0.1,0.8,0.2,1.0,0.1,0.8,0.2};
103
104 //phase matching conditions
105 //float required[4]={1.0, 0.5, 0.3, 0.5};
106
107
108 //use integrationtime for maxwindow
109 //#define MAXWINDOW //(numbeats+1)*lowperiod;
110
111
112 //for hanning window, constructed in plugin initialisation
113 float hanning[N];
114
115
116 int eqlbandbins[43]= {1,2,3,4,5,6,7,8,9,11,13,15,17,19,22,25,28,32,36,41,46,52,58,65,73,82,92,103,116,129,144,161,180,201,225,251,280,312,348,388,433,483,513};
117 int eqlbandsizes[42]= {1,1,1,1,1,1,1,1,2,2,2,2,2,3,3,3,4,4,5,5,6,6,7,8,9,10,11,13,13,15,17,19,21,24,26,29,32,36,40,45,50,30};
118
119 //this loudness conversion was removed since it worked better without transient detection but just using current energy
120 //float contours[42][11]= {{ 47.88, 59.68, 68.55, 75.48, 81.71, 87.54, 93.24, 98.84,104.44,109.94,115.31},{ 29.04, 41.78, 51.98, 60.18, 67.51, 74.54, 81.34, 87.97, 94.61,101.21,107.74},{ 20.72, 32.83, 43.44, 52.18, 60.24, 67.89, 75.34, 82.70, 89.97, 97.23,104.49},{ 15.87, 27.14, 37.84, 46.94, 55.44, 63.57, 71.51, 79.34, 87.14, 94.97,102.37},{ 12.64, 23.24, 33.91, 43.27, 52.07, 60.57, 68.87, 77.10, 85.24, 93.44,100.90},{ 10.31, 20.43, 31.03, 40.54, 49.59, 58.33, 66.89, 75.43, 83.89, 92.34,100.80},{ 8.51, 18.23, 28.83, 38.41, 47.65, 56.59, 65.42, 74.16, 82.89, 91.61,100.33},{ 7.14, 16.55, 27.11, 36.79, 46.16, 55.27, 64.29, 73.24, 82.15, 91.06, 99.97},{ 5.52, 14.58, 25.07, 34.88, 44.40, 53.73, 62.95, 72.18, 81.31, 90.44, 99.57},{ 3.98, 12.69, 23.10, 32.99, 42.69, 52.27, 61.66, 71.15, 80.54, 89.93, 99.31},{ 2.99, 11.43, 21.76, 31.73, 41.49, 51.22, 60.88, 70.51, 80.11, 89.70, 99.30},{ 2.35, 10.58, 20.83, 30.86, 40.68, 50.51, 60.33, 70.08, 79.83, 89.58, 99.32},{ 2.05, 10.12, 20.27, 30.35, 40.22, 50.10, 59.97, 69.82, 79.67, 89.52, 99.38},{ 2.00, 9.93, 20.00, 30.07, 40.00, 49.93, 59.87, 69.80, 79.73, 89.67, 99.60},{ 2.19, 10.00, 20.00, 30.00, 40.00, 50.00, 59.99, 69.99, 79.98, 89.98, 99.97},{ 2.71, 10.56, 20.61, 30.71, 40.76, 50.81, 60.86, 70.96, 81.01, 91.06,101.17},{ 3.11, 11.05, 21.19, 31.41, 41.53, 51.64, 61.75, 71.95, 82.05, 92.15,102.33},{ 2.39, 10.69, 21.14, 31.52, 41.73, 51.95, 62.11, 72.31, 82.46, 92.56,102.59},{ 1.50, 10.11, 20.82, 31.32, 41.62, 51.92, 62.12, 72.32, 82.52, 92.63,102.56},{ -0.17, 8.50, 19.27, 29.77, 40.07, 50.37, 60.57, 70.77, 80.97, 91.13,101.23},{ -1.80, 6.96, 17.77, 28.29, 38.61, 48.91, 59.13, 69.33, 79.53, 89.71, 99.86},{ -3.42, 5.49, 16.36, 26.94, 37.31, 47.61, 57.88, 68.08, 78.28, 88.41, 98.39},{ -4.73, 4.38, 15.34, 25.99, 36.39, 46.71, 57.01, 67.21, 77.41, 87.51, 97.41},{ -5.73, 3.63, 14.74, 25.48, 35.88, 46.26, 56.56, 66.76, 76.96, 87.06, 96.96},{ -6.24, 3.33, 14.59, 25.39, 35.84, 46.22, 56.52, 66.72, 76.92, 87.04, 97.00},{ -6.09, 3.62, 15.03, 25.83, 36.37, 46.70, 57.00, 67.20, 77.40, 87.57, 97.68},{ -5.32, 4.44, 15.90, 26.70, 37.28, 47.60, 57.90, 68.10, 78.30, 88.52, 98.78},{ -3.49, 6.17, 17.52, 28.32, 38.85, 49.22, 59.52, 69.72, 79.92, 90.20,100.61},{ -0.81, 8.58, 19.73, 30.44, 40.90, 51.24, 61.52, 71.69, 81.87, 92.15,102.63},{ 2.91, 11.82, 22.64, 33.17, 43.53, 53.73, 63.96, 74.09, 84.22, 94.45,104.89},{ 6.68, 15.19, 25.71, 36.03, 46.25, 56.31, 66.45, 76.49, 86.54, 96.72,107.15},{ 10.43, 18.65, 28.94, 39.02, 49.01, 58.98, 68.93, 78.78, 88.69, 98.83,109.36},{ 13.56, 21.65, 31.78, 41.68, 51.45, 61.31, 71.07, 80.73, 90.48,100.51,111.01},{ 14.36, 22.91, 33.19, 43.09, 52.71, 62.37, 71.92, 81.38, 90.88,100.56,110.56},{ 15.06, 23.90, 34.23, 44.05, 53.48, 62.90, 72.21, 81.43, 90.65, 99.93,109.34},{ 15.36, 23.90, 33.89, 43.31, 52.40, 61.42, 70.29, 79.18, 88.00, 96.69,105.17},{ 15.60, 23.90, 33.60, 42.70, 51.50, 60.20, 68.70, 77.30, 85.80, 94.00,101.70},{ 15.60, 23.90, 33.60, 42.70, 51.50, 60.20, 68.70, 77.30, 85.80, 94.00,101.70},{ 15.60, 23.90, 33.60, 42.70, 51.50, 60.20, 68.70, 77.30, 85.80, 94.00,101.70},{ 15.60, 23.90, 33.60, 42.70, 51.50, 60.20, 68.70, 77.30, 85.80, 94.00,101.70},{ 15.60, 23.90, 33.60, 42.70, 51.50, 60.20, 68.70, 77.30, 85.80, 94.00,101.70},{ 15.60, 23.90, 33.60, 42.70, 51.50, 60.20, 68.70, 77.30, 85.80, 94.00,101.70}};
121 //double phons[11]={2,10,20,30,40,50,60,70,80,90,100};
122
123
124 extern "C"
125 {
126 }
127
128 InterfaceTable *ft;
129
130
131
132 struct DrumTrack : Unit {
133
134 //FFT data
135 int m_bufWritePos;
136 float * m_prepareFFTBuf;
137 float * m_FFTBuf;
138
139 scfft *m_scfft;
140
141 //time positions
142 long m_frame;
143
144 //loudness measure
145 float m_loudness[LOUDNESSFRAMESSTORED];
146 int m_loudnesscounter;
147 float m_loudbands[40];
148
149 //for bass onset detections
150 float m_bassonsets[LOUDNESSFRAMESSTORED];
151
152 //tempo
153
154 float m_currtempo;
155 float m_lasttempo;
156 float m_tempodiff[tempoconsistency]; //initialise to ones
157 int m_tdindex;
158
159 //phase
160
161 float m_currphase;
162 float m_lastphasewinner;
163 float m_phasediffs[phaseconsistency]; //initialise to ones
164 int m_pdindex;
165
166 //phasor, trigger beat and modulo when >1.0
167 float m_phase, m_phaseperblock;
168
169 //phasor output separate so can have it lock and keep going when don't want to track
170 float m_outputphase, m_outputtempo, m_outputphaseperblock;
171
172 int halftrig;
173 int q1trig;
174 int q2trig;
175
176 //can make twice as many including groove, or just test eighth note positions for now
177
178 //dynamic programming
179 float m_lastscore[40];
180 float m_lastcandidatetempo[10]; //indices
181 float m_lastcandidatephase[40];
182
183 //candidate scores
184 //float m_scores[NRD]; //2000 possibles
185 float m_bestscores[10];
186 float m_besttemposcores[10]; //store tempi
187 float m_bestphasescores[40]; //store phases four for each, always best two and two antiphase
188 float m_phasescores[40]; //store the actual scores for use in the the dyn prog cost function
189
190 //amortization
191 int m_amortisationstate;
192 int m_storeloudnesscounter;
193 float m_scorenorm; //normalise all scores in a sweep by the maximum
194
195 //chord detection- Goto histogramming requires storing fft bins 1 to 24 over last 4 seconds (see workbook 15 dec 04)
196 // float * m_fftstore;
197 // int m_fftstorepos;
198 // int m_fftstoreposhold;
199 // float m_chordhistogram[24];
200 // float m_chordhistogramprev[24];
201 //
202
203
204 //bass/chord normalisation
205 float m_bassmax;
206
207 //,m_chordmax;
208
209 //final consistency requirement
210 float m_prevphase,m_prevtempo;
211 float m_consistency;
212
213
214 //goto onset spotting
215 float * m_powerbuf[3];
216 int m_powerbufcount;
217
218 float m_maxsnaresig;
219 long m_lastsnaredetect;
220
221 float m_maxkicksig;
222 long m_lastkickdetect;
223
224 //0 for nothing, 1 for snare, 2 for kick, same counter as m_loudnesscounter
225 int m_onsets[LOUDNESSFRAMESSTORED];
226 //int onsetposition[50];
227 int m_onsetposition[MAXONSETS]; //no more than this
228 float m_patternphase; //if
229 float m_patternscore;
230 float m_patterntempo;
231
232 float * m_prior;
233
234 int m_debugmode;
235
236 };
237
238
239
240 extern "C"
241 {
242 //required interface functions
243 void DrumTrack_next(DrumTrack *unit, int wrongNumSamples);
244 void DrumTrack_Ctor(DrumTrack *unit);
245 void DrumTrack_Dtor(DrumTrack *unit);
246 }
247
248 //other functions
249 void preparefft(DrumTrack *unit, float* in, int n);
250 void dofft(DrumTrack *unit);
251 void calculateloudness(DrumTrack *unit);
252 void updatetempophase(DrumTrack *unit, float tempowinner,float phasewinner);
253 float phasematchesbassonsets(DrumTrack *unit, float phase, float bps);
254 //float comparechordetect(DrumTrack *unit, float phase, float bps);
255
256 void snaredetection(DrumTrack *unit);
257 void kickdetection(DrumTrack *unit);
258 int findarchetype(DrumTrack *unit, float tempowinner);
259 void testpattern(DrumTrack * unit, int &bestindex, float &bestscore, int &besttempo, int first, int diff, int firstval);
260
261 //amortisation
262 void do100thscoring(DrumTrack *unit,int j);
263 float calcphasediff(float prevphase, float phase, float prevtempo, float tempo);
264 void do40thpath(DrumTrack *unit,int i);
265 void finaldecision(DrumTrack *unit);
266
267 //old
268 void tempoassess(DrumTrack *unit, float *, float *);
269
DrumTrack_Ctor(DrumTrack * unit)270 void DrumTrack_Ctor(DrumTrack* unit) {
271 int i,j;
272
273 unit->m_debugmode=(int)ZIN0(10);
274
275 ////prior//////
276
277 unit->m_prior=NULL;
278
279 World *world = unit->mWorld;
280
281 int bufnum = (int)ZIN0(7);
282
283 //if (bufnum >= world->mNumSndBufs) bufnum = 0;
284
285 //printf("bufnum%d\n",bufnum);
286
287 if (bufnum>=0) {
288 SndBuf *buf = world->mSndBufs + bufnum;
289
290 int priorbufsize = buf->samples;
291
292 if(priorbufsize!=100) {printf("buffer for tempo weightings prior not size 100 bufnum%d\n",bufnum);}
293 else {
294 unit->m_prior= buf->data;
295
296 //for (int h=0; h<100; ++h) {
297 // printf("%f\n",unit->m_prior[h]);
298 //}
299 }
300 }
301
302
303 ////////FFT data///////////
304
305 unit->m_prepareFFTBuf = (float*)RTAlloc(unit->mWorld, N * sizeof(float));
306 unit->m_FFTBuf = (float*)RTAlloc(unit->mWorld, N * sizeof(float));
307 unit->m_bufWritePos = 0;
308
309 //N=1024
310 SCWorld_Allocator alloc(ft, unit->mWorld);
311 //no overlap
312 unit->m_scfft = scfft_create(N, N, kHannWindow, unit->m_FFTBuf, unit->m_FFTBuf, kForward, alloc);
313
314 ////////time positions//////////
315 unit->m_frame=0;
316
317 /////////loudness measure////////
318 unit->m_loudnesscounter=LOUDNESSFRAMESSTORED-1;
319 //zero loudness store
320 for(j=0;j<LOUDNESSFRAMESSTORED;++j) {
321 unit->m_loudness[j]=0.0;
322 unit->m_bassonsets[j]=0.0;
323 }
324
325 //zero previous specific loudness in Bark bands
326 for(j=0;j<40;++j) {
327 unit->m_loudbands[j]=0.0;
328 }
329
330 /////////tempo assess///////////
331 unit->m_currtempo=2;
332 unit->m_lasttempo=2;
333
334 for(j=0;j<tempoconsistency;++j)
335 unit->m_tempodiff[j]=1.0; //if 0.0 biases taking first tempo estimate it can!
336
337 unit->m_tdindex=0;
338
339
340 ////////phase assess///////////
341
342 unit->m_currphase=0.0;
343
344 unit->m_lastphasewinner=0.0;
345
346 for(j=0;j<phaseconsistency;++j)
347 unit->m_phasediffs[j]=1.0; //take first phase you can? No, wait
348
349 unit->m_pdindex=0;
350
351 unit->m_phase=0.0;
352
353 //default of 2bps
354 unit->m_phaseperblock= (unit->mWorld->mFullRate.mBufLength*2)/(FS);
355
356 unit->m_outputphase= unit->m_phase;
357 unit->m_outputtempo= unit->m_currtempo;
358 unit->m_outputphaseperblock= unit->m_phaseperblock;
359
360 unit->mCalcFunc = (UnitCalcFunc)&DrumTrack_next;
361
362 unit->halftrig=0;
363 unit->q1trig=0;
364 unit->q2trig=0;
365
366 //amortisation
367 unit->m_amortisationstate=142; //off
368
369 //dyn prog initialise playing field
370 float * lastscore= unit->m_lastscore;
371 float * lastcandtempo= unit->m_lastcandidatetempo;
372 float * lastcandphase= unit->m_lastcandidatephase;
373
374 for(j=0;j<10;++j) {
375
376 lastcandtempo[j]=1.5+j*0.15; //even spread
377
378 for (i=0;i<4;++i) {
379 lastcandphase[4*j+i]=i*0.25; //even spread
380 lastscore[4*j+i]=0;
381
382 }
383 }
384
385
386
387 unit->m_scorenorm= 1.0;
388
389 //int storesize= FFTSTORESIZE; //24*FFTSTOREMEM;
390 //
391 // unit->m_fftstore = (float*)RTAlloc(unit->mWorld, storesize * sizeof(float));
392 //
393 // float * fftstore= unit->m_fftstore;
394 //
395 // //zero initialise
396 // for(j=0;j<storesize;++j) fftstore[j]=0;
397 //
398 // unit->m_fftstorepos=FFTSTOREMEM-1;
399 //
400 unit->m_bassmax=1.0;
401 //unit->m_chordmax=1.0;
402
403 unit->m_prevphase=0.0;
404 unit->m_prevtempo=2;
405 unit->m_consistency=0.0;
406
407
408 //snare detection
409 for (i=0;i<3;++i)
410 unit->m_powerbuf[i] = (float*)RTAlloc(unit->mWorld, NOVER4 * sizeof(float));
411
412 //zero buffers
413 for (i=0;i<3;++i)
414 for (j=0;j<NOVER4;++j)
415 unit->m_powerbuf[i][j]=0.0;
416
417 unit->m_powerbufcount=0;
418
419 unit->m_maxsnaresig=ZIN0(9); //*15.0; //15.0; //40.0; //from testing, taken as the fair value
420 unit->m_lastsnaredetect=0;
421
422 unit->m_maxkicksig=ZIN0(8)*20000.0; //1.0
423
424 //blank out onsets
425 for(j=0;j<LOUDNESSFRAMESSTORED;++j) {
426 unit->m_onsets[j]=0;
427 }
428
429 }
430
431
432
DrumTrack_Dtor(DrumTrack * unit)433 void DrumTrack_Dtor(DrumTrack *unit)
434 {
435
436 RTFree(unit->mWorld, unit->m_prepareFFTBuf);
437 RTFree(unit->mWorld, unit->m_FFTBuf);
438 //RTFree(unit->mWorld, unit->m_fftstore);
439
440 for (int i=0;i<3;++i)
441 RTFree(unit->mWorld, unit->m_powerbuf[i]);
442
443 if(unit->m_scfft) {
444 SCWorld_Allocator alloc(ft, unit->mWorld);
445 scfft_destroy(unit->m_scfft, alloc);
446 }
447 }
448
449
DrumTrack_next(DrumTrack * unit,int wrongNumSamples)450 void DrumTrack_next(DrumTrack *unit, int wrongNumSamples)
451 {
452 //would normally be float,will be cast to int for Tristan's optimisation
453 float *in = IN(0);
454
455 //updated at control rate
456 unit->m_maxsnaresig=ZIN0(9); //*15.0; //15.0; //40.0; //from testing, taken as the fair value
457 unit->m_maxkicksig=ZIN0(8)*20000.0; //1.0
458
459 //printf("%d \n",wrongNumSamples);
460
461 int numSamples = unit->mWorld->mFullRate.mBufLength;
462
463 //conditions in reverse order to avoid immediate spillover
464
465 //printf("state %d \n",unit->m_amortisationstate);
466
467 //final update phase decision
468 if(unit->m_amortisationstate==140) {
469
470 //printf("finaldecision \n");
471
472 unit->m_amortisationstate=unit->m_amortisationstate+1; //141 is off, nothing to do
473
474 finaldecision(unit);
475 }
476
477 //then path assessments, 40*40= 1600, do 40 each time for conceptual clarity
478 if((unit->m_amortisationstate>99) && (unit->m_amortisationstate<140)) {
479
480 //printf("do40thpath %d \n",unit->m_amortisationstate);
481
482 if(unit->m_amortisationstate==100) {
483
484 //maybe
485 // if((1.0/unit->m_bestscores[0])>0.00001) {
486 if((1.0/unit->m_bestscores[0])<unit->m_scorenorm) {
487 unit->m_scorenorm= 1.0/unit->m_bestscores[0];
488
489 //printf("%f \n",unit->m_scorenorm);
490 }
491 //else
492 // unit->m_scorenorm= 1.0;
493
494 //set weakest candidate(s) to be the patten phase, tempo
495
496 //dangerous
497 //unit->m_bestscores[9]=unit->m_patternscore;
498 unit->m_bestscores[9]=unit->m_bestscores[0];
499
500 unit->m_besttemposcores[9]= unit->m_patterntempo;
501 unit->m_bestphasescores[36]= unit->m_patternphase;
502
503
504 }
505
506 do40thpath(unit, unit->m_amortisationstate-100);
507 unit->m_amortisationstate=unit->m_amortisationstate+1;
508
509 }
510
511 //calculation spread out in time
512 if(unit->m_amortisationstate<100) {
513
514 //printf("do100thscore %d \n",unit->m_amortisationstate);
515
516 do100thscoring(unit,unit->m_amortisationstate);
517
518 unit->m_amortisationstate=unit->m_amortisationstate+1;
519
520 }
521
522 preparefft(unit, in, numSamples);
523
524 //test if impulse to output
525
526 unit->m_phase+=unit->m_phaseperblock;
527
528 //if not locked, update output phase from model phase, else keep a separate output phase
529
530 float lock= ZIN0(1);
531
532 //printf("lock %f \n",lock);
533
534 if(lock<0.5) {
535
536 unit->m_outputphase= unit->m_phase;
537 unit->m_outputtempo= unit->m_currtempo;
538 unit->m_outputphaseperblock= unit->m_phaseperblock;
539 } else {
540 unit->m_outputphase+=unit->m_outputphaseperblock;
541 }
542
543 if (unit->m_phase >= 1.f) {unit->m_phase-= 1.f;}
544
545 //0 is beat, 1 is quaver, 2 is semiquaver, 3 is actual current tempo in bps
546 //so no audio accuracy with beats, just asap, may as well be control rate
547 ZOUT0(0)=0.0;
548 ZOUT0(1)=0.0;
549 ZOUT0(2)=0.0;
550 ZOUT0(3)=unit->m_outputtempo; //*0.016666667;
551
552 //output beat
553 if (unit->m_outputphase >= 1.f) {
554
555 //printf("beat \n");
556
557 unit->m_outputphase -= 1.f;
558 ZOUT0(0)=1.0;
559 ZOUT0(1)=1.0;
560 ZOUT0(2)=1.0;
561 unit->halftrig=0;
562 unit->q1trig=0;
563 unit->q2trig=0;
564 }
565
566 if (unit->m_outputphase>=0.5 && unit->halftrig==0) {
567 ZOUT0(1)=1.0;
568 ZOUT0(2)=1.0;
569 unit->halftrig=1;
570 }
571
572 if (unit->m_outputphase>=0.25 && unit->q1trig==0) {
573 ZOUT0(2)=1.0;
574 unit->q1trig=1;
575 }
576
577 if (unit->m_outputphase>=0.75 && unit->q2trig==0) {
578 ZOUT0(2)=1.0;
579 unit->q2trig=1;
580 }
581
582 //for (int i=0; i<numSamples; ++i) {
583 // *++output = 0.0;
584 // }
585 //
586
587
588 }
589
590
591 //Tristan recommends copying ints rather than floats- I say negligible compared to other algorithm costs for the moment
592 // TO TREAT, check, update, probably replace entirely with pre allocated buffer based scheme?
preparefft(DrumTrack * unit,float * in,int n)593 void preparefft(DrumTrack *unit, float* in, int n) {
594
595 int i, index = 0, cpt = n, maxindex;
596
597 int bufpos= unit->m_bufWritePos;
598
599 float * preparefftbuf=unit->m_prepareFFTBuf;
600 float * fftbuf= unit->m_FFTBuf;
601
602 // Copy input samples into prepare buffer
603 while ((bufpos < N) && (cpt > 0)) {
604 preparefftbuf[bufpos] = in[index];
605 bufpos++;
606 index++;
607 cpt--;
608 }
609
610 // When Buffer is full...
611 if (bufpos >= N) {
612
613 // Make a copy of prepared buffer into FFT buffer for computation
614 for (i=0; i<N; i++)
615 fftbuf[i] = preparefftbuf[i];
616
617 // Save overlapping samples back into buffer- no danger since no indices overwritten
618 for (i=0; i<OVERLAP; i++)
619 preparefftbuf[i] = preparefftbuf[OVERLAPINDEX+i];
620
621 maxindex = n - index + OVERLAPINDEX;
622
623 //blockSize less than N-OVERLAPINDEX so no problem
624 // Copy the rest of incoming samples into prepareFFTBuffer
625 for (i=OVERLAPINDEX; i<maxindex; i++) {
626 preparefftbuf[i] = in[index];
627 index++;
628 }
629
630 bufpos = maxindex;
631
632 //FFT buffer ready- calculate away!
633 unit->m_frame= unit->m_frame+1;
634 dofft(unit);
635 }
636
637
638 unit->m_bufWritePos= bufpos;
639 //printf("%d \n",bufpos);
640
641 }
642
643
644
645 //calculation function once FFT data ready
dofft(DrumTrack * unit)646 void dofft(DrumTrack *unit) {
647
648 int i;
649
650 float * fftbuf= unit->m_FFTBuf;
651
652 for (i=0; i<N; ++i)
653 fftbuf[i] *= hanning[i];
654
655 scfft_dofft(unit->m_scfft);
656
657 float val1, val2;
658 // Squared Absolute so get power
659 for (i=2; i<N; i+=2) {
660 val1 = fftbuf[i];
661 val2 = fftbuf[i+1];
662 //i>>1 is i/2
663 fftbuf[i>>1] = (val1*val1)+(val2*val2);
664 }
665
666 //calculate loudness first, increments loudnesscounter needed in checkforonsets
667 calculateloudness(unit);
668
669 //for snare and kick detection
670 ///keeping a record of last three fftbufs
671 //update last three powers in required bands
672 unit->m_powerbufcount=(unit->m_powerbufcount+1)%3;
673
674 float * storebuf= unit->m_powerbuf[unit->m_powerbufcount];
675
676 //only stores lower bands under 11kHz
677 for (i=0;i<NOVER4;++i)
678 storebuf[i]=fftbuf[i];
679
680 //zero out now, not two ago like before
681 int onsetframe= (unit->m_loudnesscounter+LOUDNESSFRAMESSTORED)%LOUDNESSFRAMESSTORED;
682 unit->m_onsets[onsetframe]=0; //zero out old values
683
684 //high detections
685 //gotodetectioninband(unit,unit->m_gotobands[1]);
686
687 //low detections second so these onsets always overpower the hgh onsets
688 //gotodetectioninband(unit,unit->m_gotobands[0]);
689
690 //snare detections (not overwritable by kicks)
691 snaredetection(unit);
692 kickdetection(unit);
693
694 //avoid snare overwrite, trust snare detector
695
696 // //check for any twos in last ten, checking ten either side
697 // int basepos= (unit->m_loudnesscounter+LOUDNESSFRAMESSTORED-2)%LOUDNESSFRAMESSTORED;
698 //
699 // //if any kicks near recent snares, zero the snares
700 // for (j=0;j<5;++j) {
701 // int pos=(basepos+LOUDNESSFRAMESSTORED-j)%LOUDNESSFRAMESSTORED;
702 //
703 // if(unit->m_onsets[pos]==1) {
704 // for (i=0;i<5;++i) { //checking 5 previous frames from current position, will gradually test 5 either side
705 // int pos2=(basepos+LOUDNESSFRAMESSTORED-i)%LOUDNESSFRAMESSTORED;
706 //
707 // if(unit->m_onsets[pos2]==2) {
708 // unit->m_onsets[pos]=0;
709 // //break //could break because know no 2 can come till 10 after a 2 onset, but safer to leave alone
710 // }
711 //
712 // }
713 //
714 // }
715 //
716 // }
717
718 //int onsetval= unit->m_onsets[(unit->m_loudnesscounter+LOUDNESSFRAMESSTORED-2)%LOUDNESSFRAMESSTORED];
719 //if(onsetval) printf("onset %d \n",onsetval);
720
721
722 if (unit->m_frame%SKIP==0) {
723
724 //printf("amortisation time \n");
725
726 //amortisation- 8 control periods in a frame
727 //have 2000 calcs to do, split over 100 control periods = 6400 samples, ie one tempo per control period
728
729 unit->m_amortisationstate=0;
730
731 //fix time reference for calculations, so it doesn't update during the amortisation
732 unit->m_storeloudnesscounter= unit->m_loudnesscounter;
733
734 //unit->m_fftstoreposhold= unit->m_fftstorepos;
735
736 unit->m_currphase=unit->m_phase;
737
738 //reset scoring
739 //float * scores= unit->m_scores;
740 float * bestscores= unit->m_bestscores;
741 //float * besttemposcores=unit->m_besttemposcores;
742 // float * bestphasescores=unit->m_bestphasescores;
743 //
744 for (i=0; i<10; ++i) {
745
746 //no need to zero, gets written into during this process
747 //for (j=0; j<ND; ++j)
748 //scores[i][j]; //2000 possibles
749
750 bestscores[i]=-1000;
751 //besttemposcores[i]=0.0;
752 // bestphasescores[i*4]=0.0;
753 // bestphasescores[i*4+1]=0.0;
754 // bestphasescores[i*4+2]=0.0;
755 // bestphasescores[i*4+3]=0.0;
756 // no need to reset these since will automatically get written over
757 }
758
759 //assess pattern matches for scoring
760 int match= findarchetype(unit,0.0); //don't know tempowinner yet
761
762 //if (match && (unit->m_patternscore>1.75)) {
763 //
764 // printf("pattern phase %f pattern tempo %f \n",unit->m_patternphase,unit->m_patterntempo);
765 //
766 // }
767
768
769
770 //float tempowinner,phasewinner;
771 //
772 // tempoassess(unit,&tempowinner,&phasewinner);
773 //
774 // //1.0-phasewinner because the phasenow should be (1.0-pw) to get to a beat at pw
775 // updatetempophase(unit, tempowinner,phasewinner);
776 //
777 }
778
779 //updatephase
780
781 }
782
783
784
785 //global
786 float scoretemp[ND];
787
do100thscoring(DrumTrack * unit,int j)788 void do100thscoring(DrumTrack *unit,int j) {
789 int i,k, baseframe, rounded, testframe;
790 float tempo, Ti, starttime;
791 float phase, beatpos;
792 float beat, beatsum;
793 float prior;
794
795
796 //weight by prior if one exists
797 prior= 1.0;
798
799 if (unit->m_prior) {prior= unit->m_prior[j];}
800
801 //printf("prior %f %d\n",prior,j);
802
803 baseframe=unit->m_storeloudnesscounter+LOUDNESSFRAMESSTORED;
804 float * loudness= unit->m_loudness;
805
806 float best, secondbest;
807 int bestindex, secondbestindex;
808 //find best two phases
809 best=-1000;
810 bestindex=0;
811 secondbest=-1000;
812 secondbestindex=0;
813
814 //float * scores= unit->m_scores;
815
816 //int groovetype=0;
817
818 //for(int groove=0;groove<1;++groove) {
819
820 tempo=TEMPOLOW+(j*TEMPOSTEP);
821
822 Ti= 60/tempo; //could have precalculated these- OPTIMISE
823
824 starttime= 0.0-(5*Ti);
825
826
827 //different phase options
828 for (k=0; k<ND; ++k) {
829
830 phase=k*NDRECIP;
831
832 beatpos=starttime+(Ti*phase);
833
834 beatsum=0.0;
835
836 //8 subbeats
837 for (i=0;i<8;++i) {
838
839 beat=((subbeats[i])*Ti)+beatpos;
840
841 //beat=((subbeats[groove][i])*Ti)+beatpos;
842
843 //get nearest frame position
844
845 rounded= (int)floor(beat*FRAMESR+ .5f);
846
847 //printf("error in rounding? beat %f rounded %d correction %d \n",beat, rounded, (int)(beat*FRAMESR -.5f));
848
849 testframe=(baseframe+rounded)%LOUDNESSFRAMESSTORED;
850
851 beatsum+=(sbtemplate[i])*loudness[testframe];
852
853 //could do a local sum +-2 frames
854
855 // float localsum=0.0;
856 //
857 // for (int hh=0; hh<3; ++hh) {
858 //
859 // int locale= (testframe-1+hh+LOUDNESSFRAMESSTORED)%LOUDNESSFRAMESSTORED;
860 //
861 // localsum+=loudness[locale];
862 // }
863
864 //beatsum+=(sbtemplate[i])*localsum*0.333;
865
866 }
867
868 beatsum=beatsum*prior;
869 scoretemp[k]=beatsum;
870 //what is best so far?
871
872 //for normalising
873 if (beatsum>best) {
874 secondbest=best;
875 secondbestindex=bestindex;
876 best=beatsum;
877 bestindex=k;
878 //groovetype=groove;
879 } else if (beatsum>secondbest) {
880 secondbest=beatsum;
881 secondbestindex=k;
882 }
883
884 //not sure this needs to be stored at all
885 //scores[j*ND+k]=beatsum;
886
887 }
888
889
890
891
892 //what is minimum you need to do to get into the best scoring table?
893 float leastbest= unit->m_bestscores[9];
894
895 //update topten
896 if (best>leastbest) {
897
898 float * bestscores= unit->m_bestscores;
899 float * besttemposcores=unit->m_besttemposcores;
900 float * bestphasescores=unit->m_bestphasescores;
901 float * phasescores= unit->m_phasescores;
902
903 //where does it rate
904 for (i=0; i<10; ++i) {
905 if(best>bestscores[i]) break;
906 }
907
908 //copy all below down one
909 for (k=9; k>i; --k) {
910 bestscores[k]=bestscores[k-1];
911 besttemposcores[k]=besttemposcores[k-1];
912
913 for (int g=0; g<4; ++g) {
914 bestphasescores[k*4+g]=bestphasescores[(k-1)*4+g];
915 phasescores[k*4+g]=phasescores[(k-1)*4+g];
916 }
917 }
918
919 //insertion at i
920 bestscores[i]=best;
921 besttemposcores[i]=tempo*0.01666667; //j;
922
923 //actually stores phases
924 bestphasescores[i*4]=bestindex*NDRECIP;
925 bestphasescores[i*4+1]=secondbestindex*NDRECIP;
926 bestphasescores[i*4+2]=((bestindex+NDOVER2)%ND)*NDRECIP; //pi out of phase option, may be doubled up safely I assume
927 bestphasescores[i*4+3]=((secondbestindex+NDOVER2)%ND)*NDRECIP;
928
929 //this stores scores
930 phasescores[i*4]= scoretemp[bestindex];
931 phasescores[i*4+1]= scoretemp[secondbestindex];
932 phasescores[i*4+2]= scoretemp[((bestindex+NDOVER2)%ND)];
933 phasescores[i*4+3]= scoretemp[((secondbestindex+NDOVER2)%ND)];
934
935 }
936
937 }
938
939
940
941
942
do40thpath(DrumTrack * unit,int i)943 void do40thpath(DrumTrack *unit,int i) {
944
945 int j;
946
947 //will make them constants, variables?
948 float dynleak=ZIN0(2); //0.7; //0.5;
949 float tempowt=ZIN0(3); //1.0; //1.0; //dyn tempo cost
950 float phasewt=ZIN0(4); //2.0; //dyn phase cost
951 // float gamma=0.0; //1.0; //1.0 //consistent tempo cost
952 // float epsilon=0.0; //2.0; //2.0; //consistent phase cost
953 float basswt=ZIN0(5); //1.0;
954 float patternwt=ZIN0(6); //1.0 used to be chordwt;
955
956
957 //printf("do40th test1 %d %d \n",unit->m_amortisationstate,i);
958
959 float * lastscore= unit->m_lastscore;
960
961 //maybe store float as cheaper on CPU?
962 float * lastcandtempo= unit->m_lastcandidatetempo;
963 float * lastcandphase= unit->m_lastcandidatephase;
964
965 //float * bestscores= unit->m_bestscores;
966
967 //or should have stored actual values?
968 float tempocand= unit->m_besttemposcores[i/4];
969 float phasecand=unit->m_bestphasescores[i];
970
971
972 //test phasewinner against bass onsets
973 float bassonsetson= phasematchesbassonsets(unit,phasecand,tempocand);
974 //compare to antiphase
975
976 //printf("phase winner %f antiphase %f\n",phasewinner,fmod(phasewinner+0.5,1.0));
977
978 float antiphase= fmod(phasecand+0.5,1.0);
979
980 float bassonsetsoff= phasematchesbassonsets(unit,antiphase,tempocand);
981
982 if (bassonsetsoff<1) bassonsetsoff=1;
983
984 float bassratio= bassonsetson/bassonsetsoff;
985
986 //float chordratio= comparechordetect(unit,phasecand,tempocand);
987
988 float bassmax= unit->m_bassmax;
989
990 //gradual decay over time
991 bassmax= 0.999*bassmax;
992
993 if (bassratio>bassmax) bassmax=bassratio;
994
995 unit->m_bassmax=bassmax;
996
997 //float chordmax= unit->m_chordmax;
998 //
999 ////gradual decay over time
1000 //chordmax= 0.999*chordmax;
1001 //
1002 //if (chordratio>chordmax) chordmax=chordratio;
1003 //
1004 //unit->m_chordmax=chordmax;
1005
1006 //bigger the bass/chord ratio, less the cost
1007 float basscost= (basswt)*(1.0-(bassratio/bassmax));
1008
1009 //maximal cost if no evidence
1010 float patterncost= 1.0; //(chordwt)*(1.0-(chordratio/chordmax));
1011
1012 if (unit->m_patternscore>1.75) {
1013 //be more lenient because kick/snare detection is approximate
1014 float patttempodiff=fabs(tempocand-unit->m_patterntempo);
1015 if (patttempodiff>0.105) patttempodiff=1; else patttempodiff=0.0;
1016
1017 //phase cost of this phase replacing current phase of oscillator
1018 float pattphaseerror= fabs(calcphasediff(unit->m_patternphase,phasecand,unit->m_patterntempo,tempocand));
1019
1020 //printf("pattern phase cost %f pattern tempo cost %f \n",pattphaseerror,patttempodiff);
1021
1022 //patterncost= patternwt*((0.0*patttempodiff) + (3*pattphaseerror));
1023 patterncost= patternwt*((0.5*patttempodiff) + (0.5*3*pattphaseerror));
1024 }
1025
1026
1027 //values now
1028 float tempo=unit->m_currtempo;
1029 float phase=unit->m_currphase; //captured at beginning of amortisation, can't used unit->m_phase without correction as some time has passed due to amortisation
1030
1031 float prevtempo,prevphase;
1032
1033 //find lowest score
1034
1035 //score= previousscore*dynleak + score+ tempotransitioncost*alpha + epsilon*tempoconfrimationcost (from currtempo to this)
1036 //beta*phasetransitioncost (path cost) + gamma*phaseconfirmationcost (from last phase to this)
1037
1038 float cost,mincost;
1039
1040 mincost=1000000;
1041
1042 //these two transitions are dyn prog independent so calculated outside this loop
1043 //tempo transition costs- fixed if tempo transition above some constant (assume JND for tempo = 8% so 0.105bps at 1.5bps
1044
1045 float tempodiff=fabs(tempocand-tempo);
1046 if (tempodiff>0.105) tempodiff=1; else tempodiff=0.0;
1047
1048 float tempowincost= 0.0; //gamma*tempodiff;
1049
1050 //phase cost of this phase replacing current phase of oscillator
1051 float phaseerror= fabs(calcphasediff(phase,phasecand,tempo,tempocand));
1052
1053 float phasewincost = 0.0; //epsilon*phaseerror;
1054
1055 float tempotransitioncost, phasetransitioncost, oldscorecost, newscorecost;
1056
1057 //aim is to minimse cost, normed to 0-1 then inverted
1058 //could have *0.01);//fixed norm to avoid bias from calc to calc//
1059 newscorecost= 1.0-(unit->m_phasescores[i]*(unit->m_scorenorm)); //score normalised by best result //bestscores[j];
1060
1061 //through 40 previous candidates to this one
1062 for(j=0;j<40;++j) {
1063
1064 prevtempo=lastcandtempo[j/4];
1065 prevphase=lastcandphase[j];
1066
1067 oldscorecost= dynleak*lastscore[j]; //could pre multiply to avoid redoing in each function call, one optimisation too much maybe
1068
1069 //cost over changing hypotheses (no cost if consistent)
1070 tempodiff=fabs(prevtempo-tempocand);
1071 if(tempodiff>0.105) tempodiff=1; else tempodiff=0.0;
1072
1073 tempotransitioncost=tempowt*tempodiff;
1074
1075 //DrumTrack phase transition costs (my correction)
1076 phaseerror= fabs(calcphasediff(prevphase,phasecand,prevtempo,tempocand));
1077
1078 phasetransitioncost=phasewt*3*phaseerror; //random 3!
1079
1080 cost = oldscorecost+newscorecost+phasetransitioncost+tempotransitioncost+phasewincost+tempowincost+basscost+patterncost;
1081
1082 //if(j==0)
1083 //printf(" oldscorecost %f newscorecost %f phasetransitioncost %f tempotransitioncost %f phasewincost %f tempowincost %f cost %f \n", oldscorecost,newscorecost,phasetransitioncost,tempotransitioncost,phasewincost,tempowincost,cost);
1084
1085 //cost
1086 if (cost<mincost)
1087 mincost=cost;
1088
1089 }
1090
1091 //will store mincost in current score until finalisation
1092 //bestscores[j]=mincost;
1093
1094 //will also be the min passed through as lastscore, works OK
1095 unit->m_phasescores[i]=mincost;
1096
1097 //save cost to unit->m_cost[j]=cost for unit->m_phasescores;
1098
1099 }
1100
1101 //find next beat times with respect to old phase, tempo and new phase, tempo at this point
1102
1103 //favours low tempi since phase representation is time independent!
calcphasediff(float prevphase,float phase,float prevtempo,float tempo)1104 float calcphasediff(float prevphase, float phase, float prevtempo, float tempo) {
1105
1106 float a,b,c,result;
1107
1108 float phasediff= TIMEELAPSED*prevtempo- prevphase; //used to be timediff= TIMEELAPSED-(prevphase/prevtempo); phasediff=timediff*prevtempo
1109
1110 //phase from old beat to next beat, see 12 OCT diagram
1111 float phasetobeat= floor(phasediff)+1.0-phasediff;
1112
1113 //corrected for old tempo (currtempo) then rewritten in terms of the new tempowinner
1114 //float requiredphase= (phasetobeat*tempo)/prevtempo;
1115
1116 float oldtimetobeat= phasetobeat/prevtempo;
1117 float newtimetobeat= phase/tempo;
1118
1119 a=oldtimetobeat;
1120 b=newtimetobeat;
1121
1122 //wlog
1123 if(b<a) {c=b; b=a; a=c; c=1/prevtempo;} else {c= 1/tempo;}
1124
1125 //closest between the two beat predictions
1126 result= sc_min(b-a, a-(b-c));
1127 //
1128 // printf("phase error %f \n",result);
1129 //
1130 //if correct within 50mS
1131 //if (result<0.03) result=0.0;
1132
1133 return result;//sc_min(b-a, a-(b-c));
1134 }
1135
1136 /*
1137 //favours low tempi since phase representation is time independent!
1138 float calcphasediff(float prevphase, float phase, float prevtempo, float tempo) {
1139
1140 float a,b;
1141
1142 float phasediff= TIMEELAPSED*prevtempo- prevphase; //used to be timediff= TIMEELAPSED-(prevphase/prevtempo); phasediff=timediff*prevtempo
1143
1144 //phase from old beat to next beat, see 12 OCT diagram
1145 float phasetobeat= floor(phasediff)+1.0-phasediff;
1146
1147 //corrected for old tempo (currtempo) then rewritten in terms of the new tempowinner
1148 float requiredphase= (phasetobeat*tempo)/prevtempo;
1149
1150 a=requiredphase;
1151 b=phase;
1152
1153 if(b<a) b=b+1.0;
1154
1155 return sc_min(b-a, 1.0+a-b);
1156
1157 }
1158 */
1159
1160 //choose lowest score as winner-
1161 //only swap if sufficiently unambiguous lead?
finaldecision(DrumTrack * unit)1162 void finaldecision(DrumTrack *unit) {
1163 int i,j;
1164
1165 float * lastscore= unit->m_lastscore;
1166
1167 //maybe store float as cheaper on CPU?
1168 float * lastcandtempo= unit->m_lastcandidatetempo;
1169 float * lastcandphase= unit->m_lastcandidatephase;
1170
1171 float * bestscores= unit->m_phasescores; //actually stored in this array, was bestscores before but bestscores used for holding 10 best tempi scores
1172
1173 //or should have stored actual values?
1174 float * tempocand= unit->m_besttemposcores;
1175 float * phasecand=unit->m_bestphasescores;
1176
1177 float score,min, secondmin;
1178 int minindex,secondminindex;
1179
1180 minindex=0;
1181 min=10000000;
1182 secondmin=10000000;
1183 secondminindex=0;
1184
1185 for (j=0;j<40;++j){
1186
1187 score=bestscores[j];
1188
1189 if(score<min) {
1190 min=score;
1191 minindex=j;
1192 } else if((score<secondmin) && (score>min)) {
1193 secondmin=score;
1194 secondminindex=j;
1195 }
1196
1197
1198 }
1199
1200 //minindex is winner, update paths
1201 float phasewinner=phasecand[minindex];
1202 float tempowinner=tempocand[minindex/4];
1203
1204 //int match= findarchetype(unit,tempowinner); //don't use tempowinner yet
1205 //
1206 // if (match && (unit->m_patternscore>1.75)) {
1207 //
1208 // printf("phasewinner %f pattern phase %f tempowinner %f pattern tempo %f \n",phasewinner,unit->m_patternphase, tempowinner,unit->m_patterntempo);
1209 //
1210 // phasewinner= unit->m_patternphase;
1211 // tempowinner= unit->m_patterntempo;
1212 //
1213 // }
1214
1215 //perhaps only allow a tempochange if these two are sufficiently different
1216 //printf("best %f secondbest %f ratio %f \n",min,secondmin, min/secondmin);
1217
1218 //check consistency of estimate
1219
1220 //float tempodiff=fabs(tempocand-unit->m_prevtempo);
1221 //if (tempodiff<0.105) tempodiff=1; else tempodiff=0.0;
1222 //
1223
1224 //phase cost of last posited phase becoming new phase of oscillator
1225 float phaseerror= fabs(calcphasediff(unit->m_prevphase,phasewinner,unit->m_prevtempo,tempowinner));
1226
1227 //phaseerror is in time, if less than 0.075 seconds?
1228 //used to be 0.1
1229 //if ((phaseerror<0.1) && ((min/secondmin)<0.995))
1230 if (phaseerror<0.135) //0.14
1231 ++unit->m_consistency;
1232 else
1233 unit->m_consistency=0.0;
1234
1235 unit->m_prevphase=phasewinner;
1236 unit->m_prevtempo=tempowinner;
1237
1238
1239 //printf("phasewinner %f tempowinner %f \n",phasewinner, tempowinner);
1240 //printf("minimum score %f consistency %f phaseerror %f\n",min,unit->m_consistency,phaseerror);
1241
1242
1243 //could make the test value a parameter, or do -2 on score
1244 //only swap when sufficient consistent, don't keep swapping if consistent!
1245 //if( (unit->m_consistency>2.5) && (unit->m_consistency<3.5)) {
1246 if( (unit->m_consistency>1.5) && (unit->m_consistency<2.5)) {
1247 //if( (unit->m_consistency>0.5) && (unit->m_consistency<1.5)) {
1248
1249 //phase has moved on by some time since the calculation frame
1250 ////correction for recording happened during this!
1251 //int framespassed= (unit->m_loudnesscounter+LOUDNESSFRAMESSTORED- unit->m_storeloudnesscounter)%LOUDNESSFRAMESSTORED;
1252 //float phasepassed= framespassed*FRAMEPERIOD*tempowinner;
1253
1254 float timepassed= 0.2046259; //141*64/44100; //fixed by control period, amortisation and sampling rate
1255 float phasepassed= timepassed*tempowinner;
1256
1257 //don't update phase if sufficiently similar
1258 updatetempophase(unit, tempowinner,fmod(phasewinner+phasepassed,1.0)); //phasewinner
1259
1260 if(unit->m_debugmode==1)
1261 printf("update phasewinner %f pattern phase %f tempowinner %f pattern tempo %f \n",phasewinner,unit->m_patternphase, tempowinner,unit->m_patterntempo);
1262
1263 }
1264
1265 int index;
1266
1267 //update previous scores with these
1268 for(j=0;j<10;++j) {
1269
1270 lastcandtempo[j]=tempocand[j]; //even spread
1271
1272 for (i=0;i<4;++i) {
1273 index=4*j+i;
1274 lastcandphase[index]=phasecand[index]; //even spread
1275 lastscore[index]=bestscores[index];
1276 }
1277 }
1278
1279 }
1280
1281
1282
1283 //used twice, once for phase, once for antiphase?
phasematchesbassonsets(DrumTrack * unit,float phase,float bps)1284 float phasematchesbassonsets(DrumTrack *unit, float phase, float bps) {
1285 int i,j,baseframe, rounded, testframe;
1286 float Ti, starttime, beatpos, beat;
1287 //just testing at beat frame positions
1288
1289 baseframe=unit->m_storeloudnesscounter+LOUDNESSFRAMESSTORED;
1290
1291 Ti= 1/bps; //could have precalculated these- OPTIMISE
1292
1293 ////correction for recording happened during this!
1294 //int framespassed= (unit->m_loudnesscounter+LOUDNESSFRAMESSTORED- unit->m_storeloudnesscounter)%LOUDNESSFRAMESSTORED;
1295 //
1296 //printf("gone by %d \n",framespassed);
1297 //
1298 starttime= 0.0-(5*Ti);
1299
1300 beatpos=starttime+(Ti*phase);
1301
1302 float beatsum=0;
1303 //int found;
1304 float avg;
1305
1306 float * bassonsets= unit->m_bassonsets;
1307
1308 //4 beats
1309 for (i=0;i<4;++i) {
1310
1311 beat=(i*Ti)+beatpos;
1312
1313 rounded= (int)floor(beat*FRAMESR+ .5f);
1314
1315 //found=0;
1316 avg=0.0;
1317
1318 // //test within 3 either side
1319 // for(j=0;j<9;++j) {
1320 // testframe=(baseframe+rounded+j-4)%LOUDNESSFRAMESSTORED;
1321 //
1322 // //could do weighted sum, peak in middle...
1323 // avg=avg+bassonsets[testframe]; //if(bassonsets[testframe]==1) found=1;
1324 // }
1325 //
1326 // //testframe=(baseframe+rounded)%LOUDNESSFRAMESSTORED;
1327 //
1328 // beatsum+=avg*0.11111; //bassonsets[testframe];
1329 //
1330
1331 //test within 3 either side
1332 for(j=0;j<7;++j) {
1333 testframe=(baseframe+rounded+j-3)%LOUDNESSFRAMESSTORED;
1334
1335 //could do weighted sum, peak in middle...
1336 avg=avg+bassonsets[testframe]; //if(bassonsets[testframe]==1) found=1;
1337 }
1338
1339 //testframe=(baseframe+rounded)%LOUDNESSFRAMESSTORED;
1340
1341 beatsum+=avg*0.1428571; //bassonsets[testframe];
1342
1343
1344 }
1345
1346 return beatsum;
1347 }
1348
1349
1350
1351
1352 //only updates if sufficiently different
updatetempophase(DrumTrack * unit,float newtempo,float newphase)1353 void updatetempophase(DrumTrack *unit, float newtempo,float newphase) {
1354
1355 float phase,phasenow,a,b,ahead;
1356
1357 phase=unit->m_phase;
1358
1359 //test phase difference of new estimate from current phase of oscillator
1360
1361 a=1.0-newphase;
1362 b=phase;
1363
1364 if(b<a) b=b+1.0;
1365
1366 b=sc_min(b-a, 1.0+a-b); //value from 0.0 to 0.5
1367
1368 //only update if greater than 50mS phase difference (adjusted for tempo)
1369
1370 //if (b>(0.05*newtempo)) {
1371 //if (b>(0.025*newtempo)) { //improved CDR by 5%
1372 if (b>(0.01*newtempo)) { //by 10% now, but 0.0 doesn't help
1373 //pass in [] if no update
1374 //if(newphase>=(-0.1))
1375 phasenow=1.0-newphase;
1376 //printf("phasechange %f\n",phasenow);
1377 //printf("check b %f\n",b);
1378
1379 }
1380 else
1381 phasenow=phase;
1382
1383 a=phase;
1384 b=phasenow;
1385
1386 if(b<a) b=1.0+b;
1387
1388 //phasenow up to 1.0 ahead, but by how much?
1389 ahead= b-a;
1390
1391 if(ahead>0.5) //phasenow behind phase- drop phase back, ahead will be negative
1392 ahead= ahead-1.0;
1393
1394
1395 //both cases now adjust by ahead
1396 //correction by up to a quarter cycle? No, correct by a maximum of x seconds, tempo dependent
1397
1398 //actually, correct by full amount as long as there is consistent evidence
1399 //0.2 seconds in beats at current tempo
1400 //maxcorrection=1.0; //min(0.1*temponow,1.0); %correct by no more than a beat
1401 //ahead=sign(ahead)*(min(abs(ahead),maxcorrection));
1402
1403 //can't correct back earlier than current phase else may beat twice!
1404 //must temporarily drop the rate
1405 //phase=mod(max(phase+ahead,floor(phase)),1.0);
1406
1407 //no, just store last beat time and require greater than...
1408 unit->m_phase=fmod(phase+ahead+1.0,1.0);
1409
1410 unit->m_currtempo=newtempo;
1411
1412 unit->m_phaseperblock= (unit->mWorld->mFullRate.mBufLength*newtempo)/(FS);
1413
1414 }
1415
1416
1417
1418
1419 //also calc kick drum detector on bottom three bands
calculateloudness(DrumTrack * unit)1420 void calculateloudness(DrumTrack *unit) {
1421
1422 int j,k;
1423
1424 float * fftbuf= unit->m_FFTBuf;
1425
1426 float dfsum=0.0; //,lsum=0.0;
1427 float bassonset=0;
1428 float basssum=0.0;
1429
1430 //store powers for later chord detection step
1431 // float * fftstore= unit->m_fftstore;
1432 //
1433 // unit->m_fftstorepos=(unit->m_fftstorepos+1)%FFTSTOREMEM;
1434 //
1435 // int basepos= 24*unit->m_fftstorepos;
1436 // for(j=0;j<24;++j) {
1437 // fftstore[basepos+j]=fftbuf[j+1];
1438 // }
1439 //
1440
1441
1442
1443 for (k=0; k<40; ++k){
1444
1445 int bandstart=eqlbandbins[k];
1446 //int bandend=eqlbandbins[k+1];
1447 int bandsize= eqlbandsizes[k];
1448
1449 float bsum=0.0;
1450
1451 for (int h=0; h<bandsize;++h) {
1452 bsum= bsum+fftbuf[h+bandstart];
1453 }
1454
1455 //store recips of bandsizes?
1456 bsum= bsum/bandsize;
1457
1458
1459 float diff=bsum;
1460 dfsum=dfsum+diff;
1461 if (k<5) basssum=basssum+diff;
1462
1463 }
1464
1465
1466 //increment first so this frame is unit->loudnesscounter
1467 unit->m_loudnesscounter=(unit->m_loudnesscounter+1)%LOUDNESSFRAMESSTORED;
1468
1469 unit->m_loudness[unit->m_loudnesscounter]=dfsum; //dfsum*0.025; //divide by num of bands to get a dB answer
1470 //printf("loudness %f %f \n",unit->loudness[unit->loudnesscounter], lsum);
1471
1472 bassonset= basssum; //90+(10*log10(basssum));
1473
1474 unit->m_bassonsets[unit->m_loudnesscounter]=bassonset;
1475
1476 }
1477
1478
1479 //snare limits= [34,177] (may try to reduce summands for CPU saving)
snaredetection(DrumTrack * unit)1480 void snaredetection(DrumTrack *unit){
1481
1482 float snaresig,highfreqave,lowfreqave,quantsum, power,temp;
1483 int count,num;
1484
1485 //will also use these for indexing
1486 int now=unit->m_powerbufcount;
1487 int last, lastlast;
1488 last=(2+now)%3; //avoid negative numbers in modulo- get back negatives!
1489 lastlast=(1+now)%3;
1490
1491 float * nowbuf,*lastbuf,*lastlastbuf;
1492 nowbuf=unit->m_powerbuf[now];
1493 lastbuf=unit->m_powerbuf[last];
1494 lastlastbuf=unit->m_powerbuf[lastlast];
1495
1496 num=0;
1497 quantsum=0.0;
1498 count=0;
1499
1500 snaresig=1.0;
1501
1502 for(int f=33; f<177;++f) {
1503
1504 power=lastbuf[f];
1505
1506 highfreqave = 0.25*(lastbuf[f+2]+lastlastbuf[f+1]+lastbuf[f+1]+nowbuf[f+1]);
1507 lowfreqave = 0.25*(lastbuf[f-2]+lastlastbuf[f-1]+lastbuf[f-1]+nowbuf[f-1]);
1508
1509 temp=sc_min(highfreqave,lowfreqave);
1510
1511 //0.25
1512 if(temp > (0.5*power)) {
1513 quantsum=quantsum+power;
1514 num=num+1;
1515 }
1516
1517 //printf("minave %f power %f quantsum %f \n",temp,power,quantsum);
1518
1519 count=count+1;
1520
1521 if(count==9) {
1522 //0.125*(quantsum*0.11111111)
1523 temp=0.0138889*quantsum;
1524 temp=sc_min(temp,0.54);
1525 snaresig*=(1+temp);
1526 quantsum=0.0;
1527 count=0;
1528 }
1529
1530 }
1531
1532 //snaresig(1,t)= prod(noisebands); %mean(noisebands); %num
1533
1534 //printf("snaresig %f \n",snaresig);
1535
1536 //can't allow max to get too high else detections suddenly cut out- 100 seems a fair value
1537
1538 //if(snaresig>(unit->m_maxsnaresig)) {
1539 // //unit->m_maxsnaresig=snaresig;
1540 //
1541 // printf("max found! %f \n",snaresig); //unit->m_maxsnaresig);
1542 // }
1543
1544 //max vals up to 1.54**16 ie about 1000
1545
1546 snaresig=snaresig/(1000*unit->m_maxsnaresig);
1547
1548 //printf("postsnaresig %f \n",snaresig);
1549
1550 //should peak pick really!
1551
1552 //snare detection- don't allow another for a while? m_lastsnaredetect
1553 if(snaresig>0.5) { //used to be 0.5, can add a user defined threshold
1554
1555 //stop in a row detections
1556 if(unit->m_lastsnaredetect<(unit->m_frame-6)) {
1557
1558 if(unit->m_debugmode==2)
1559 printf("snare found! %ld %ld \n", unit->m_lastsnaredetect, unit->m_frame);
1560
1561 //occured one frame ago, but do -2 to avoid kick overwrite on next cycle!
1562 int onsetframe= (unit->m_loudnesscounter+LOUDNESSFRAMESSTORED-2)%LOUDNESSFRAMESSTORED;
1563
1564 unit->m_onsets[onsetframe]=2; //(-1); //snare
1565 }
1566
1567 unit->m_lastsnaredetect=unit->m_frame;
1568
1569 }
1570
1571 }
1572
1573
1574
1575 //uses Goto onset detection to with threshold to spot a kick
kickdetection(DrumTrack * unit)1576 void kickdetection(DrumTrack *unit){
1577
1578 float dsum;
1579 float kicksig;
1580
1581 //will also use these for indexing
1582 int now=unit->m_powerbufcount;
1583 int last, lastlast;
1584 last=(2+now)%3; //avoid negative numbers in modulo- get back negatives!
1585 lastlast=(1+now)%3;
1586
1587 float * nowbuf,*lastbuf,*lastlastbuf;
1588 nowbuf=unit->m_powerbuf[now];
1589 lastbuf=unit->m_powerbuf[last];
1590 lastlastbuf=unit->m_powerbuf[lastlast];
1591
1592 dsum=0.0;
1593
1594 for(int f=1; f<=3; ++f) {
1595
1596 float updownmax= sc_max(lastlastbuf[f-1],lastlastbuf[f+1]);
1597 float prevpow= sc_max(lastlastbuf[f],updownmax);
1598
1599 float tempmin=sc_min(lastbuf[f],nowbuf[f]);
1600
1601 if(tempmin>prevpow) {
1602
1603 float temp=sc_max(lastbuf[f],nowbuf[f]);
1604 dsum=dsum+temp;
1605 }
1606 }
1607
1608
1609 kicksig=dsum/3;
1610 //running max must be kept- just will do best so far for now...could become best within last x seconds
1611 //updatemaxforband
1612
1613
1614 // if(kicksig>(unit->m_maxkicksig)) {
1615 // unit->m_maxkicksig=kicksig;
1616 //
1617 // printf("max found! %f \n",unit->m_maxkicksig);
1618 // }
1619
1620 kicksig=kicksig/(unit->m_maxkicksig);
1621
1622 //kick detection- don't allow another for a while? m_lastsnaredetect
1623 if(kicksig>0.6) { //used to be 0.5, can add a user defined threshold
1624
1625 //stop in a row detections
1626 if(unit->m_lastkickdetect<(unit->m_frame-6)) {
1627
1628 if(unit->m_debugmode==2)
1629 printf("kick found! %ld %ld \n", unit->m_lastkickdetect, unit->m_frame);
1630
1631
1632 //occured one frame ago, but do -2 to avoid kick overwrite on next cycle!
1633 int onsetframe= (unit->m_loudnesscounter+LOUDNESSFRAMESSTORED-2)%LOUDNESSFRAMESSTORED;
1634
1635 unit->m_onsets[onsetframe]=1; //kick- might do 1 kick, -1 snare
1636 }
1637
1638 unit->m_lastkickdetect=unit->m_frame;
1639
1640 }
1641
1642 }
1643
1644
1645
1646 //one matching the tempowinner will score most (can over write even if an equal score)
1647
1648 //impose tempowinner t choose selection spread? o/w could be missing second beat but have third and fourth
1649
1650 //look for archetypal pattern in m_onsets
1651 //phase not important, want to just look at a fixed area in the past
findarchetype(DrumTrack * unit,float tempowinner)1652 int findarchetype(DrumTrack *unit, float tempowinner) {
1653 int i,j,k,baseframe;
1654 float starttime, lasttime;
1655 int startframe, lastframe, nextonset;
1656 //just testing at beat frame positions
1657
1658 baseframe=unit->m_storeloudnesscounter+LOUDNESSFRAMESSTORED;
1659 int * onsets= unit->m_onsets;
1660
1661 //don't know periods, just going to find from search
1662 starttime= 0.0-(5*MAXPERIOD); //0.0-(5*0.667); //one more eighth note than usual to calc pre beat
1663
1664 startframe=((int)(starttime*FRAMESR+ .5f) + baseframe)%LOUDNESSFRAMESSTORED;
1665
1666 //must have at least room for a fast 0.333*4 bar else no point checking
1667 lasttime= -4*MINPERIOD; //-4*0.33;
1668
1669 //this is last start frame, last end frame is baseframe
1670 lastframe= ((int)(lasttime*FRAMESR+ .5f) + baseframe)%LOUDNESSFRAMESSTORED;
1671
1672 nextonset=(startframe+LOUDNESSFRAMESSTORED-1)%LOUDNESSFRAMESSTORED;
1673
1674 //already made a list of onsets?
1675 int numtolast=0;
1676
1677 if (lastframe<startframe)
1678 numtolast= lastframe+LOUDNESSFRAMESSTORED-startframe;
1679 else
1680 numtolast= lastframe-startframe;
1681
1682 int numtonow=0;
1683
1684 if (baseframe<startframe)
1685 numtonow= baseframe+LOUDNESSFRAMESSTORED-startframe;
1686 else
1687 numtonow= baseframe-startframe;
1688
1689 int pos;
1690
1691 int numonsets=0;
1692 int numstarts=0;
1693
1694
1695 //store them in an array (preallocate 50, maximum size)
1696 //permanent array for this
1697 //int onsetposition[50];
1698 int * onsetposition= unit->m_onsetposition;
1699
1700 for (i=0;i<numtonow;++i) {
1701
1702 pos= (startframe+i+LOUDNESSFRAMESSTORED)%LOUDNESSFRAMESSTORED;
1703
1704 if(onsets[pos]!=0) {
1705 if(i<numtolast) ++numstarts;
1706
1707 onsetposition[numonsets]=pos;
1708
1709 ++numonsets;
1710
1711 if (numonsets==MAXONSETS) {printf("disaster? %d \n",numonsets); break;}
1712 }
1713 }
1714
1715 //if (numstarts>MAXONSETS) numstarts= MAXONSETS;
1716 //printf("numonsets %d numstarts %d \n", numonsets,numstarts);
1717
1718
1719 int bestindex=-1;
1720 float bestscore=0.0;
1721 int besttempo=0;
1722
1723 //float score;
1724 //int tempo;
1725
1726
1727
1728 for (i=0; i<numstarts; ++i) {
1729
1730 int first=onsetposition[i];
1731 int firstval= onsets[first];
1732
1733 for (j=i+1;j<numonsets; ++j) {
1734 int second=onsetposition[j];
1735
1736 int diff, realdiff;
1737
1738 diff= (second+LOUDNESSFRAMESSTORED- first)%LOUDNESSFRAMESSTORED; //works for both cases second<first and first<=second
1739 int test= (baseframe+LOUDNESSFRAMESSTORED- first)%LOUDNESSFRAMESSTORED;
1740
1741 //second IS second beat
1742 if(test>(3*diff)) {
1743
1744 testpattern(unit,bestindex,bestscore,besttempo,first,diff,firstval);
1745
1746 }
1747
1748 ////second is actually third beat
1749
1750 if(test>((3/2)*diff)) {
1751
1752 realdiff= (diff/2);
1753
1754 testpattern(unit,bestindex,bestscore,besttempo,first,realdiff,firstval);
1755
1756 }
1757
1758 //second is fourth, already all beats will fit within
1759 realdiff= (diff/3);
1760
1761 testpattern(unit,bestindex,bestscore,besttempo,first,realdiff,firstval);
1762
1763 }
1764
1765 }
1766
1767 //tempo= FRAMESR/(float)tempo;
1768
1769 float actualtempo;
1770
1771 if (besttempo>0) {
1772 actualtempo = FRAMESR/(float)besttempo;
1773
1774 int dist= (baseframe-bestindex+LOUDNESSFRAMESSTORED)%LOUDNESSFRAMESSTORED;
1775
1776 float phase= (dist%besttempo)/(float)besttempo;
1777
1778 unit->m_patternphase= 1.0-phase;
1779 unit->m_patternscore=bestscore;
1780 unit->m_patterntempo=actualtempo;
1781
1782 if(unit->m_debugmode==1)
1783 printf("best match phase %f score %f tempo %f \n", unit->m_patternphase, unit->m_patternscore, unit->m_patterntempo);
1784
1785 return 1;
1786 }
1787
1788 return 0; //no matches found
1789 }
1790
1791
testpattern(DrumTrack * unit,int & bestindex,float & bestscore,int & besttempo,int first,int diff,int firstval)1792 void testpattern(DrumTrack * unit, int &bestindex, float &bestscore, int &besttempo, int first, int diff, int firstval) {
1793
1794 int k;
1795 float score;
1796
1797 //int * onsetposition= unit->m_onsetposition;
1798 int * onsets= unit->m_onsets;
1799
1800 int second= (first+diff)%LOUDNESSFRAMESSTORED;
1801
1802 //first case- second is the second beat of the pattern
1803 //min one beat 0.33*FRAMESR max three beats 0.66*FRAMESR 86.1328
1804 int mindiff= MINDIFF; //28; //allowing for some error could be 25, usually 28
1805 int maxdiff= MAXDIFF; //58;
1806
1807 //int test= (baseframe+LOUDNESSFRAMESSTORED- first)%LOUDNESSFRAMESSTORED;
1808
1809 //can exclude more cases knowing diff- 3*diff can't be greater than LOUDNESSFRAMESSTORED
1810 //if(3*diff<LOUDNESSFRAMESSTORED) {
1811
1812 //spacing must be plausible
1813 if(diff>=mindiff && diff<=maxdiff) {
1814
1815 int tempo= diff; //will convert later FRAMESR/(float)diff;
1816 int secondval= onsets[second];
1817
1818 //spacing is diff for testing
1819
1820 int third=(second+diff)%LOUDNESSFRAMESSTORED;
1821 int fourth=(third+diff)%LOUDNESSFRAMESSTORED;
1822
1823 //two tests for each case, each case determines a unique position of bestindex
1824
1825 int thirdval=0;
1826 int fourthval=0;
1827
1828 int posindex,negindex;
1829
1830 //allowing for an error of up to 5 either side, successively overwrites with best option if non zero
1831 for (k=4;k>=0;--k) {
1832
1833 negindex=(third-k+LOUDNESSFRAMESSTORED)%LOUDNESSFRAMESSTORED;
1834
1835 if(onsets[negindex])
1836 thirdval=onsets[negindex];
1837
1838 posindex=(third+k)%LOUDNESSFRAMESSTORED;
1839
1840 if(onsets[posindex])
1841 thirdval=onsets[posindex];
1842
1843 }
1844
1845 for (k=4;k>=0;--k) {
1846
1847 negindex=(fourth-k+LOUDNESSFRAMESSTORED)%LOUDNESSFRAMESSTORED;
1848
1849 if(onsets[negindex])
1850 fourthval=onsets[negindex];
1851
1852 posindex=(fourth+k)%LOUDNESSFRAMESSTORED;
1853
1854 if(onsets[posindex])
1855 fourthval=onsets[posindex];
1856
1857 }
1858
1859
1860 if (firstval==2) //snare
1861 {
1862
1863 //two possibilities
1864
1865 score = 1.0;
1866
1867 if(secondval==1) score+=0.5;
1868 if(thirdval==2) score+=1.0;
1869 if(fourthval==1) score+=1.0;
1870
1871 if(score>bestscore) {
1872
1873 bestindex=fourth; //first beat of bar!
1874 bestscore=score;
1875 besttempo=tempo;
1876 }
1877
1878 score = 1.0;
1879
1880 if(secondval==1) score+=1.0;
1881 if(thirdval==2) score+=1.0;
1882 if(fourthval==1) score+=0.5;
1883
1884 if(score>bestscore) {
1885
1886 bestindex=second; //first beat of bar!
1887 bestscore=score;
1888 besttempo=tempo;
1889 }
1890
1891
1892 } else { //kick
1893
1894 score = 1.0;
1895
1896 if(secondval==2) score+=1.0;
1897 if(thirdval==1) score+=0.5;
1898 if(fourthval==2) score+=1.0;
1899
1900 if(score>bestscore) {
1901
1902 bestindex=first; //first beat of bar!
1903 bestscore=score;
1904 besttempo=tempo;
1905 }
1906
1907
1908 score = 0.5;
1909
1910 if(secondval==2) score+=1.0;
1911 if(thirdval==1) score+=1.0;
1912 if(fourthval==2) score+=1.0;
1913
1914 if(score>bestscore) {
1915
1916 bestindex=third; //first beat of bar!
1917 bestscore=score;
1918 besttempo=tempo;
1919 }
1920
1921
1922 }
1923
1924
1925
1926
1927
1928 }
1929
1930
1931
1932 }
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
prepareHanningWindow()1944 void prepareHanningWindow(){
1945 float ang;
1946
1947 ang=(1.0/N)*TWOPI;
1948
1949 for(int i=0;i<N;++i)
1950 hanning[i]=0.5 - 0.5*cos(ang*i);
1951
1952 }
1953
1954
PluginLoad(DrumTrack)1955 PluginLoad(DrumTrack) {
1956
1957 ft= inTable;
1958
1959 prepareHanningWindow();
1960
1961 DefineDtorCantAliasUnit(DrumTrack);
1962 }
1963
1964
1965
1966 /*
1967
1968
1969 //used twice, once for phase, once for antiphase?
1970 float comparechordetect(DrumTrack *unit, float phase, float bps) {
1971 int i,j,k,baseframe, rounded, testframe;
1972 float Ti, starttime, beatpos, beat;
1973 //just testing at beat frame positions
1974
1975 baseframe=unit->m_fftstoreposhold+FFTSTOREMEM;
1976
1977 Ti= 1/bps; //could have precalculated these- OPTIMISE
1978
1979 int framesize= (int)floor(0.5*Ti/FRAMEPERIOD); //eighth note area
1980
1981 //%as goto ignore outer 1/5s, only take middle 3/5
1982 int keep= (int)floor((0.6*framesize)+ .5f);
1983 int onefifth= (int)floor((0.2*framesize)+ .5f);
1984
1985 starttime= 0.0-(5.5*Ti); //one more eighth note than usual to calc pre beat
1986
1987 beatpos=starttime+(Ti*phase);
1988
1989 float * fftstore= unit->m_fftstore;
1990
1991 //should allocate for each
1992 float *chordhistogram= unit->m_chordhistogram;
1993 float *chordhistogramprev= unit->m_chordhistogramprev;
1994 float onsum=0.0;
1995 float offsum=0.0;
1996
1997 //8 beats
1998 for (i=0;i<9;++i) {
1999
2000 beat=(i*(Ti*0.5))+beatpos;
2001
2002
2003 //ERROR if beat negative? Should be -.5f in rounding! No, floor goes moe negative
2004 rounded= (int)floor(beat*FRAMESR+ .5f);
2005
2006 //printf("error in rounding? beat %f rounded %d correction %d \n",beat, rounded, (int)(beat*FRAMESR -.5f));
2007
2008 testframe=baseframe+rounded+onefifth;
2009
2010 //calc new histogram
2011 for (j=0;j<24;++j) {
2012
2013 float sum=0.0;
2014
2015 for(k=0;k<keep;++k) {
2016
2017 sum+= fftstore[((testframe+k)%FFTSTOREMEM)*24+j];
2018 }
2019
2020
2021 chordhistogram[j]=sum;
2022 }
2023
2024 //peak pick
2025 //for (j=1;j<23;++j) {
2026 //
2027 //if((chordhistogram[j-1]>chordhistogram[j]) || (chordhistogram[j]<chordhistogram[j+1]))
2028 //chordhistogram[j]=0;
2029 //
2030 //}
2031
2032 //zero 0 and 23
2033 chordhistogram[0]=0;
2034 chordhistogram[23]=0;
2035
2036 //do difference to prev, sum of positives only
2037 if(i>0) {
2038
2039 for (j=0;j<24;++j) {
2040
2041 float diff;
2042
2043 diff=chordhistogram[j]-chordhistogramprev[j];
2044
2045 //printf("%f \n",diff);
2046
2047 if(diff<0) diff=0;
2048
2049 if(i%2==1)
2050 onsum+=diff; //bassonsets[testframe];
2051 else
2052 offsum+=diff;
2053 }
2054
2055 }
2056
2057 //copy new into previous
2058 for (j=1;j<23;++j)
2059 chordhistogramprev[j]=chordhistogram[j];
2060
2061
2062 }
2063
2064
2065 if (offsum<1) offsum=1;
2066
2067 //printf("onsum %f offsum %f ratio %f\n",onsum, offsum, onsum/offsum);
2068 //
2069
2070 return onsum/offsum;
2071 }
2072
2073
2074 */
2075
2076