Chris@0
|
1
|
Chris@0
|
2 #include "TuningDifference.h"
|
Chris@0
|
3
|
Chris@1
|
4 #include <iostream>
|
Chris@1
|
5
|
Chris@1
|
6 using std::cerr;
|
Chris@1
|
7 using std::endl;
|
Chris@1
|
8
|
Chris@0
|
9
|
Chris@0
|
10 TuningDifference::TuningDifference(float inputSampleRate) :
|
Chris@0
|
11 Plugin(inputSampleRate)
|
Chris@0
|
12 {
|
Chris@0
|
13 }
|
Chris@0
|
14
|
Chris@0
|
15 TuningDifference::~TuningDifference()
|
Chris@0
|
16 {
|
Chris@0
|
17 }
|
Chris@0
|
18
|
Chris@0
|
19 string
|
Chris@0
|
20 TuningDifference::getIdentifier() const
|
Chris@0
|
21 {
|
Chris@1
|
22 return "tuning-difference";
|
Chris@0
|
23 }
|
Chris@0
|
24
|
Chris@0
|
25 string
|
Chris@0
|
26 TuningDifference::getName() const
|
Chris@0
|
27 {
|
Chris@1
|
28 return "Tuning Difference";
|
Chris@0
|
29 }
|
Chris@0
|
30
|
Chris@0
|
31 string
|
Chris@0
|
32 TuningDifference::getDescription() const
|
Chris@0
|
33 {
|
Chris@0
|
34 // Return something helpful here!
|
Chris@0
|
35 return "";
|
Chris@0
|
36 }
|
Chris@0
|
37
|
Chris@0
|
38 string
|
Chris@0
|
39 TuningDifference::getMaker() const
|
Chris@0
|
40 {
|
Chris@0
|
41 // Your name here
|
Chris@0
|
42 return "";
|
Chris@0
|
43 }
|
Chris@0
|
44
|
Chris@0
|
45 int
|
Chris@0
|
46 TuningDifference::getPluginVersion() const
|
Chris@0
|
47 {
|
Chris@0
|
48 // Increment this each time you release a version that behaves
|
Chris@0
|
49 // differently from the previous one
|
Chris@0
|
50 return 1;
|
Chris@0
|
51 }
|
Chris@0
|
52
|
Chris@0
|
53 string
|
Chris@0
|
54 TuningDifference::getCopyright() const
|
Chris@0
|
55 {
|
Chris@0
|
56 // This function is not ideally named. It does not necessarily
|
Chris@0
|
57 // need to say who made the plugin -- getMaker does that -- but it
|
Chris@0
|
58 // should indicate the terms under which it is distributed. For
|
Chris@0
|
59 // example, "Copyright (year). All Rights Reserved", or "GPL"
|
Chris@0
|
60 return "";
|
Chris@0
|
61 }
|
Chris@0
|
62
|
Chris@0
|
63 TuningDifference::InputDomain
|
Chris@0
|
64 TuningDifference::getInputDomain() const
|
Chris@0
|
65 {
|
Chris@1
|
66 return FrequencyDomain;
|
Chris@0
|
67 }
|
Chris@0
|
68
|
Chris@0
|
69 size_t
|
Chris@0
|
70 TuningDifference::getPreferredBlockSize() const
|
Chris@0
|
71 {
|
Chris@2
|
72 return 16384;
|
Chris@0
|
73 }
|
Chris@0
|
74
|
Chris@0
|
75 size_t
|
Chris@0
|
76 TuningDifference::getPreferredStepSize() const
|
Chris@0
|
77 {
|
Chris@1
|
78 return 0;
|
Chris@0
|
79 }
|
Chris@0
|
80
|
Chris@0
|
81 size_t
|
Chris@0
|
82 TuningDifference::getMinChannelCount() const
|
Chris@0
|
83 {
|
Chris@1
|
84 return 2;
|
Chris@0
|
85 }
|
Chris@0
|
86
|
Chris@0
|
87 size_t
|
Chris@0
|
88 TuningDifference::getMaxChannelCount() const
|
Chris@0
|
89 {
|
Chris@1
|
90 return 2;
|
Chris@0
|
91 }
|
Chris@0
|
92
|
Chris@0
|
93 TuningDifference::ParameterList
|
Chris@0
|
94 TuningDifference::getParameterDescriptors() const
|
Chris@0
|
95 {
|
Chris@0
|
96 ParameterList list;
|
Chris@0
|
97 return list;
|
Chris@0
|
98 }
|
Chris@0
|
99
|
Chris@0
|
100 float
|
Chris@1
|
101 TuningDifference::getParameter(string) const
|
Chris@0
|
102 {
|
Chris@0
|
103 return 0;
|
Chris@0
|
104 }
|
Chris@0
|
105
|
Chris@0
|
106 void
|
Chris@1
|
107 TuningDifference::setParameter(string, float)
|
Chris@0
|
108 {
|
Chris@0
|
109 }
|
Chris@0
|
110
|
Chris@0
|
111 TuningDifference::ProgramList
|
Chris@0
|
112 TuningDifference::getPrograms() const
|
Chris@0
|
113 {
|
Chris@0
|
114 ProgramList list;
|
Chris@0
|
115 return list;
|
Chris@0
|
116 }
|
Chris@0
|
117
|
Chris@0
|
118 string
|
Chris@0
|
119 TuningDifference::getCurrentProgram() const
|
Chris@0
|
120 {
|
Chris@0
|
121 return ""; // no programs
|
Chris@0
|
122 }
|
Chris@0
|
123
|
Chris@0
|
124 void
|
Chris@1
|
125 TuningDifference::selectProgram(string)
|
Chris@0
|
126 {
|
Chris@0
|
127 }
|
Chris@0
|
128
|
Chris@0
|
129 TuningDifference::OutputList
|
Chris@0
|
130 TuningDifference::getOutputDescriptors() const
|
Chris@0
|
131 {
|
Chris@0
|
132 OutputList list;
|
Chris@0
|
133
|
Chris@1
|
134 OutputDescriptor d;
|
Chris@1
|
135 d.identifier = "cents";
|
Chris@1
|
136 d.name = "Tuning Difference";
|
Chris@1
|
137 d.description = "Difference in averaged frequency profile between channels 1 and 2, in cents. A positive value means channel 2 is higher.";
|
Chris@1
|
138 d.unit = "cents";
|
Chris@1
|
139 d.hasFixedBinCount = true;
|
Chris@1
|
140 d.binCount = 1;
|
Chris@1
|
141 d.hasKnownExtents = false;
|
Chris@1
|
142 d.isQuantized = false;
|
Chris@1
|
143 d.sampleType = OutputDescriptor::VariableSampleRate;
|
Chris@1
|
144 d.hasDuration = false;
|
Chris@1
|
145 list.push_back(d);
|
Chris@0
|
146
|
Chris@1
|
147 d.identifier = "tuningfreq";
|
Chris@1
|
148 d.name = "Relative Tuning Frequency";
|
Chris@1
|
149 d.description = "Tuning frequency of channel 2, if channel 1 is assumed to contain the same music as it at a tuning frequency of A=440Hz.";
|
Chris@1
|
150 d.unit = "cents";
|
Chris@1
|
151 d.hasFixedBinCount = true;
|
Chris@1
|
152 d.binCount = 1;
|
Chris@1
|
153 d.hasKnownExtents = false;
|
Chris@1
|
154 d.isQuantized = false;
|
Chris@1
|
155 d.sampleType = OutputDescriptor::VariableSampleRate;
|
Chris@1
|
156 d.hasDuration = false;
|
Chris@1
|
157 list.push_back(d);
|
Chris@1
|
158
|
Chris@1
|
159 d.identifier = "correlation";
|
Chris@1
|
160 d.name = "Frequency-shift correlation curve";
|
Chris@0
|
161 d.description = "";
|
Chris@0
|
162 d.unit = "";
|
Chris@0
|
163 d.hasFixedBinCount = true;
|
Chris@0
|
164 d.binCount = 1;
|
Chris@0
|
165 d.hasKnownExtents = false;
|
Chris@0
|
166 d.isQuantized = false;
|
Chris@1
|
167 d.sampleType = OutputDescriptor::FixedSampleRate;
|
Chris@1
|
168 d.sampleRate = 100;
|
Chris@0
|
169 d.hasDuration = false;
|
Chris@0
|
170 list.push_back(d);
|
Chris@0
|
171
|
Chris@0
|
172 return list;
|
Chris@0
|
173 }
|
Chris@0
|
174
|
Chris@0
|
175 bool
|
Chris@0
|
176 TuningDifference::initialise(size_t channels, size_t stepSize, size_t blockSize)
|
Chris@0
|
177 {
|
Chris@0
|
178 if (channels < getMinChannelCount() ||
|
Chris@0
|
179 channels > getMaxChannelCount()) return false;
|
Chris@0
|
180
|
Chris@1
|
181 if (blockSize != getPreferredBlockSize() ||
|
Chris@1
|
182 stepSize != blockSize/2) return false;
|
Chris@0
|
183
|
Chris@1
|
184 m_blockSize = blockSize;
|
Chris@1
|
185
|
Chris@1
|
186 reset();
|
Chris@1
|
187
|
Chris@0
|
188 return true;
|
Chris@0
|
189 }
|
Chris@0
|
190
|
Chris@0
|
191 void
|
Chris@0
|
192 TuningDifference::reset()
|
Chris@0
|
193 {
|
Chris@1
|
194 m_sum[0].clear();
|
Chris@1
|
195 m_sum[1].clear();
|
Chris@1
|
196 m_frameCount = 0;
|
Chris@0
|
197 }
|
Chris@0
|
198
|
Chris@0
|
199 TuningDifference::FeatureSet
|
Chris@0
|
200 TuningDifference::process(const float *const *inputBuffers, Vamp::RealTime timestamp)
|
Chris@0
|
201 {
|
Chris@1
|
202 for (int c = 0; c < 2; ++c) {
|
Chris@1
|
203 m_sum[c].resize(m_blockSize/2 - 1);
|
Chris@1
|
204 for (int i = 1; i < m_blockSize/2; ++i) { // discarding DC and Nyquist
|
Chris@1
|
205 double energy =
|
Chris@1
|
206 inputBuffers[c][i*2 ] * inputBuffers[c][i*2 ] +
|
Chris@1
|
207 inputBuffers[c][i*2+1] * inputBuffers[c][i*2+1];
|
Chris@1
|
208 m_sum[c][i-1] += energy;
|
Chris@1
|
209 }
|
Chris@1
|
210 }
|
Chris@1
|
211
|
Chris@1
|
212 ++m_frameCount;
|
Chris@0
|
213 return FeatureSet();
|
Chris@0
|
214 }
|
Chris@0
|
215
|
Chris@0
|
216 TuningDifference::FeatureSet
|
Chris@0
|
217 TuningDifference::getRemainingFeatures()
|
Chris@0
|
218 {
|
Chris@1
|
219 int n = m_sum[0].size();
|
Chris@1
|
220 if (n == 0) return FeatureSet();
|
Chris@1
|
221
|
Chris@1
|
222 Feature f;
|
Chris@1
|
223 FeatureSet fs;
|
Chris@1
|
224
|
Chris@1
|
225 vector<double> corr(n * 2 - 1, 0.0);
|
Chris@1
|
226 for (int shift = -(n-1); shift <= n-1; ++shift) {
|
Chris@1
|
227 int index = shift + n-1;
|
Chris@1
|
228 int count = 0;
|
Chris@2
|
229 // cerr << "index = " << index << ", n = " << n << endl;
|
Chris@1
|
230 for (int i = 0; i < n; ++i) {
|
Chris@1
|
231 int j = i + shift;
|
Chris@1
|
232 if (j >= 0 && j < n) {
|
Chris@1
|
233 corr[index] += m_sum[1][i] * m_sum[0][j];
|
Chris@1
|
234 ++count;
|
Chris@1
|
235 }
|
Chris@1
|
236 }
|
Chris@1
|
237 if (count > 0) {
|
Chris@1
|
238 corr[index] /= count;
|
Chris@1
|
239 }
|
Chris@1
|
240 f.values.clear();
|
Chris@2
|
241 // cerr << "value = " << corr[index] << endl;
|
Chris@1
|
242 f.values.push_back(corr[index]);
|
Chris@1
|
243 fs[2].push_back(f);
|
Chris@1
|
244 }
|
Chris@1
|
245
|
Chris@1
|
246 return fs;
|
Chris@0
|
247 }
|
Chris@0
|
248
|