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