c@225
|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
c@225
|
2
|
c@225
|
3 /*
|
c@225
|
4 QM DSP Library
|
c@225
|
5
|
c@225
|
6 Centre for Digital Music, Queen Mary, University of London.
|
c@309
|
7 This file 2005-2006 Christian Landone.
|
c@309
|
8
|
mathieu@321
|
9 Modifications:
|
mathieu@321
|
10
|
mathieu@321
|
11 - delta threshold
|
mathieu@321
|
12 Description: add delta threshold used as offset in the smoothed
|
mathieu@321
|
13 detection function
|
mathieu@321
|
14 Author: Mathieu Barthet
|
mathieu@321
|
15 Date: June 2010
|
mathieu@321
|
16
|
c@309
|
17 This program is free software; you can redistribute it and/or
|
c@309
|
18 modify it under the terms of the GNU General Public License as
|
c@309
|
19 published by the Free Software Foundation; either version 2 of the
|
c@309
|
20 License, or (at your option) any later version. See the file
|
mathieu@321
|
21 COPYING included with this distribution for more information.
|
c@225
|
22 */
|
c@225
|
23
|
c@225
|
24 #include "PeakPicking.h"
|
c@241
|
25 #include "maths/Polyfit.h"
|
c@225
|
26
|
c@237
|
27 #include <iostream>
|
c@272
|
28 #include <cstring>
|
c@272
|
29
|
c@225
|
30
|
c@225
|
31 //////////////////////////////////////////////////////////////////////
|
c@225
|
32 // Construction/Destruction
|
c@225
|
33 //////////////////////////////////////////////////////////////////////
|
c@225
|
34
|
c@225
|
35 PeakPicking::PeakPicking( PPickParams Config )
|
c@225
|
36 {
|
c@225
|
37 m_workBuffer = NULL;
|
c@225
|
38 initialise( Config );
|
c@225
|
39 }
|
c@225
|
40
|
c@225
|
41 PeakPicking::~PeakPicking()
|
c@225
|
42 {
|
c@225
|
43 deInitialise();
|
c@225
|
44 }
|
c@225
|
45
|
c@225
|
46 void PeakPicking::initialise( PPickParams Config )
|
c@225
|
47 {
|
c@225
|
48 m_DFLength = Config.length ;
|
c@225
|
49 Qfilta = Config.QuadThresh.a ;
|
c@225
|
50 Qfiltb = Config.QuadThresh.b ;
|
c@225
|
51 Qfiltc = Config.QuadThresh.c ;
|
cannam@483
|
52
|
c@225
|
53 m_DFProcessingParams.length = m_DFLength;
|
c@225
|
54 m_DFProcessingParams.LPOrd = Config.LPOrd;
|
c@225
|
55 m_DFProcessingParams.LPACoeffs = Config.LPACoeffs;
|
c@225
|
56 m_DFProcessingParams.LPBCoeffs = Config.LPBCoeffs;
|
c@225
|
57 m_DFProcessingParams.winPre = Config.WinT.pre;
|
c@225
|
58 m_DFProcessingParams.winPost = Config.WinT.post;
|
c@225
|
59 m_DFProcessingParams.AlphaNormParam = Config.alpha;
|
c@225
|
60 m_DFProcessingParams.isMedianPositive = false;
|
c@410
|
61 m_DFProcessingParams.delta = Config.delta; //add the delta threshold as an adjustable parameter
|
mathieu@321
|
62
|
c@225
|
63 m_DFSmoothing = new DFProcess( m_DFProcessingParams );
|
c@225
|
64
|
c@225
|
65 m_workBuffer = new double[ m_DFLength ];
|
c@225
|
66 memset( m_workBuffer, 0, sizeof(double)*m_DFLength);
|
c@225
|
67 }
|
c@225
|
68
|
c@225
|
69 void PeakPicking::deInitialise()
|
c@225
|
70 {
|
c@225
|
71 delete [] m_workBuffer;
|
c@225
|
72 delete m_DFSmoothing;
|
c@225
|
73 m_workBuffer = NULL;
|
c@225
|
74 }
|
c@225
|
75
|
cannam@499
|
76 void PeakPicking::process( double* src, int len, vector<int> &onsets )
|
c@225
|
77 {
|
c@283
|
78 if (len < 4) return;
|
c@283
|
79
|
cannam@483
|
80 vector <double> m_maxima;
|
c@225
|
81
|
c@225
|
82 // Signal conditioning
|
c@225
|
83 m_DFSmoothing->process( src, m_workBuffer );
|
cannam@483
|
84
|
cannam@499
|
85 for (int i = 0; i < len; i++) {
|
cannam@499
|
86 m_maxima.push_back( m_workBuffer[ i ] );
|
c@225
|
87 }
|
cannam@483
|
88
|
c@225
|
89 quadEval( m_maxima, onsets );
|
c@225
|
90
|
cannam@499
|
91 for( int b = 0; b < (int)m_maxima.size(); b++) {
|
cannam@483
|
92 src[ b ] = m_maxima[ b ];
|
c@225
|
93 }
|
c@225
|
94 }
|
c@225
|
95
|
c@225
|
96 int PeakPicking::quadEval( vector<double> &src, vector<int> &idx )
|
c@225
|
97 {
|
cannam@499
|
98 int maxLength;
|
c@225
|
99
|
c@225
|
100 vector <int> m_maxIndex;
|
c@225
|
101 vector <int> m_onsetPosition;
|
cannam@483
|
102
|
c@225
|
103 vector <double> m_maxFit;
|
c@225
|
104 vector <double> m_poly;
|
c@225
|
105 vector <double> m_err;
|
c@225
|
106
|
c@225
|
107 m_poly.push_back(0);
|
c@225
|
108 m_poly.push_back(0);
|
c@225
|
109 m_poly.push_back(0);
|
c@225
|
110
|
cannam@499
|
111 for (int t = -2; t < 3; t++) {
|
cannam@483
|
112 m_err.push_back( (double)t );
|
c@225
|
113 }
|
cannam@483
|
114
|
cannam@499
|
115 for (int i = 2; i < int(src.size()) - 2; i++) {
|
cannam@499
|
116 if ((src[i] > src[i-1]) && (src[i] > src[i+1]) && (src[i] > 0) ) {
|
c@237
|
117 m_maxIndex.push_back(i);
|
cannam@483
|
118 }
|
c@225
|
119 }
|
c@225
|
120
|
cannam@499
|
121 maxLength = int(m_maxIndex.size());
|
c@225
|
122
|
c@225
|
123 double selMax = 0;
|
c@225
|
124
|
cannam@499
|
125 for (int j = 0; j < maxLength ; j++) {
|
cannam@483
|
126 for (int k = -2; k <= 2; ++k) {
|
cannam@483
|
127 selMax = src[ m_maxIndex[j] + k ] ;
|
cannam@483
|
128 m_maxFit.push_back(selMax);
|
cannam@483
|
129 }
|
c@225
|
130
|
cannam@483
|
131 TPolyFit::PolyFit2(m_err, m_maxFit, m_poly);
|
c@225
|
132
|
cannam@483
|
133 double f = m_poly[0];
|
cannam@483
|
134 double h = m_poly[2];
|
c@225
|
135
|
cannam@483
|
136 if (h < -Qfilta || f > Qfiltc) {
|
cannam@483
|
137 idx.push_back(m_maxIndex[j]);
|
cannam@483
|
138 }
|
cannam@483
|
139
|
cannam@483
|
140 m_maxFit.clear();
|
c@225
|
141 }
|
c@225
|
142
|
c@225
|
143 return 1;
|
c@225
|
144 }
|