Chris@32
|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
Chris@37
|
2 /*
|
Chris@37
|
3 This file is Copyright (c) 2012 Chris Cannam
|
Chris@37
|
4
|
Chris@37
|
5 Permission is hereby granted, free of charge, to any person
|
Chris@37
|
6 obtaining a copy of this software and associated documentation
|
Chris@37
|
7 files (the "Software"), to deal in the Software without
|
Chris@37
|
8 restriction, including without limitation the rights to use, copy,
|
Chris@37
|
9 modify, merge, publish, distribute, sublicense, and/or sell copies
|
Chris@37
|
10 of the Software, and to permit persons to whom the Software is
|
Chris@37
|
11 furnished to do so, subject to the following conditions:
|
Chris@37
|
12
|
Chris@37
|
13 The above copyright notice and this permission notice shall be
|
Chris@37
|
14 included in all copies or substantial portions of the Software.
|
Chris@37
|
15
|
Chris@37
|
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
Chris@37
|
17 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
Chris@37
|
18 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
Chris@37
|
19 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
|
Chris@37
|
20 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
Chris@37
|
21 CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
Chris@37
|
22 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
Chris@37
|
23 */
|
Chris@32
|
24
|
Chris@32
|
25 #ifndef _NOTE_HYPOTHESIS_H_
|
Chris@32
|
26 #define _NOTE_HYPOTHESIS_H_
|
Chris@32
|
27
|
Chris@35
|
28 #include "vamp-sdk/RealTime.h"
|
Chris@32
|
29 #include <vector>
|
Chris@32
|
30
|
Chris@32
|
31 /**
|
Chris@32
|
32 * An agent used to test an incoming series of instantaneous pitch
|
Chris@32
|
33 * estimates to see whether they fit a consistent single-note
|
Chris@32
|
34 * relationship. Contains rules specific to testing note pitch and
|
Chris@32
|
35 * timing.
|
Chris@32
|
36 */
|
Chris@32
|
37
|
Chris@32
|
38 class NoteHypothesis
|
Chris@32
|
39 {
|
Chris@32
|
40 public:
|
Chris@32
|
41 enum State {
|
Chris@32
|
42
|
Chris@45
|
43 /// Just constructed, will provisionally accept any estimate
|
Chris@45
|
44 New,
|
Chris@32
|
45
|
Chris@45
|
46 /// Accepted at least one estimate, but not enough evidence to satisfy
|
Chris@45
|
47 Provisional,
|
Chris@32
|
48
|
Chris@45
|
49 /// Could not find enough consistency in offered estimates
|
Chris@45
|
50 Rejected,
|
Chris@32
|
51
|
Chris@45
|
52 /// Have accepted enough consistent estimates to satisfy hypothesis
|
Chris@45
|
53 Satisfied,
|
Chris@32
|
54
|
Chris@45
|
55 /// Have been satisfied, but evidence has now changed: we're done
|
Chris@45
|
56 Expired
|
Chris@32
|
57 };
|
Chris@32
|
58
|
Chris@32
|
59 /**
|
Chris@66
|
60 * Construct an empty hypothesis. The given slack (in
|
Chris@66
|
61 * milliseconds) determines how long the hypothesis is prepared to
|
Chris@66
|
62 * tolerate unacceptable estimates in between accepted estimates
|
Chris@66
|
63 * before it becomes rejected. A reasonable default is 40ms.
|
Chris@66
|
64 *
|
Chris@66
|
65 * This hypothesis will be in New state and will provisionally
|
Chris@66
|
66 * accept any estimate.
|
Chris@32
|
67 */
|
Chris@66
|
68 NoteHypothesis(float slack);
|
Chris@32
|
69
|
Chris@32
|
70 /**
|
Chris@32
|
71 * Destroy the hypothesis
|
Chris@32
|
72 */
|
Chris@32
|
73 ~NoteHypothesis();
|
Chris@32
|
74
|
Chris@32
|
75 struct Estimate {
|
Chris@58
|
76 Estimate() : freq(0), time(), confidence(1) { }
|
Chris@35
|
77 Estimate(double _f, Vamp::RealTime _t, double _c) :
|
Chris@33
|
78 freq(_f), time(_t), confidence(_c) { }
|
Chris@34
|
79 bool operator==(const Estimate &e) const {
|
Chris@34
|
80 return e.freq == freq && e.time == time && e.confidence == confidence;
|
Chris@34
|
81 }
|
Chris@45
|
82 double freq;
|
Chris@35
|
83 Vamp::RealTime time;
|
Chris@45
|
84 double confidence;
|
Chris@32
|
85 };
|
Chris@32
|
86 typedef std::vector<Estimate> Estimates;
|
Chris@32
|
87
|
Chris@32
|
88 /**
|
Chris@32
|
89 * Test the given estimate to see whether it is consistent with
|
Chris@32
|
90 * this hypothesis, and adjust the hypothesis' internal state
|
Chris@32
|
91 * accordingly. If the estimate is not inconsistent with the
|
Chris@32
|
92 * hypothesis, return true.
|
Chris@32
|
93 */
|
Chris@32
|
94 bool accept(Estimate);
|
Chris@32
|
95
|
Chris@32
|
96 /**
|
Chris@32
|
97 * Return the current state of this hypothesis.
|
Chris@32
|
98 */
|
Chris@32
|
99 State getState() const;
|
Chris@32
|
100
|
Chris@32
|
101 /**
|
Chris@32
|
102 * If the hypothesis has been satisfied (i.e. is in Satisfied or
|
Chris@32
|
103 * Expired state), return the series of estimates that it
|
Chris@32
|
104 * accepted. Otherwise return an empty list
|
Chris@32
|
105 */
|
Chris@32
|
106 Estimates getAcceptedEstimates() const;
|
Chris@32
|
107
|
Chris@32
|
108 struct Note {
|
Chris@33
|
109 Note() : freq(0), time(), duration() { }
|
Chris@35
|
110 Note(double _f, Vamp::RealTime _t, Vamp::RealTime _d) :
|
Chris@33
|
111 freq(_f), time(_t), duration(_d) { }
|
Chris@34
|
112 bool operator==(const Note &e) const {
|
Chris@34
|
113 return e.freq == freq && e.time == time && e.duration == duration;
|
Chris@34
|
114 }
|
Chris@45
|
115 double freq;
|
Chris@45
|
116 Vamp::RealTime time;
|
Chris@45
|
117 Vamp::RealTime duration;
|
Chris@32
|
118 };
|
Chris@32
|
119
|
Chris@32
|
120 /**
|
Chris@52
|
121 * Return the time of the first accepted estimate
|
Chris@52
|
122 */
|
Chris@52
|
123 Vamp::RealTime getStartTime() const;
|
Chris@52
|
124
|
Chris@52
|
125 /**
|
Chris@34
|
126 * Return the mean frequency of the accepted estimates
|
Chris@34
|
127 */
|
Chris@34
|
128 double getMeanFrequency() const;
|
Chris@34
|
129
|
Chris@34
|
130 /**
|
Chris@32
|
131 * Return a single note roughly matching this hypothesis
|
Chris@32
|
132 */
|
Chris@32
|
133 Note getAveragedNote() const;
|
Chris@32
|
134
|
Chris@32
|
135 private:
|
Chris@32
|
136 bool isWithinTolerance(Estimate) const;
|
Chris@32
|
137 bool isOutOfDateFor(Estimate) const;
|
Chris@32
|
138 bool isSatisfied() const;
|
Chris@32
|
139
|
Chris@32
|
140 State m_state;
|
Chris@32
|
141 Estimates m_pending;
|
Chris@66
|
142 float m_slack;
|
Chris@32
|
143 };
|
Chris@32
|
144
|
Chris@32
|
145 #endif
|