diff options
author | David Robillard <d@drobilla.net> | 2015-01-07 00:12:07 -0500 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2015-01-07 00:12:07 -0500 |
commit | 2a251b457069ffb4b744fbd0dd7aca7acb31f381 (patch) | |
tree | 4311e63fe7ef1b5d7a5b841a4dd0eb7b26b324a7 /libs/evoral | |
parent | 4d202d9157bef5b6325fe54b7874080952f86a37 (diff) |
MusicalTime => Beats.
Diffstat (limited to 'libs/evoral')
-rw-r--r-- | libs/evoral/evoral/Beats.hpp | 247 | ||||
-rw-r--r-- | libs/evoral/evoral/types.hpp | 208 | ||||
-rw-r--r-- | libs/evoral/src/Event.cpp | 2 | ||||
-rw-r--r-- | libs/evoral/src/MIDIEvent.cpp | 2 | ||||
-rw-r--r-- | libs/evoral/src/Note.cpp | 2 | ||||
-rw-r--r-- | libs/evoral/src/OldSMF.cpp | 2 | ||||
-rw-r--r-- | libs/evoral/src/Sequence.cpp | 2 | ||||
-rw-r--r-- | libs/evoral/src/TimeConverter.cpp | 2 | ||||
-rw-r--r-- | libs/evoral/src/types.cpp | 6 | ||||
-rw-r--r-- | libs/evoral/test/SMFTest.cpp | 8 | ||||
-rw-r--r-- | libs/evoral/test/SMFTest.hpp | 2 | ||||
-rw-r--r-- | libs/evoral/test/SequenceTest.cpp | 2 | ||||
-rw-r--r-- | libs/evoral/test/SequenceTest.hpp | 4 |
13 files changed, 265 insertions, 224 deletions
diff --git a/libs/evoral/evoral/Beats.hpp b/libs/evoral/evoral/Beats.hpp new file mode 100644 index 0000000000..e0277c4b3d --- /dev/null +++ b/libs/evoral/evoral/Beats.hpp @@ -0,0 +1,247 @@ +/* This file is part of Evoral. + * Copyright (C) 2008-2015 David Robillard <http://drobilla.net> + * Copyright (C) 2000-2008 Paul Davis + * + * Evoral is free software; you can redistribute it and/or modify it under the + * terms of the GNU General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) any later + * version. + * + * Evoral is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef EVORAL_BEATS_HPP +#define EVORAL_BEATS_HPP + +#include <float.h> +#include <math.h> +#include <stdint.h> + +#include <iostream> +#include <limits> + +#include "evoral/visibility.h" + +namespace Evoral { + +/** Musical time in beats. */ +class /*LIBEVORAL_API*/ Beats { +public: + LIBEVORAL_API static const double PPQN; + + Beats() : _time(0.0) {} + + /** Create from a real number of beats. */ + explicit Beats(double time) : _time(time) {} + + /** Create from an integer number of beats. */ + static Beats beats(int32_t beats) { + return Beats((double)beats); + } + + /** Create from ticks at the standard PPQN. */ + static Beats ticks(uint32_t ticks) { + return Beats(ticks / PPQN); + } + + /** Create from ticks at a given rate. + * + * Note this can also be used to create from frames by setting ppqn to the + * number of samples per beat. + */ + static Beats ticks_at_rate(uint64_t ticks, uint32_t ppqn) { + return Beats((double)ticks / (double)ppqn); + } + + Beats& operator=(const Beats& other) { + _time = other._time; + return *this; + } + + Beats round_up_to_beat() const { + return Evoral::Beats(ceil(_time)); + } + + Beats round_down_to_beat() const { + return Evoral::Beats(floor(_time)); + } + + Beats snap_to(const Evoral::Beats& snap) const { + return Beats(ceil(_time / snap._time) * snap._time); + } + + inline bool operator==(const Beats& b) const { + /* Acceptable tolerance is 1 tick. */ + return fabs(_time - b._time) <= (1.0 / PPQN); + } + + inline bool operator==(double t) const { + /* Acceptable tolerance is 1 tick. */ + return fabs(_time - t) <= (1.0 / PPQN); + } + + inline bool operator==(int beats) const { + /* Acceptable tolerance is 1 tick. */ + return fabs(_time - beats) <= (1.0 / PPQN); + } + + inline bool operator!=(const Beats& b) const { + return !operator==(b); + } + + inline bool operator<(const Beats& b) const { + /* Acceptable tolerance is 1 tick. */ + if (fabs(_time - b._time) <= (1.0 / PPQN)) { + return false; /* Effectively identical. */ + } else { + return _time < b._time; + } + } + + inline bool operator<=(const Beats& b) const { + return operator==(b) || operator<(b); + } + + inline bool operator>(const Beats& b) const { + /* Acceptable tolerance is 1 tick. */ + if (fabs(_time - b._time) <= (1.0 / PPQN)) { + return false; /* Effectively identical. */ + } else { + return _time > b._time; + } + } + + inline bool operator>=(const Beats& b) const { + return operator==(b) || operator>(b); + } + + inline bool operator<(double b) const { + /* Acceptable tolerance is 1 tick. */ + if (fabs(_time - b) <= (1.0 / PPQN)) { + return false; /* Effectively identical. */ + } else { + return _time < b; + } + } + + inline bool operator<=(double b) const { + return operator==(b) || operator<(b); + } + + inline bool operator>(double b) const { + /* Acceptable tolerance is 1 tick. */ + if (fabs(_time - b) <= (1.0 / PPQN)) { + return false; /* Effectively identical. */ + } else { + return _time > b; + } + } + + inline bool operator>=(double b) const { + return operator==(b) || operator>(b); + } + + Beats operator+(const Beats& b) const { + return Beats(_time + b._time); + } + + Beats operator-(const Beats& b) const { + return Beats(_time - b._time); + } + + Beats operator+(double d) const { + return Beats(_time + d); + } + + Beats operator-(double d) const { + return Beats(_time - d); + } + + Beats operator-() const { + return Beats(-_time); + } + + template<typename Number> + Beats operator*(Number factor) const { + return Beats(_time * factor); + } + + Beats& operator+=(const Beats& b) { + _time += b._time; + return *this; + } + + Beats& operator-=(const Beats& b) { + _time -= b._time; + return *this; + } + + double to_double() const { return _time; } + uint64_t to_ticks() const { return lrint(_time * PPQN); } + uint64_t to_ticks(uint32_t ppqn) const { return lrint(_time * ppqn); } + + uint32_t get_beats() const { return floor(_time); } + uint32_t get_ticks() const { return (uint32_t)lrint(fmod(_time, 1.0) * PPQN); } + + bool operator!() const { return _time == 0; } + + static Beats min() { return Beats(DBL_MIN); } + static Beats max() { return Beats(DBL_MAX); } + static Beats tick() { return Beats(1.0 / PPQN); } + +private: + double _time; +}; + +extern LIBEVORAL_API const Beats MaxBeats; +extern LIBEVORAL_API const Beats MinBeats; + +/* + TIL, several horrible hours later, that sometimes the compiler looks in the + namespace of a type (Evoral::Beats in this case) for an operator, and + does *NOT* look in the global namespace. + + C++ is proof that hell exists and we are living in it. In any case, move + these to the global namespace and PBD::Property's loopy + virtual-method-in-a-template will bite you. +*/ + +inline std::ostream& +operator<<(std::ostream& os, const Beats& t) +{ + os << t.to_double(); + return os; +} + +inline std::istream& +operator>>(std::istream& is, Beats& t) +{ + double beats; + is >> beats; + t = Beats(beats); + return is; +} + +} // namespace Evoral + +namespace PBD { + namespace DEBUG { + LIBEVORAL_API extern uint64_t Beats; + } +} + +namespace std { + template<> + struct numeric_limits<Evoral::Beats> { + static Evoral::Beats min() { return Evoral::Beats::min(); } + static Evoral::Beats max() { return Evoral::Beats::max(); } + }; +} + +#endif // EVORAL_BEATS_HPP diff --git a/libs/evoral/evoral/types.hpp b/libs/evoral/evoral/types.hpp index 14ba36acdf..1951fb8ba6 100644 --- a/libs/evoral/evoral/types.hpp +++ b/libs/evoral/evoral/types.hpp @@ -27,6 +27,7 @@ #include <limits> #include <list> +#include "evoral/Beats.hpp" #include "evoral/visibility.h" #include "pbd/debug.h" @@ -38,207 +39,9 @@ namespace Evoral { */ typedef int32_t event_id_t; -/** Musical time: beats relative to some defined origin */ -class /*LIBEVORAL_API*/ MusicalTime { -public: - LIBEVORAL_API static const double PPQN; - - MusicalTime() : _time(0.0) {} - - /** Create from a real number of beats. */ - explicit MusicalTime(double time) : _time(time) {} - - /** Create from an integer number of beats. */ - static MusicalTime beats(int32_t beats) { - return MusicalTime((double)beats); - } - - /** Create from ticks at the standard PPQN. */ - static MusicalTime ticks(uint32_t ticks) { - return MusicalTime(ticks / PPQN); - } - - /** Create from ticks at a given rate. - * - * Note this can also be used to create from frames by setting ppqn to the - * number of samples per beat. - */ - static MusicalTime ticks_at_rate(uint64_t ticks, uint32_t ppqn) { - return MusicalTime((double)ticks / (double)ppqn); - } - - MusicalTime& operator=(const MusicalTime& other) { - _time = other._time; - return *this; - } - - MusicalTime round_up_to_beat() const { - return Evoral::MusicalTime(ceil(_time)); - } - - MusicalTime round_down_to_beat() const { - return Evoral::MusicalTime(floor(_time)); - } - - MusicalTime snap_to(const Evoral::MusicalTime& snap) const { - return MusicalTime(ceil(_time / snap._time) * snap._time); - } - - inline bool operator==(const MusicalTime& b) const { - /* Acceptable tolerance is 1 tick. */ - return fabs(_time - b._time) <= (1.0 / PPQN); - } - - inline bool operator==(double t) const { - /* Acceptable tolerance is 1 tick. */ - return fabs(_time - t) <= (1.0 / PPQN); - } - - inline bool operator==(int beats) const { - /* Acceptable tolerance is 1 tick. */ - return fabs(_time - beats) <= (1.0 / PPQN); - } - - inline bool operator!=(const MusicalTime& b) const { - return !operator==(b); - } - - inline bool operator<(const MusicalTime& b) const { - /* Acceptable tolerance is 1 tick. */ - if (fabs(_time - b._time) <= (1.0 / PPQN)) { - return false; /* Effectively identical. */ - } else { - return _time < b._time; - } - } - - inline bool operator<=(const MusicalTime& b) const { - return operator==(b) || operator<(b); - } - - inline bool operator>(const MusicalTime& b) const { - /* Acceptable tolerance is 1 tick. */ - if (fabs(_time - b._time) <= (1.0 / PPQN)) { - return false; /* Effectively identical. */ - } else { - return _time > b._time; - } - } - - inline bool operator>=(const MusicalTime& b) const { - return operator==(b) || operator>(b); - } - - inline bool operator<(double b) const { - /* Acceptable tolerance is 1 tick. */ - if (fabs(_time - b) <= (1.0 / PPQN)) { - return false; /* Effectively identical. */ - } else { - return _time < b; - } - } - - inline bool operator<=(double b) const { - return operator==(b) || operator<(b); - } - - inline bool operator>(double b) const { - /* Acceptable tolerance is 1 tick. */ - if (fabs(_time - b) <= (1.0 / PPQN)) { - return false; /* Effectively identical. */ - } else { - return _time > b; - } - } - - inline bool operator>=(double b) const { - return operator==(b) || operator>(b); - } - - MusicalTime operator+(const MusicalTime& b) const { - return MusicalTime(_time + b._time); - } - - MusicalTime operator-(const MusicalTime& b) const { - return MusicalTime(_time - b._time); - } - - MusicalTime operator+(double d) const { - return MusicalTime(_time + d); - } - - MusicalTime operator-(double d) const { - return MusicalTime(_time - d); - } - - MusicalTime operator-() const { - return MusicalTime(-_time); - } - - template<typename Number> - MusicalTime operator*(Number factor) const { - return MusicalTime(_time * factor); - } - - MusicalTime& operator+=(const MusicalTime& b) { - _time += b._time; - return *this; - } - - MusicalTime& operator-=(const MusicalTime& b) { - _time -= b._time; - return *this; - } - - double to_double() const { return _time; } - uint64_t to_ticks() const { return lrint(_time * PPQN); } - uint64_t to_ticks(uint32_t ppqn) const { return lrint(_time * ppqn); } - - uint32_t get_beats() const { return floor(_time); } - uint32_t get_ticks() const { return (uint32_t)lrint(fmod(_time, 1.0) * PPQN); } - - bool operator!() const { return _time == 0; } - - static MusicalTime min() { return MusicalTime(DBL_MIN); } - static MusicalTime max() { return MusicalTime(DBL_MAX); } - static MusicalTime tick() { return MusicalTime(1.0 / PPQN); } - -private: - double _time; -}; - -extern LIBEVORAL_API const MusicalTime MaxMusicalTime; -extern LIBEVORAL_API const MusicalTime MinMusicalTime; - /** Type of an event (opaque, mapped by application) */ typedef uint32_t EventType; -/* - TIL, several horrible hours later, that sometimes the compiler looks in the - namespace of a type (Evoral::MusicalTime in this case) for an operator, and - does *NOT* look in the global namespace. - - C++ is proof that hell exists and we are living in it. In any case, move - these to the global namespace and PBD::Property's loopy - virtual-method-in-a-template will bite you. -*/ - -inline std::ostream& -operator<<(std::ostream& os, const MusicalTime& t) -{ - os << t.to_double(); - return os; -} - -inline std::istream& -operator>>(std::istream& is, MusicalTime& t) -{ - double beats; - is >> beats; - t = MusicalTime(beats); - return is; -} - } // namespace Evoral namespace PBD { @@ -246,16 +49,7 @@ namespace PBD { LIBEVORAL_API extern uint64_t Sequence; LIBEVORAL_API extern uint64_t Note; LIBEVORAL_API extern uint64_t ControlList; - LIBEVORAL_API extern uint64_t MusicalTime; } } -namespace std { - template<> - struct numeric_limits<Evoral::MusicalTime> { - static Evoral::MusicalTime min() { return Evoral::MusicalTime::min(); } - static Evoral::MusicalTime max() { return Evoral::MusicalTime::max(); } - }; -} - #endif // EVORAL_TYPES_HPP diff --git a/libs/evoral/src/Event.cpp b/libs/evoral/src/Event.cpp index b874c37de4..66e45ab2ad 100644 --- a/libs/evoral/src/Event.cpp +++ b/libs/evoral/src/Event.cpp @@ -155,7 +155,7 @@ Event<Timestamp>::set_original_time (Timestamp t) #endif // EVORAL_EVENT_ALLOC -template class Event<Evoral::MusicalTime>; +template class Event<Evoral::Beats>; template class Event<double>; template class Event<int64_t>; diff --git a/libs/evoral/src/MIDIEvent.cpp b/libs/evoral/src/MIDIEvent.cpp index 66a97f73e4..4985f66cf4 100644 --- a/libs/evoral/src/MIDIEvent.cpp +++ b/libs/evoral/src/MIDIEvent.cpp @@ -102,7 +102,7 @@ MIDIEvent<Time>::to_xml() const #endif // EVORAL_MIDI_XML -template class MIDIEvent<Evoral::MusicalTime>; +template class MIDIEvent<Evoral::Beats>; } // namespace Evoral diff --git a/libs/evoral/src/Note.cpp b/libs/evoral/src/Note.cpp index 93c0a90478..7e4f58d73f 100644 --- a/libs/evoral/src/Note.cpp +++ b/libs/evoral/src/Note.cpp @@ -108,7 +108,7 @@ Note<Time>::operator=(const Note<Time>& other) return *this; } -template class Note<Evoral::MusicalTime>; +template class Note<Evoral::Beats>; } // namespace Evoral diff --git a/libs/evoral/src/OldSMF.cpp b/libs/evoral/src/OldSMF.cpp index 0cee749c9c..eef61e332b 100644 --- a/libs/evoral/src/OldSMF.cpp +++ b/libs/evoral/src/OldSMF.cpp @@ -364,6 +364,6 @@ SMF<Time>::write_var_len(uint32_t value) return ret; } -template class SMF<Evoral::MusicalTime>; +template class SMF<Evoral::Beats>; } // namespace Evoral diff --git a/libs/evoral/src/Sequence.cpp b/libs/evoral/src/Sequence.cpp index a77e3c94be..10b7e31b79 100644 --- a/libs/evoral/src/Sequence.cpp +++ b/libs/evoral/src/Sequence.cpp @@ -1404,6 +1404,6 @@ Sequence<Time>::dump (ostream& str) const str << "--- dump\n"; } -template class Sequence<Evoral::MusicalTime>; +template class Sequence<Evoral::Beats>; } // namespace Evoral diff --git a/libs/evoral/src/TimeConverter.cpp b/libs/evoral/src/TimeConverter.cpp index 0d39087e7c..e1e4b8231f 100644 --- a/libs/evoral/src/TimeConverter.cpp +++ b/libs/evoral/src/TimeConverter.cpp @@ -45,6 +45,6 @@ IdentityConverter<A,B>::from(B b) const template class IdentityConverter<double, framepos_t>; template class TimeConverter<double, framepos_t>; -template class TimeConverter<Evoral::MusicalTime, framepos_t>; +template class TimeConverter<Evoral::Beats, framepos_t>; } // namespace Evoral diff --git a/libs/evoral/src/types.cpp b/libs/evoral/src/types.cpp index 80801dcdea..50c2975d3d 100644 --- a/libs/evoral/src/types.cpp +++ b/libs/evoral/src/types.cpp @@ -22,8 +22,8 @@ namespace Evoral { -const double MusicalTime::PPQN = 1920.0; -const MusicalTime MaxMusicalTime = Evoral::MusicalTime(DBL_MAX); -const MusicalTime MinMusicalTime = Evoral::MusicalTime(DBL_MIN); +const double Beats::PPQN = 1920.0; +const Beats MaxBeats = Evoral::Beats(DBL_MAX); +const Beats MinBeats = Evoral::Beats(DBL_MIN); } diff --git a/libs/evoral/test/SMFTest.cpp b/libs/evoral/test/SMFTest.cpp index 9bbe021947..d42ee26dff 100644 --- a/libs/evoral/test/SMFTest.cpp +++ b/libs/evoral/test/SMFTest.cpp @@ -45,25 +45,25 @@ SMFTest::takeFiveTest () smf.seek_to_start(); uint64_t time = 0; /* in SMF ticks */ - Evoral::Event<Evoral::MusicalTime> ev; + Evoral::Event<Evoral::Beats> ev; uint32_t delta_t = 0; uint32_t size = 0; uint8_t* buf = NULL; int ret; while ((ret = smf.read_event(&delta_t, &size, &buf)) >= 0) { - ev.set(buf, size, Evoral::MusicalTime()); + ev.set(buf, size, Evoral::Beats()); time += delta_t; if (ret > 0) { // didn't skip (meta) event //cerr << "read smf event type " << hex << int(buf[0]) << endl; - ev.set_time(Evoral::MusicalTime::ticks_at_rate(time, smf.ppqn())); + ev.set_time(Evoral::Beats::ticks_at_rate(time, smf.ppqn())); ev.set_event_type(type_map->midi_event_type(buf[0])); seq->append(ev, next_event_id ()); } } seq->end_write (Sequence<Time>::Relax, - Evoral::MusicalTime::ticks_at_rate(time, smf.ppqn())); + Evoral::Beats::ticks_at_rate(time, smf.ppqn())); CPPUNIT_ASSERT(!seq->empty()); } diff --git a/libs/evoral/test/SMFTest.hpp b/libs/evoral/test/SMFTest.hpp index 6e42b6f7b3..94172c62c8 100644 --- a/libs/evoral/test/SMFTest.hpp +++ b/libs/evoral/test/SMFTest.hpp @@ -57,7 +57,7 @@ class SMFTest : public CppUnit::TestFixture CPPUNIT_TEST_SUITE_END(); public: - typedef Evoral::MusicalTime Time; + typedef Evoral::Beats Time; void setUp() { type_map = new DummyTypeMap(); diff --git a/libs/evoral/test/SequenceTest.cpp b/libs/evoral/test/SequenceTest.cpp index f6a8363f4d..39afcd3095 100644 --- a/libs/evoral/test/SequenceTest.cpp +++ b/libs/evoral/test/SequenceTest.cpp @@ -75,7 +75,7 @@ SequenceTest::iteratorSeekTest () } bool on = true; - for (Sequence<Time>::const_iterator i = seq->begin(Evoral::MusicalTime(600)); i != seq->end(); ++i) { + for (Sequence<Time>::const_iterator i = seq->begin(Evoral::Beats(600)); i != seq->end(); ++i) { if (on) { CPPUNIT_ASSERT(((const MIDIEvent<Time>&)*i).is_note_on()); CPPUNIT_ASSERT_EQUAL(i->time(), Time((num_notes + 6) * 100)); diff --git a/libs/evoral/test/SequenceTest.hpp b/libs/evoral/test/SequenceTest.hpp index d8e0406100..da1991efc8 100644 --- a/libs/evoral/test/SequenceTest.hpp +++ b/libs/evoral/test/SequenceTest.hpp @@ -113,7 +113,7 @@ class SequenceTest : public CppUnit::TestFixture CPPUNIT_TEST_SUITE_END (); public: - typedef MusicalTime Time; + typedef Beats Time; typedef std::vector< boost::shared_ptr< Note<Time> > > Notes; void setUp () { @@ -125,7 +125,7 @@ public: for (int i = 0; i < 12; i++) { test_notes.push_back( boost::shared_ptr<Note<Time> >( - new Note<Time>(0, MusicalTime(i * 100), MusicalTime(100), 64 + i, 64))); + new Note<Time>(0, Beats(i * 100), Beats(100), 64 + i, 64))); } } |