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 @ 34:3fb9c657d86b

History | View | Annotate | Download (3.43 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
#include "system/sysutils.h"
9

    
10
namespace Turbot {
11

    
12
NoteHypothesis::NoteHypothesis()
13
{
14
    m_state = New;
15
}
16

    
17
NoteHypothesis::~NoteHypothesis()
18
{
19
}
20

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

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

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

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

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

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

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

    
69
    return ((int)m_pending.size() > lengthRequired);
70
}
71

    
72
bool
73
NoteHypothesis::accept(Estimate s)
74
{
75
    bool accept = false;
76

    
77
    switch (m_state) {
78

    
79
    case New:
80
        m_state = Provisional;
81
        accept = true;
82
        break;
83

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

    
100
    case Rejected:
101
        break;
102

    
103
    case Expired:
104
        break;
105
    }
106

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

    
114
    return accept;
115
}        
116

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

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

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

    
145
NoteHypothesis::Note
146
NoteHypothesis::getAveragedNote() const
147
{
148
    Note n;
149

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

    
157
    n.time = m_pending.begin()->time;
158

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

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

    
169
}
170