summaryrefslogtreecommitdiff
path: root/libs/evoral
diff options
context:
space:
mode:
Diffstat (limited to 'libs/evoral')
-rw-r--r--libs/evoral/evoral/Beats.hpp247
-rw-r--r--libs/evoral/evoral/types.hpp208
-rw-r--r--libs/evoral/src/Event.cpp2
-rw-r--r--libs/evoral/src/MIDIEvent.cpp2
-rw-r--r--libs/evoral/src/Note.cpp2
-rw-r--r--libs/evoral/src/OldSMF.cpp2
-rw-r--r--libs/evoral/src/Sequence.cpp2
-rw-r--r--libs/evoral/src/TimeConverter.cpp2
-rw-r--r--libs/evoral/src/types.cpp6
-rw-r--r--libs/evoral/test/SMFTest.cpp8
-rw-r--r--libs/evoral/test/SMFTest.hpp2
-rw-r--r--libs/evoral/test/SequenceTest.cpp2
-rw-r--r--libs/evoral/test/SequenceTest.hpp4
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)));
}
}