|
@@ -36,6 +36,7 @@ typedef struct
|
36
|
36
|
unsigned frmCnt; // spectral frame count
|
37
|
37
|
cmReal_t* sfV; // sfV[frmCnt] spectral flux vector
|
38
|
38
|
cmReal_t* dfV; // dfV[frmCnt] onset function vector
|
|
39
|
+ cmReal_t maxSf;
|
39
|
40
|
|
40
|
41
|
cmAudioFileInfo_t afInfo;
|
41
|
42
|
unsigned fftSmpCnt;
|
|
@@ -139,15 +140,12 @@ cmOnRC_t cmOnsetFinalize( cmOnH_t* hp )
|
139
|
140
|
bool cmOnsetIsValid( cmOnH_t h )
|
140
|
141
|
{ return h.h!=NULL; }
|
141
|
142
|
|
142
|
|
-cmOnRC_t _cmOnsetExec( _cmOn_t* p, unsigned chCnt )
|
|
143
|
+cmOnRC_t _cmOnsetExec( _cmOn_t* p )
|
143
|
144
|
{
|
144
|
145
|
cmOnRC_t rc = kOkOnRC;
|
145
|
146
|
int fi = 0;
|
146
|
147
|
unsigned binCnt = p->binCnt; //p->pvocPtr->binCnt;
|
147
|
148
|
cmReal_t mag0V[ binCnt ];
|
148
|
|
- cmSample_t out0V[ p->hopSmpCnt ];
|
149
|
|
- cmSample_t out1V[ p->hopSmpCnt ];
|
150
|
|
- cmSample_t* aoutV[chCnt];
|
151
|
149
|
double prog = 0.1;
|
152
|
150
|
cmReal_t b0 = 1;
|
153
|
151
|
cmReal_t b[] = {1 };
|
|
@@ -155,11 +153,6 @@ cmOnRC_t _cmOnsetExec( _cmOn_t* p, unsigned chCnt )
|
155
|
153
|
cmReal_t d[] = {0};
|
156
|
154
|
cmReal_t maxVal = 0;
|
157
|
155
|
|
158
|
|
- if( chCnt > 0 )
|
159
|
|
- aoutV[0] = out0V;
|
160
|
|
-
|
161
|
|
- if( chCnt > 1 )
|
162
|
|
- aoutV[1] = out1V;
|
163
|
156
|
|
164
|
157
|
cmVOR_Zero(mag0V,binCnt);
|
165
|
158
|
|
|
@@ -206,11 +199,11 @@ cmOnRC_t _cmOnsetExec( _cmOn_t* p, unsigned chCnt )
|
206
|
199
|
cmReal_t stdDev = sqrt(cmVOR_Variance(p->sfV, p->frmCnt, &mean ));
|
207
|
200
|
cmVOR_SubVS(p->sfV,p->frmCnt,mean);
|
208
|
201
|
cmVOR_DivVS(p->sfV,p->frmCnt,stdDev);
|
209
|
|
- cmReal_t maxSf = cmVOR_Max(p->sfV,p->frmCnt,1);
|
|
202
|
+ p->maxSf = cmVOR_Max(p->sfV,p->frmCnt,1);
|
210
|
203
|
prog = 0.1;
|
211
|
204
|
|
212
|
205
|
printf("max:%f ",maxVal);
|
213
|
|
- printf("mean:%f max:%f sd:%f\n",mean,maxSf,stdDev);
|
|
206
|
+ printf("mean:%f max:%f sd:%f\n",mean,p->maxSf,stdDev);
|
214
|
207
|
|
215
|
208
|
// Pick peaks from the onset detection function using a subset
|
216
|
209
|
// of the rules from Dixon, 2006, Onset Detection Revisited.
|
|
@@ -222,9 +215,6 @@ cmOnRC_t _cmOnsetExec( _cmOn_t* p, unsigned chCnt )
|
222
|
215
|
int nn = ei - bi; // wnd frm cnt
|
223
|
216
|
int wi = fi < p->cfg.wndFrmCnt ? fi : p->cfg.wndFrmCnt; // cur wnd index
|
224
|
217
|
|
225
|
|
- // initialize the out
|
226
|
|
- cmVOS_Fill(out1V,p->hopSmpCnt,p->sfV[fi]/maxSf);
|
227
|
|
- cmVOS_Zero(out0V,p->hopSmpCnt);
|
228
|
218
|
|
229
|
219
|
p->dfV[fi] = 0;
|
230
|
220
|
|
|
@@ -239,25 +229,10 @@ cmOnRC_t _cmOnsetExec( _cmOn_t* p, unsigned chCnt )
|
239
|
229
|
if( p->sfV[fi] > cmVOR_Mean(p->sfV + bi, nn ) + p->cfg.threshold )
|
240
|
230
|
{
|
241
|
231
|
p->dfV[fi] = p->sfV[fi];
|
242
|
|
- out0V[ p->hopSmpCnt/2 ] = p->sfV[fi]/maxSf;
|
243
|
232
|
|
244
|
|
- unsigned smpIdx = fi * p->hopSmpCnt + p->hopSmpCnt/2;
|
245
|
|
-
|
246
|
|
- // write the output text file
|
247
|
|
- if( cmFilePrintf(p->txH, "[ %i, %f ]\n", smpIdx, p->sfV[fi] ) != kOkFileRC )
|
248
|
|
- {
|
249
|
|
- rc = cmErrMsg(&p->err,kDspTextFileFailOnRC,"Text output write to '%s' failed.", cmFileName(p->txH));
|
250
|
|
- goto errLabel;
|
251
|
|
- }
|
252
|
233
|
}
|
253
|
234
|
}
|
254
|
235
|
|
255
|
|
- // write the output audio file
|
256
|
|
- if( cmAudioFileWriteFloat(p->afH, p->hopSmpCnt, chCnt, aoutV ) != kOkAfRC )
|
257
|
|
- {
|
258
|
|
- rc = cmErrMsg(&p->err,kDspAudioFileFailOnRC,"Audio file write to '%s' failed.",cmAudioFileName(p->afH));
|
259
|
|
- goto errLabel;
|
260
|
|
- }
|
261
|
236
|
|
262
|
237
|
if( fi >= prog*p->frmCnt )
|
263
|
238
|
{
|
|
@@ -267,16 +242,13 @@ cmOnRC_t _cmOnsetExec( _cmOn_t* p, unsigned chCnt )
|
267
|
242
|
|
268
|
243
|
}
|
269
|
244
|
|
270
|
|
- errLabel:
|
271
|
|
-
|
272
|
245
|
return rc;
|
273
|
246
|
}
|
274
|
247
|
|
275
|
|
-cmOnRC_t cmOnsetExec( cmOnH_t h, const cmOnsetCfg_t* cfg, const cmChar_t* inAudioFn, const cmChar_t* outAudioFn, const cmChar_t* outTextFn )
|
|
248
|
+cmOnRC_t cmOnsetProc( cmOnH_t h, const cmOnsetCfg_t* cfg, const cmChar_t* inAudioFn )
|
276
|
249
|
{
|
277
|
|
- cmOnRC_t rc = kOkOnRC;
|
278
|
|
- _cmOn_t* p = _cmOnsetHandleToPtr(h);
|
279
|
|
- unsigned audioOutChCnt = 2;
|
|
250
|
+ cmOnRC_t rc = kOkOnRC;
|
|
251
|
+ _cmOn_t* p = _cmOnsetHandleToPtr(h);
|
280
|
252
|
p->cfg = *cfg;
|
281
|
253
|
|
282
|
254
|
// get the audio file header information
|
|
@@ -307,9 +279,29 @@ cmOnRC_t cmOnsetExec( cmOnH_t h, const cmOnsetCfg_t* cfg, const cmChar_t* inAudi
|
307
|
279
|
goto errLabel;
|
308
|
280
|
}
|
309
|
281
|
|
|
282
|
+
|
|
283
|
+ rc = _cmOnsetExec(p);
|
|
284
|
+
|
|
285
|
+ errLabel:
|
|
286
|
+ return rc;
|
|
287
|
+}
|
|
288
|
+
|
|
289
|
+cmOnRC_t cmOnsetWrite( cmOnH_t h, const cmChar_t* outAudioFn, const cmChar_t* outTextFn)
|
|
290
|
+{
|
|
291
|
+ enum { kChCnt = 2 };
|
|
292
|
+ cmOnRC_t rc = kOkOnRC;
|
|
293
|
+ _cmOn_t* p = _cmOnsetHandleToPtr(h);
|
|
294
|
+
|
|
295
|
+ cmSample_t out0V[ p->hopSmpCnt ];
|
|
296
|
+ cmSample_t out1V[ p->hopSmpCnt ];
|
|
297
|
+ cmSample_t* aoutV[kChCnt];
|
|
298
|
+
|
|
299
|
+ aoutV[0] = out0V;
|
|
300
|
+ aoutV[1] = out1V;
|
|
301
|
+
|
310
|
302
|
// initalize the audio output file
|
311
|
303
|
if( outAudioFn != NULL )
|
312
|
|
- if( cmAudioFileIsValid( p->afH = cmAudioFileNewCreate( outAudioFn, p->afInfo.srate, p->afInfo.bits, audioOutChCnt, NULL, p->err.rpt)) == false )
|
|
304
|
+ if( cmAudioFileIsValid( p->afH = cmAudioFileNewCreate( outAudioFn, p->afInfo.srate, p->afInfo.bits, kChCnt, NULL, p->err.rpt)) == false )
|
313
|
305
|
{
|
314
|
306
|
rc = cmErrMsg(&p->err,kDspAudioFileFailOnRC, "The audio output file '%s' could not be opened.", outAudioFn);
|
315
|
307
|
goto errLabel;
|
|
@@ -327,9 +319,47 @@ cmOnRC_t cmOnsetExec( cmOnH_t h, const cmOnsetCfg_t* cfg, const cmChar_t* inAudi
|
327
|
319
|
cmFilePrint(p->txH,"{\n onsetArray : \n[\n");
|
328
|
320
|
}
|
329
|
321
|
|
330
|
|
- rc = _cmOnsetExec(p,audioOutChCnt);
|
|
322
|
+ // rewind the audio file
|
|
323
|
+ cmAudioFileRdSeek(p->afRdPtr,0);
|
331
|
324
|
|
332
|
|
- errLabel:
|
|
325
|
+ unsigned fi;
|
|
326
|
+ for(fi=0; fi<p->frmCnt; ++fi)
|
|
327
|
+ {
|
|
328
|
+ // audio channel 1 is filled with the spectral flux
|
|
329
|
+ // initialize the out
|
|
330
|
+ cmVOS_Fill(out1V,p->hopSmpCnt,p->sfV[fi]/p->maxSf);
|
|
331
|
+ cmVOS_Zero(out0V,p->hopSmpCnt);
|
|
332
|
+
|
|
333
|
+ if( p->dfV[fi] > 0 )
|
|
334
|
+ {
|
|
335
|
+ // audio channel 0 is set with the detection indicators
|
|
336
|
+ unsigned smpIdx = fi * p->hopSmpCnt + p->hopSmpCnt/2;
|
|
337
|
+ out0V[ p->hopSmpCnt/2 ] = p->sfV[fi]/p->maxSf;
|
|
338
|
+
|
|
339
|
+
|
|
340
|
+ // write the output text file
|
|
341
|
+ if( cmFileIsValid(p->txH) )
|
|
342
|
+ if( cmFilePrintf(p->txH, "[ %i, %f ]\n", smpIdx, p->sfV[fi] ) != kOkFileRC )
|
|
343
|
+ {
|
|
344
|
+ rc = cmErrMsg(&p->err,kDspTextFileFailOnRC,"Text output write to '%s' failed.", cmFileName(p->txH));
|
|
345
|
+ goto errLabel;
|
|
346
|
+ }
|
|
347
|
+ }
|
|
348
|
+
|
|
349
|
+ // write the output audio file
|
|
350
|
+ if( cmAudioFileIsValid(p->afH) && cmAudioFileRdRead(p->afRdPtr) == cmOkRC )
|
|
351
|
+ {
|
|
352
|
+ aoutV[0] = p->afRdPtr->outV;
|
|
353
|
+
|
|
354
|
+ if( cmAudioFileWriteFloat(p->afH, p->hopSmpCnt, kChCnt, aoutV ) != kOkAfRC )
|
|
355
|
+ {
|
|
356
|
+ rc = cmErrMsg(&p->err,kDspAudioFileFailOnRC,"Audio file write to '%s' failed.",cmAudioFileName(p->afH));
|
|
357
|
+ goto errLabel;
|
|
358
|
+ }
|
|
359
|
+ }
|
|
360
|
+
|
|
361
|
+ }
|
|
362
|
+
|
333
|
363
|
// close the output audio file
|
334
|
364
|
if( cmAudioFileDelete(&p->afH) != kOkAfRC )
|
335
|
365
|
rc = cmErrMsg(&p->err,kDspAudioFileFailOnRC,"The audio file close failed.");
|
|
@@ -342,9 +372,11 @@ cmOnRC_t cmOnsetExec( cmOnH_t h, const cmOnsetCfg_t* cfg, const cmChar_t* inAudi
|
342
|
372
|
if( cmFileClose(&p->txH) != kOkFileRC )
|
343
|
373
|
rc = cmErrMsg(&p->err,kDspTextFileFailOnRC,"The text file close failed.");
|
344
|
374
|
}
|
|
375
|
+
|
|
376
|
+ errLabel:
|
345
|
377
|
return rc;
|
346
|
|
-}
|
347
|
378
|
|
|
379
|
+}
|
348
|
380
|
|
349
|
381
|
cmOnRC_t cmOnsetTest( cmCtx_t* c )
|
350
|
382
|
{
|
|
@@ -367,7 +399,9 @@ cmOnRC_t cmOnsetTest( cmCtx_t* c )
|
367
|
399
|
if((rc = cmOnsetInitialize(c,&h)) != kOkOnRC )
|
368
|
400
|
goto errLabel;
|
369
|
401
|
|
370
|
|
- rc = cmOnsetExec(h,&cfg,inAudioFn,outAudioFn,outTextFn);
|
|
402
|
+ if((rc = cmOnsetProc(h,&cfg,inAudioFn)) == kOkOnRC )
|
|
403
|
+ cmOnsetWrite(h,outAudioFn,outTextFn);
|
|
404
|
+
|
371
|
405
|
|
372
|
406
|
errLabel:
|
373
|
407
|
cmOnsetFinalize(&h);
|