Chris@181
|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
Chris@181
|
2
|
Chris@181
|
3 /*
|
Chris@181
|
4 Silvet
|
Chris@181
|
5
|
Chris@181
|
6 A Vamp plugin for note transcription.
|
Chris@181
|
7 Centre for Digital Music, Queen Mary University of London.
|
Chris@181
|
8 This file Copyright 2012 Chris Cannam.
|
Chris@181
|
9
|
Chris@181
|
10 This program is free software; you can redistribute it and/or
|
Chris@181
|
11 modify it under the terms of the GNU General Public License as
|
Chris@181
|
12 published by the Free Software Foundation; either version 2 of the
|
Chris@181
|
13 License, or (at your option) any later version. See the file
|
Chris@181
|
14 COPYING included with this distribution for more information.
|
Chris@181
|
15 */
|
Chris@181
|
16
|
Chris@181
|
17 #ifndef NOTE_HYPOTHESIS_H
|
Chris@181
|
18 #define NOTE_HYPOTHESIS_H
|
Chris@181
|
19
|
Chris@181
|
20 #include "AgentHypothesis.h"
|
Chris@181
|
21
|
Chris@181
|
22 #include <set>
|
Chris@181
|
23 #include <vector>
|
Chris@181
|
24
|
Chris@181
|
25 /**
|
Chris@181
|
26 * An AgentHypothesis which tests a series of instantaneous pitch
|
Chris@181
|
27 * estimates to see whether they fit a single-note relationship.
|
Chris@181
|
28 * Contains rules specific to testing note pitch and timing.
|
Chris@181
|
29 */
|
Chris@181
|
30
|
Chris@181
|
31 class NoteHypothesis : public AgentHypothesis
|
Chris@181
|
32 {
|
Chris@181
|
33 public:
|
Chris@181
|
34 /**
|
Chris@181
|
35 * Construct an empty hypothesis. This will be in New state and
|
Chris@181
|
36 * will provisionally accept any estimate.
|
Chris@181
|
37 */
|
Chris@181
|
38 NoteHypothesis();
|
Chris@181
|
39
|
Chris@181
|
40 /**
|
Chris@181
|
41 * Destroy the hypothesis
|
Chris@181
|
42 */
|
Chris@181
|
43 ~NoteHypothesis();
|
Chris@181
|
44
|
Chris@181
|
45 virtual bool accept(Observation);
|
Chris@181
|
46 virtual State getState() const;
|
Chris@181
|
47 virtual Observations getAcceptedObservations() const;
|
Chris@181
|
48
|
Chris@181
|
49 struct Note {
|
Chris@181
|
50 Note() : freq(0), time(), duration() { }
|
Chris@181
|
51 Note(double _f, Vamp::RealTime _t, Vamp::RealTime _d) :
|
Chris@181
|
52 freq(_f), time(_t), duration(_d) { }
|
Chris@181
|
53 bool operator==(const Note &e) const {
|
Chris@181
|
54 return e.freq == freq && e.time == time && e.duration == duration;
|
Chris@181
|
55 }
|
Chris@181
|
56 double freq;
|
Chris@181
|
57 Vamp::RealTime time;
|
Chris@181
|
58 Vamp::RealTime duration;
|
Chris@181
|
59 };
|
Chris@181
|
60
|
Chris@181
|
61 /**
|
Chris@181
|
62 * Return the mean frequency of the accepted observations
|
Chris@181
|
63 */
|
Chris@181
|
64 double getMeanFrequency() const;
|
Chris@181
|
65
|
Chris@181
|
66 /**
|
Chris@181
|
67 * Return a single note roughly matching this hypothesis
|
Chris@181
|
68 */
|
Chris@181
|
69 Note getAveragedNote() const;
|
Chris@181
|
70
|
Chris@181
|
71 /**
|
Chris@181
|
72 * Return the time of the first accepted observation
|
Chris@181
|
73 */
|
Chris@181
|
74 Vamp::RealTime getStartTime() const;
|
Chris@181
|
75
|
Chris@181
|
76 /**
|
Chris@181
|
77 * Return the difference between the start time and the end of the
|
Chris@181
|
78 * final accepted observation
|
Chris@181
|
79 */
|
Chris@181
|
80 Vamp::RealTime getDuration() const;
|
Chris@181
|
81
|
Chris@181
|
82 /**
|
Chris@181
|
83 * Convert the given sequence of accepted hypotheses into a
|
Chris@181
|
84 * sampled series of pitches (in Hz), returned at regular
|
Chris@181
|
85 * intervals determined by the given start time, end time, and
|
Chris@181
|
86 * interval. The range is [start,end], i.e. the end time is
|
Chris@181
|
87 * included. The interval must be greater than zero.
|
Chris@181
|
88 *
|
Chris@181
|
89 * Unvoiced samples are returned as 0Hz.
|
Chris@181
|
90 */
|
Chris@181
|
91 static std::vector<double> sample(const std::set<NoteHypothesis> &,
|
Chris@181
|
92 Vamp::RealTime startTime,
|
Chris@181
|
93 Vamp::RealTime endTime,
|
Chris@181
|
94 Vamp::RealTime interval);
|
Chris@181
|
95
|
Chris@181
|
96 /**
|
Chris@181
|
97 *!!! No! Not equally spaced, should be able to be anything [ordered]
|
Chris@181
|
98
|
Chris@181
|
99 * Given a series of equally spaced observations, return a series
|
Chris@181
|
100 * of the same number of pitches (in Hz) calculated by running an
|
Chris@181
|
101 * AgentFeeder<NoteHypothesis> on the observations and flattening
|
Chris@181
|
102 * and sampling the resulting accepted hypotheses.
|
Chris@181
|
103 *
|
Chris@181
|
104 * The result should contain only pitches that contributed to
|
Chris@181
|
105 * recognised notes in the input observations, with the remaining
|
Chris@181
|
106 * (unvoiced) samples returned as 0Hz.
|
Chris@181
|
107 *
|
Chris@181
|
108 * If the input observations are not equally spaced, the result is
|
Chris@181
|
109 * undefined.
|
Chris@181
|
110 *!!! (what about rounding errors from RealTime to frame and vice versa?)
|
Chris@181
|
111 *!!! (should provide a Timebase?)
|
Chris@181
|
112 *!!! update docs for updated api
|
Chris@181
|
113 */
|
Chris@181
|
114 static std::vector<double> winnow(const Observations &,
|
Chris@181
|
115 Vamp::RealTime startTime,
|
Chris@181
|
116 Vamp::RealTime endTime,
|
Chris@181
|
117 Vamp::RealTime interval);
|
Chris@181
|
118
|
Chris@181
|
119 //!!!
|
Chris@181
|
120 bool operator==(const NoteHypothesis &other) const {
|
Chris@181
|
121 return m_state == other.m_state && m_pending == other.m_pending;
|
Chris@181
|
122 }
|
Chris@181
|
123
|
Chris@181
|
124 bool operator<(const NoteHypothesis &other) const {
|
Chris@181
|
125 return getStartTime() < other.getStartTime();
|
Chris@181
|
126 }
|
Chris@181
|
127
|
Chris@181
|
128 private:
|
Chris@181
|
129 bool isWithinTolerance(Observation) const;
|
Chris@181
|
130 bool isOutOfDateFor(Observation) const;
|
Chris@181
|
131 bool isSatisfied() const;
|
Chris@181
|
132
|
Chris@181
|
133 State m_state;
|
Chris@181
|
134 Observations m_pending;
|
Chris@181
|
135 };
|
Chris@181
|
136
|
Chris@181
|
137 #endif
|