Chris@32: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ Chris@37: /* Chris@37: This file is Copyright (c) 2012 Chris Cannam Chris@37: Chris@37: Permission is hereby granted, free of charge, to any person Chris@37: obtaining a copy of this software and associated documentation Chris@37: files (the "Software"), to deal in the Software without Chris@37: restriction, including without limitation the rights to use, copy, Chris@37: modify, merge, publish, distribute, sublicense, and/or sell copies Chris@37: of the Software, and to permit persons to whom the Software is Chris@37: furnished to do so, subject to the following conditions: Chris@37: Chris@37: The above copyright notice and this permission notice shall be Chris@37: included in all copies or substantial portions of the Software. Chris@37: Chris@37: THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, Chris@37: EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF Chris@37: MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND Chris@37: NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR Chris@37: ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF Chris@37: CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION Chris@37: WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Chris@37: */ Chris@32: Chris@32: #ifndef _NOTE_HYPOTHESIS_H_ Chris@32: #define _NOTE_HYPOTHESIS_H_ Chris@32: Chris@35: #include "vamp-sdk/RealTime.h" Chris@32: #include Chris@32: Chris@32: /** Chris@32: * An agent used to test an incoming series of instantaneous pitch Chris@32: * estimates to see whether they fit a consistent single-note Chris@32: * relationship. Contains rules specific to testing note pitch and Chris@32: * timing. Chris@32: */ Chris@32: Chris@32: class NoteHypothesis Chris@32: { Chris@32: public: Chris@32: enum State { Chris@32: Chris@45: /// Just constructed, will provisionally accept any estimate Chris@45: New, Chris@32: Chris@45: /// Accepted at least one estimate, but not enough evidence to satisfy Chris@45: Provisional, Chris@32: Chris@45: /// Could not find enough consistency in offered estimates Chris@45: Rejected, Chris@32: Chris@45: /// Have accepted enough consistent estimates to satisfy hypothesis Chris@45: Satisfied, Chris@32: Chris@45: /// Have been satisfied, but evidence has now changed: we're done Chris@45: Expired Chris@32: }; Chris@32: Chris@32: /** Chris@32: * Construct an empty hypothesis. This will be in New state and Chris@32: * will provisionally accept any estimate. Chris@32: */ Chris@32: NoteHypothesis(); Chris@32: Chris@32: /** Chris@32: * Destroy the hypothesis Chris@32: */ Chris@32: ~NoteHypothesis(); Chris@32: Chris@32: struct Estimate { Chris@58: Estimate() : freq(0), time(), confidence(1) { } Chris@35: Estimate(double _f, Vamp::RealTime _t, double _c) : Chris@33: freq(_f), time(_t), confidence(_c) { } Chris@34: bool operator==(const Estimate &e) const { Chris@34: return e.freq == freq && e.time == time && e.confidence == confidence; Chris@34: } Chris@45: double freq; Chris@35: Vamp::RealTime time; Chris@45: double confidence; Chris@32: }; Chris@32: typedef std::vector Estimates; Chris@32: Chris@32: /** Chris@32: * Test the given estimate to see whether it is consistent with Chris@32: * this hypothesis, and adjust the hypothesis' internal state Chris@32: * accordingly. If the estimate is not inconsistent with the Chris@32: * hypothesis, return true. Chris@32: */ Chris@32: bool accept(Estimate); Chris@32: Chris@32: /** Chris@32: * Return the current state of this hypothesis. Chris@32: */ Chris@32: State getState() const; Chris@32: Chris@32: /** Chris@32: * If the hypothesis has been satisfied (i.e. is in Satisfied or Chris@32: * Expired state), return the series of estimates that it Chris@32: * accepted. Otherwise return an empty list Chris@32: */ Chris@32: Estimates getAcceptedEstimates() const; Chris@32: Chris@32: struct Note { Chris@33: Note() : freq(0), time(), duration() { } Chris@35: Note(double _f, Vamp::RealTime _t, Vamp::RealTime _d) : Chris@33: freq(_f), time(_t), duration(_d) { } Chris@34: bool operator==(const Note &e) const { Chris@34: return e.freq == freq && e.time == time && e.duration == duration; Chris@34: } Chris@45: double freq; Chris@45: Vamp::RealTime time; Chris@45: Vamp::RealTime duration; Chris@32: }; Chris@32: Chris@32: /** Chris@52: * Return the time of the first accepted estimate Chris@52: */ Chris@52: Vamp::RealTime getStartTime() const; Chris@52: Chris@52: /** Chris@34: * Return the mean frequency of the accepted estimates Chris@34: */ Chris@34: double getMeanFrequency() const; Chris@34: Chris@34: /** Chris@32: * Return a single note roughly matching this hypothesis Chris@32: */ Chris@32: Note getAveragedNote() const; Chris@32: Chris@32: private: Chris@32: bool isWithinTolerance(Estimate) const; Chris@32: bool isOutOfDateFor(Estimate) const; Chris@32: bool isSatisfied() const; Chris@32: Chris@32: State m_state; Chris@32: Estimates m_pending; Chris@32: }; Chris@32: Chris@32: #endif