Chris@181: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ Chris@181: Chris@181: /* Chris@181: Silvet Chris@181: Chris@181: A Vamp plugin for note transcription. Chris@181: Centre for Digital Music, Queen Mary University of London. Chris@181: This file Copyright 2012 Chris Cannam. Chris@181: Chris@181: This program is free software; you can redistribute it and/or Chris@181: modify it under the terms of the GNU General Public License as Chris@181: published by the Free Software Foundation; either version 2 of the Chris@181: License, or (at your option) any later version. See the file Chris@181: COPYING included with this distribution for more information. Chris@181: */ Chris@181: Chris@181: #ifndef NOTE_HYPOTHESIS_H Chris@181: #define NOTE_HYPOTHESIS_H Chris@181: Chris@181: #include "AgentHypothesis.h" Chris@181: Chris@181: #include Chris@181: #include Chris@181: Chris@181: /** Chris@181: * An AgentHypothesis which tests a series of instantaneous pitch Chris@181: * estimates to see whether they fit a single-note relationship. Chris@181: * Contains rules specific to testing note pitch and timing. Chris@181: */ Chris@181: Chris@181: class NoteHypothesis : public AgentHypothesis Chris@181: { Chris@181: public: Chris@181: /** Chris@181: * Construct an empty hypothesis. This will be in New state and Chris@181: * will provisionally accept any estimate. Chris@181: */ Chris@181: NoteHypothesis(); Chris@181: Chris@181: /** Chris@181: * Destroy the hypothesis Chris@181: */ Chris@181: ~NoteHypothesis(); Chris@181: Chris@181: virtual bool accept(Observation); Chris@181: virtual State getState() const; Chris@181: virtual Observations getAcceptedObservations() const; Chris@181: Chris@181: struct Note { Chris@181: Note() : freq(0), time(), duration() { } Chris@181: Note(double _f, Vamp::RealTime _t, Vamp::RealTime _d) : Chris@181: freq(_f), time(_t), duration(_d) { } Chris@181: bool operator==(const Note &e) const { Chris@181: return e.freq == freq && e.time == time && e.duration == duration; Chris@181: } Chris@181: double freq; Chris@181: Vamp::RealTime time; Chris@181: Vamp::RealTime duration; Chris@181: }; Chris@181: Chris@181: /** Chris@181: * Return the mean frequency of the accepted observations Chris@181: */ Chris@181: double getMeanFrequency() const; Chris@181: Chris@181: /** Chris@181: * Return a single note roughly matching this hypothesis Chris@181: */ Chris@181: Note getAveragedNote() const; Chris@181: Chris@181: /** Chris@181: * Return the time of the first accepted observation Chris@181: */ Chris@181: Vamp::RealTime getStartTime() const; Chris@181: Chris@181: /** Chris@181: * Return the difference between the start time and the end of the Chris@181: * final accepted observation Chris@181: */ Chris@181: Vamp::RealTime getDuration() const; Chris@181: Chris@181: /** Chris@181: * Convert the given sequence of accepted hypotheses into a Chris@181: * sampled series of pitches (in Hz), returned at regular Chris@181: * intervals determined by the given start time, end time, and Chris@181: * interval. The range is [start,end], i.e. the end time is Chris@181: * included. The interval must be greater than zero. Chris@181: * Chris@181: * Unvoiced samples are returned as 0Hz. Chris@181: */ Chris@181: static std::vector sample(const std::set &, Chris@181: Vamp::RealTime startTime, Chris@181: Vamp::RealTime endTime, Chris@181: Vamp::RealTime interval); Chris@181: Chris@181: /** Chris@181: *!!! No! Not equally spaced, should be able to be anything [ordered] Chris@181: Chris@181: * Given a series of equally spaced observations, return a series Chris@181: * of the same number of pitches (in Hz) calculated by running an Chris@181: * AgentFeeder on the observations and flattening Chris@181: * and sampling the resulting accepted hypotheses. Chris@181: * Chris@181: * The result should contain only pitches that contributed to Chris@181: * recognised notes in the input observations, with the remaining Chris@181: * (unvoiced) samples returned as 0Hz. Chris@181: * Chris@181: * If the input observations are not equally spaced, the result is Chris@181: * undefined. Chris@181: *!!! (what about rounding errors from RealTime to frame and vice versa?) Chris@181: *!!! (should provide a Timebase?) Chris@181: *!!! update docs for updated api Chris@181: */ Chris@181: static std::vector winnow(const Observations &, Chris@181: Vamp::RealTime startTime, Chris@181: Vamp::RealTime endTime, Chris@181: Vamp::RealTime interval); Chris@181: Chris@181: //!!! Chris@181: bool operator==(const NoteHypothesis &other) const { Chris@181: return m_state == other.m_state && m_pending == other.m_pending; Chris@181: } Chris@181: Chris@181: bool operator<(const NoteHypothesis &other) const { Chris@181: return getStartTime() < other.getStartTime(); Chris@181: } Chris@181: Chris@181: private: Chris@181: bool isWithinTolerance(Observation) const; Chris@181: bool isOutOfDateFor(Observation) const; Chris@181: bool isSatisfied() const; Chris@181: Chris@181: State m_state; Chris@181: Observations m_pending; Chris@181: }; Chris@181: Chris@181: #endif