To check out this repository please hg clone the following URL, or open the URL using EasyMercurial or your preferred Mercurial client.

Statistics Download as Zip
| Branch: | Tag: | Revision:

root / NoteHypothesis.cpp @ 35:2f5b169e4a3b

History | View | Annotate | Download (3.4 KB)

1
/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
2
/* Copyright Chris Cannam - All Rights Reserved */
3

    
4
#include "NoteHypothesis.h"
5

    
6
#include <cmath>
7

    
8
using Vamp::RealTime;
9

    
10
NoteHypothesis::NoteHypothesis()
11
{
12
    m_state = New;
13
}
14

    
15
NoteHypothesis::~NoteHypothesis()
16
{
17
}
18

    
19
bool
20
NoteHypothesis::isWithinTolerance(Estimate s) const
21
{
22
    if (m_pending.empty()) {
23
        return true;
24
    }
25

    
26
    // check we are within a relatively close tolerance of the last
27
    // candidate
28
    Estimate last = m_pending[m_pending.size()-1];
29
    double r = s.freq / last.freq;
30
    int cents = lrint(1200.0 * (log(r) / log(2.0)));
31
    if (cents < -60 || cents > 60) return false;
32

    
33
    // and within a slightly bigger tolerance of the current mean
34
    double meanFreq = getMeanFrequency();
35
    r = s.freq / meanFreq;
36
    cents = lrint(1200.0 * (log(r) / log(2.0)));
37
    if (cents < -80 || cents > 80) return false;
38
    
39
    return true;
40
}
41

    
42
bool
43
NoteHypothesis::isOutOfDateFor(Estimate s) const
44
{
45
    if (m_pending.empty()) return false;
46

    
47
    return ((s.time - m_pending[m_pending.size()-1].time) > 
48
            RealTime::fromMilliseconds(40));
49
}
50

    
51
bool 
52
NoteHypothesis::isSatisfied() const
53
{
54
    if (m_pending.empty()) return false;
55
    
56
    double meanConfidence = 0.0;
57
    for (int i = 0; i < (int)m_pending.size(); ++i) {
58
        meanConfidence += m_pending[i].confidence;
59
    }
60
    meanConfidence /= m_pending.size();
61

    
62
    int lengthRequired = 10000;
63
    if (meanConfidence > 0.0) {
64
        lengthRequired = int(2.0 / meanConfidence + 0.5);
65
    }
66

    
67
    return ((int)m_pending.size() > lengthRequired);
68
}
69

    
70
bool
71
NoteHypothesis::accept(Estimate s)
72
{
73
    bool accept = false;
74

    
75
    switch (m_state) {
76

    
77
    case New:
78
        m_state = Provisional;
79
        accept = true;
80
        break;
81

    
82
    case Provisional:
83
        if (isOutOfDateFor(s)) {
84
            m_state = Rejected;
85
        } else if (isWithinTolerance(s)) {
86
            accept = true;
87
        }
88
        break;
89
        
90
    case Satisfied:
91
        if (isOutOfDateFor(s)) {
92
            m_state = Expired;
93
        } else if (isWithinTolerance(s)) {
94
            accept = true;
95
        }
96
        break;
97

    
98
    case Rejected:
99
        break;
100

    
101
    case Expired:
102
        break;
103
    }
104

    
105
    if (accept) {
106
        m_pending.push_back(s);
107
        if (m_state == Provisional && isSatisfied()) {
108
            m_state = Satisfied;
109
        }
110
    }
111

    
112
    return accept;
113
}        
114

    
115
NoteHypothesis::State
116
NoteHypothesis::getState() const
117
{
118
    return m_state;
119
}
120

    
121
NoteHypothesis::Estimates
122
NoteHypothesis::getAcceptedEstimates() const
123
{
124
    if (m_state == Satisfied || m_state == Expired) {
125
        return m_pending;
126
    } else {
127
        return Estimates();
128
    }
129
}
130

    
131
double
132
NoteHypothesis::getMeanFrequency() const
133
{
134
    double acc = 0.0;
135
    if (m_pending.empty()) return acc;
136
    for (int i = 0; i < (int)m_pending.size(); ++i) {
137
        acc += m_pending[i].freq;
138
    }
139
    acc /= m_pending.size();
140
    return acc;
141
}
142

    
143
NoteHypothesis::Note
144
NoteHypothesis::getAveragedNote() const
145
{
146
    Note n;
147

    
148
    if (!(m_state == Satisfied || m_state == Expired)) {
149
        n.freq = 0.0;
150
        n.time = RealTime::zeroTime;
151
        n.duration = RealTime::zeroTime;
152
        return n;
153
    }
154

    
155
    n.time = m_pending.begin()->time;
156

    
157
    Estimates::const_iterator i = m_pending.end();
158
    --i;
159
    n.duration = i->time - n.time;
160

    
161
    // just mean frequency for now, but this isn't at all right perceptually
162
    n.freq = getMeanFrequency();
163
    
164
    return n;
165
}
166