summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libs/ardour/midi_diskstream.cc4
-rw-r--r--libs/ardour/midi_model.cc85
-rw-r--r--libs/ardour/midi_ring_buffer.cc4
-rw-r--r--libs/ardour/midi_track.cc1
-rw-r--r--libs/ardour/smf_source.cc4
-rw-r--r--libs/evoral/evoral/Note.hpp10
-rw-r--r--libs/evoral/evoral/SMF.hpp2
-rw-r--r--libs/evoral/evoral/types.hpp6
-rw-r--r--libs/evoral/src/Note.cpp2
-rw-r--r--libs/evoral/src/SMF.cpp9
10 files changed, 90 insertions, 37 deletions
diff --git a/libs/ardour/midi_diskstream.cc b/libs/ardour/midi_diskstream.cc
index b486a0fce0..9c8c9e8620 100644
--- a/libs/ardour/midi_diskstream.cc
+++ b/libs/ardour/midi_diskstream.cc
@@ -949,8 +949,8 @@ MidiDiskstream::read (nframes_t& start, nframes_t dur, bool reversed)
// Synthesize LoopEvent here, because the next events
// written will have non-monotonic timestamps.
_playback_buf->write(loop_end - 1, LoopEventType, 0, 0);
- //cout << "Pushing LoopEvent ts=" << loop_end-1
- // << " start+this_read " << start+this_read << endl;
+ cout << "Pushing LoopEvent ts=" << loop_end-1
+ << " start+this_read " << start+this_read << endl;
start = loop_start;
} else {
diff --git a/libs/ardour/midi_model.cc b/libs/ardour/midi_model.cc
index 80c5759896..79e59ecde4 100644
--- a/libs/ardour/midi_model.cc
+++ b/libs/ardour/midi_model.cc
@@ -30,6 +30,7 @@
#include "ardour/midi_model.h"
#include "ardour/midi_source.h"
+#include "ardour/smf_source.h"
#include "ardour/types.h"
#include "ardour/session.h"
@@ -458,45 +459,63 @@ MidiModel::DiffCommand::marshal_change(const NotePropertyChange& change)
{
ostringstream old_value_str (ios::ate);
- old_value_str << (unsigned int) change.old_value;
+ if (change.property == StartTime || change.property == Length) {
+ old_value_str << change.old_time;
+ } else {
+ old_value_str << (unsigned int) change.old_value;
+ }
xml_change->add_property ("old", old_value_str.str());
}
{
ostringstream new_value_str (ios::ate);
- new_value_str << (unsigned int) change.old_value;
+ if (change.property == StartTime || change.property == Length) {
+ new_value_str << change.new_time;
+ } else {
+ new_value_str << (unsigned int) change.new_value;
+ }
xml_change->add_property ("new", new_value_str.str());
}
/* now the rest of the note */
+
+ const SMFSource* smf = dynamic_cast<const SMFSource*> (_model->midi_source());
if (change.property != NoteNumber) {
- ostringstream note_str(ios::ate);
+ ostringstream note_str;
note_str << int(change.note->note());
xml_change->add_property("note", note_str.str());
}
if (change.property != Channel) {
- ostringstream channel_str(ios::ate);
+ ostringstream channel_str;
channel_str << int(change.note->channel());
xml_change->add_property("channel", channel_str.str());
}
if (change.property != StartTime) {
- ostringstream time_str(ios::ate);
- time_str << int(change.note->time());
+ ostringstream time_str;
+ if (smf) {
+ time_str << smf->round_to_file_precision (change.note->time());
+ } else {
+ time_str << change.note->time();
+ }
xml_change->add_property("time", time_str.str());
}
if (change.property != Length) {
- ostringstream length_str(ios::ate);
- length_str <<(unsigned int) change.note->length();
- xml_change->add_property("length", length_str.str());
+ ostringstream length_str;
+ if (smf) {
+ length_str << smf->round_to_file_precision (change.note->length());
+ } else {
+ length_str << change.note->length();
+ }
+ xml_change->add_property ("length", length_str.str());
}
if (change.property != Velocity) {
- ostringstream velocity_str(ios::ate);
- velocity_str << (unsigned int) change.note->velocity();
+ ostringstream velocity_str;
+ velocity_str << int (change.note->velocity());
xml_change->add_property("velocity", velocity_str.str());
}
@@ -510,9 +529,9 @@ MidiModel::DiffCommand::unmarshal_change(XMLNode *xml_change)
NotePropertyChange change;
unsigned int note;
unsigned int channel;
- unsigned int time;
- unsigned int length;
unsigned int velocity;
+ Evoral::MusicalTime time;
+ Evoral::MusicalTime length;
if ((prop = xml_change->property("property")) != 0) {
change.property = (Property) string_2_enum (prop->value(), change.property);
@@ -523,7 +542,13 @@ MidiModel::DiffCommand::unmarshal_change(XMLNode *xml_change)
if ((prop = xml_change->property ("old")) != 0) {
istringstream old_str (prop->value());
- old_str >> change.old_value;
+ if (change.property == StartTime || change.property == Length) {
+ old_str >> change.old_time;
+ } else {
+ int integer_value_so_that_istream_does_the_right_thing;
+ old_str >> integer_value_so_that_istream_does_the_right_thing;
+ change.old_value = integer_value_so_that_istream_does_the_right_thing;
+ }
} else {
fatal << "!!!" << endmsg;
/*NOTREACHED*/
@@ -531,7 +556,13 @@ MidiModel::DiffCommand::unmarshal_change(XMLNode *xml_change)
if ((prop = xml_change->property ("new")) != 0) {
istringstream new_str (prop->value());
- new_str >> change.new_value;
+ if (change.property == StartTime || change.property == Length) {
+ new_str >> change.new_time;
+ } else {
+ int integer_value_so_that_istream_does_the_right_thing;
+ new_str >> integer_value_so_that_istream_does_the_right_thing;
+ change.new_value = integer_value_so_that_istream_does_the_right_thing;
+ }
} else {
fatal << "!!!" << endmsg;
/*NOTREACHED*/
@@ -570,7 +601,7 @@ MidiModel::DiffCommand::unmarshal_change(XMLNode *xml_change)
time = 0;
}
} else {
- time = change.new_value;
+ time = change.new_time;
}
if (change.property != Length) {
@@ -582,7 +613,7 @@ MidiModel::DiffCommand::unmarshal_change(XMLNode *xml_change)
length = 1;
}
} else {
- length = change.new_value;
+ length = change.new_time;
}
if (change.property != Velocity) {
@@ -600,13 +631,13 @@ MidiModel::DiffCommand::unmarshal_change(XMLNode *xml_change)
/* we must point at the instance of the note that is actually in the model.
so go look for it ...
*/
-
+
boost::shared_ptr<Evoral::Note<TimeType> > new_note (new Evoral::Note<TimeType> (channel, time, length, note, velocity));
change.note = _model->find_note (new_note);
if (!change.note) {
- warning << "MIDI note not found in model - programmers should investigate this" << endmsg;
+ warning << "MIDI note " << *new_note << " not found in model - programmers should investigate this" << endmsg;
/* use the actual new note */
change.note = new_note;
}
@@ -627,7 +658,7 @@ MidiModel::DiffCommand::set_state(const XMLNode& diff_command)
if (changed_notes) {
XMLNodeList notes = changed_notes->children();
-
+
transform (notes.begin(), notes.end(), back_inserter(_changes),
sigc::mem_fun(*this, &DiffCommand::unmarshal_change));
}
@@ -688,11 +719,15 @@ MidiModel::get_state()
boost::shared_ptr<Evoral::Note<MidiModel::TimeType> >
MidiModel::find_note (boost::shared_ptr<Evoral::Note<TimeType> > other)
{
- Notes::iterator i = find (notes().begin(), notes().end(), other);
+ for (Notes::iterator x = notes().begin(); x != notes().end(); ++x) {
+ if (**x == *other) {
+ return *x;
+ }
- if (i == notes().end()) {
- return boost::shared_ptr<Evoral::Note<TimeType> > ();
+ /* XXX optimize by using a stored iterator and break out
+ when passed start time.
+ */
}
-
- return *i;
+
+ return boost::shared_ptr<Evoral::Note<TimeType> > ();
}
diff --git a/libs/ardour/midi_ring_buffer.cc b/libs/ardour/midi_ring_buffer.cc
index 007d5271c8..88064c8798 100644
--- a/libs/ardour/midi_ring_buffer.cc
+++ b/libs/ardour/midi_ring_buffer.cc
@@ -66,8 +66,8 @@ MidiRingBuffer<T>::read(MidiBuffer& dst, nframes_t start, nframes_t end, nframes
// This event marks a loop end (i.e. the next event's timestamp will be non-monotonic)
if (ev_type == LoopEventType) {
/*ev_time -= start;
- ev_time += offset;
- cerr << "MRB loop boundary @ " << ev_time << endl;*/
+ ev_time += offset;*/
+ cerr << "MRB loop boundary @ " << ev_time << endl;
// Return without reading data or writing to buffer (loop events have no data)
// FIXME: This is not correct, loses events after the loop this cycle
diff --git a/libs/ardour/midi_track.cc b/libs/ardour/midi_track.cc
index 7324196512..000143f3d5 100644
--- a/libs/ardour/midi_track.cc
+++ b/libs/ardour/midi_track.cc
@@ -456,6 +456,7 @@ MidiTrack::roll (nframes_t nframes, sframes_t start_frame, sframes_t end_frame,
if (did_loop) {
/* add necessary note offs */
+ cerr << "DID LOOP, RESOLVE NOTES\n";
_midi_state_tracker.resolve_notes (mbuf, end_frame-start_frame - 1);
}
diff --git a/libs/ardour/smf_source.cc b/libs/ardour/smf_source.cc
index 40848dc9ed..7db027124b 100644
--- a/libs/ardour/smf_source.cc
+++ b/libs/ardour/smf_source.cc
@@ -256,7 +256,7 @@ SMFSource::append_event_unlocked_beats (const Evoral::Event<double>& ev)
const double delta_time_beats = ev.time() - _last_ev_time_beats;
const uint32_t delta_time_ticks = (uint32_t)lrint(delta_time_beats * (double)ppqn());
-
+
Evoral::SMF::append_event_delta(delta_time_ticks, ev.size(), ev.buffer());
_last_ev_time_beats = ev.time();
@@ -396,7 +396,7 @@ SMFSource::load_model (bool lock, bool force_reload)
while ((ret = read_event(&delta_t, &size, &buf)) >= 0) {
time += delta_t;
ev.set(buf, size, time / (double)ppqn());
-
+
if (ret > 0) { // didn't skip (meta) event
ev.set_event_type(EventTypeMap::instance().midi_event_type(buf[0]));
_model->append(ev);
diff --git a/libs/evoral/evoral/Note.hpp b/libs/evoral/evoral/Note.hpp
index e92094ae78..b636df46e2 100644
--- a/libs/evoral/evoral/Note.hpp
+++ b/libs/evoral/evoral/Note.hpp
@@ -38,11 +38,11 @@ public:
const Note<Time>& operator=(const Note<Time>& copy);
inline bool operator==(const Note<Time>& other) {
- return time() == other.time() &&
- note() == other.note() &&
- length() == other.length() &&
- velocity() == other.velocity() &&
- channel() == other.channel();
+ return musical_time_equal (time(), other.time()) &&
+ note() == other.note() &&
+ musical_time_equal (length(), other.length()) &&
+ velocity() == other.velocity() &&
+ channel() == other.channel();
}
inline Time time() const { return _on_event.time(); }
diff --git a/libs/evoral/evoral/SMF.hpp b/libs/evoral/evoral/SMF.hpp
index 4a6b21870b..b921a80e6d 100644
--- a/libs/evoral/evoral/SMF.hpp
+++ b/libs/evoral/evoral/SMF.hpp
@@ -64,6 +64,8 @@ public:
void flush() {};
+ double round_to_file_precision (double val) const;
+
private:
std::string _file_path;
smf_t* _smf;
diff --git a/libs/evoral/evoral/types.hpp b/libs/evoral/evoral/types.hpp
index e9ce503068..9e48a68e3c 100644
--- a/libs/evoral/evoral/types.hpp
+++ b/libs/evoral/evoral/types.hpp
@@ -21,6 +21,7 @@
#include <stdint.h>
#include <list>
+#include <cmath>
namespace Evoral {
@@ -30,6 +31,11 @@ typedef uint32_t FrameTime;
/** Musical time: beats relative to some defined origin */
typedef double MusicalTime;
+static inline bool musical_time_equal (MusicalTime a, MusicalTime b) {
+ /* acceptable tolerance is 1 tick. Nice if there was no magic number here */
+ return fabs (a - b) <= (1.0/1920.0);
+}
+
/** Type of an event (opaque, mapped by application) */
typedef uint32_t EventType;
diff --git a/libs/evoral/src/Note.cpp b/libs/evoral/src/Note.cpp
index 9440cde273..d97cfef429 100644
--- a/libs/evoral/src/Note.cpp
+++ b/libs/evoral/src/Note.cpp
@@ -39,7 +39,7 @@ Note<Time>::Note(uint8_t chan, Time t, Time l, uint8_t n, uint8_t v)
_off_event.buffer()[2] = 0x40;
assert(time() == t);
- assert(length() - l <= 1.0/1920.0); /* acceptable tolerance is 1/ppqn. Nice if there was no magic number here */
+ assert(musical_time_equal (length(), l));
assert(note() == n);
assert(velocity() == v);
assert(_on_event.channel() == _off_event.channel());
diff --git a/libs/evoral/src/SMF.cpp b/libs/evoral/src/SMF.cpp
index 372c37c0bb..2103ad8eae 100644
--- a/libs/evoral/src/SMF.cpp
+++ b/libs/evoral/src/SMF.cpp
@@ -19,6 +19,7 @@
#define __STDC_LIMIT_MACROS 1
#include <cassert>
+#include <cmath>
#include <iostream>
#include <stdint.h>
#include "libsmf/smf.h"
@@ -262,5 +263,13 @@ SMF::end_write() THROW_FILE_ERROR
throw FileError();
}
+double
+SMF::round_to_file_precision (double val) const
+{
+ double div = ppqn();
+
+ return round (val * div) / div;
+}
+
} // namespace Evoral