mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-21 14:16:31 +01:00
fix up marshall/unmarshall of note data for MidiModel::DiffCommand
git-svn-id: svn://localhost/ardour2/branches/3.0@5662 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
3023d53d7d
commit
bf0a99f0c0
10 changed files with 90 additions and 37 deletions
|
|
@ -949,8 +949,8 @@ MidiDiskstream::read (nframes_t& start, nframes_t dur, bool reversed)
|
||||||
// Synthesize LoopEvent here, because the next events
|
// Synthesize LoopEvent here, because the next events
|
||||||
// written will have non-monotonic timestamps.
|
// written will have non-monotonic timestamps.
|
||||||
_playback_buf->write(loop_end - 1, LoopEventType, 0, 0);
|
_playback_buf->write(loop_end - 1, LoopEventType, 0, 0);
|
||||||
//cout << "Pushing LoopEvent ts=" << loop_end-1
|
cout << "Pushing LoopEvent ts=" << loop_end-1
|
||||||
// << " start+this_read " << start+this_read << endl;
|
<< " start+this_read " << start+this_read << endl;
|
||||||
|
|
||||||
start = loop_start;
|
start = loop_start;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@
|
||||||
|
|
||||||
#include "ardour/midi_model.h"
|
#include "ardour/midi_model.h"
|
||||||
#include "ardour/midi_source.h"
|
#include "ardour/midi_source.h"
|
||||||
|
#include "ardour/smf_source.h"
|
||||||
#include "ardour/types.h"
|
#include "ardour/types.h"
|
||||||
#include "ardour/session.h"
|
#include "ardour/session.h"
|
||||||
|
|
||||||
|
|
@ -458,45 +459,63 @@ MidiModel::DiffCommand::marshal_change(const NotePropertyChange& change)
|
||||||
|
|
||||||
{
|
{
|
||||||
ostringstream old_value_str (ios::ate);
|
ostringstream old_value_str (ios::ate);
|
||||||
|
if (change.property == StartTime || change.property == Length) {
|
||||||
|
old_value_str << change.old_time;
|
||||||
|
} else {
|
||||||
old_value_str << (unsigned int) change.old_value;
|
old_value_str << (unsigned int) change.old_value;
|
||||||
|
}
|
||||||
xml_change->add_property ("old", old_value_str.str());
|
xml_change->add_property ("old", old_value_str.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
ostringstream new_value_str (ios::ate);
|
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());
|
xml_change->add_property ("new", new_value_str.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
/* now the rest of the note */
|
/* now the rest of the note */
|
||||||
|
|
||||||
|
const SMFSource* smf = dynamic_cast<const SMFSource*> (_model->midi_source());
|
||||||
|
|
||||||
if (change.property != NoteNumber) {
|
if (change.property != NoteNumber) {
|
||||||
ostringstream note_str(ios::ate);
|
ostringstream note_str;
|
||||||
note_str << int(change.note->note());
|
note_str << int(change.note->note());
|
||||||
xml_change->add_property("note", note_str.str());
|
xml_change->add_property("note", note_str.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (change.property != Channel) {
|
if (change.property != Channel) {
|
||||||
ostringstream channel_str(ios::ate);
|
ostringstream channel_str;
|
||||||
channel_str << int(change.note->channel());
|
channel_str << int(change.note->channel());
|
||||||
xml_change->add_property("channel", channel_str.str());
|
xml_change->add_property("channel", channel_str.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (change.property != StartTime) {
|
if (change.property != StartTime) {
|
||||||
ostringstream time_str(ios::ate);
|
ostringstream time_str;
|
||||||
time_str << int(change.note->time());
|
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());
|
xml_change->add_property("time", time_str.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (change.property != Length) {
|
if (change.property != Length) {
|
||||||
ostringstream length_str(ios::ate);
|
ostringstream length_str;
|
||||||
length_str <<(unsigned int) change.note->length();
|
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());
|
xml_change->add_property ("length", length_str.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (change.property != Velocity) {
|
if (change.property != Velocity) {
|
||||||
ostringstream velocity_str(ios::ate);
|
ostringstream velocity_str;
|
||||||
velocity_str << (unsigned int) change.note->velocity();
|
velocity_str << int (change.note->velocity());
|
||||||
xml_change->add_property("velocity", velocity_str.str());
|
xml_change->add_property("velocity", velocity_str.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -510,9 +529,9 @@ MidiModel::DiffCommand::unmarshal_change(XMLNode *xml_change)
|
||||||
NotePropertyChange change;
|
NotePropertyChange change;
|
||||||
unsigned int note;
|
unsigned int note;
|
||||||
unsigned int channel;
|
unsigned int channel;
|
||||||
unsigned int time;
|
|
||||||
unsigned int length;
|
|
||||||
unsigned int velocity;
|
unsigned int velocity;
|
||||||
|
Evoral::MusicalTime time;
|
||||||
|
Evoral::MusicalTime length;
|
||||||
|
|
||||||
if ((prop = xml_change->property("property")) != 0) {
|
if ((prop = xml_change->property("property")) != 0) {
|
||||||
change.property = (Property) string_2_enum (prop->value(), change.property);
|
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) {
|
if ((prop = xml_change->property ("old")) != 0) {
|
||||||
istringstream old_str (prop->value());
|
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 {
|
} else {
|
||||||
fatal << "!!!" << endmsg;
|
fatal << "!!!" << endmsg;
|
||||||
/*NOTREACHED*/
|
/*NOTREACHED*/
|
||||||
|
|
@ -531,7 +556,13 @@ MidiModel::DiffCommand::unmarshal_change(XMLNode *xml_change)
|
||||||
|
|
||||||
if ((prop = xml_change->property ("new")) != 0) {
|
if ((prop = xml_change->property ("new")) != 0) {
|
||||||
istringstream new_str (prop->value());
|
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 {
|
} else {
|
||||||
fatal << "!!!" << endmsg;
|
fatal << "!!!" << endmsg;
|
||||||
/*NOTREACHED*/
|
/*NOTREACHED*/
|
||||||
|
|
@ -570,7 +601,7 @@ MidiModel::DiffCommand::unmarshal_change(XMLNode *xml_change)
|
||||||
time = 0;
|
time = 0;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
time = change.new_value;
|
time = change.new_time;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (change.property != Length) {
|
if (change.property != Length) {
|
||||||
|
|
@ -582,7 +613,7 @@ MidiModel::DiffCommand::unmarshal_change(XMLNode *xml_change)
|
||||||
length = 1;
|
length = 1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
length = change.new_value;
|
length = change.new_time;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (change.property != Velocity) {
|
if (change.property != Velocity) {
|
||||||
|
|
@ -606,7 +637,7 @@ MidiModel::DiffCommand::unmarshal_change(XMLNode *xml_change)
|
||||||
change.note = _model->find_note (new_note);
|
change.note = _model->find_note (new_note);
|
||||||
|
|
||||||
if (!change.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 */
|
/* use the actual new note */
|
||||||
change.note = new_note;
|
change.note = new_note;
|
||||||
}
|
}
|
||||||
|
|
@ -688,11 +719,15 @@ MidiModel::get_state()
|
||||||
boost::shared_ptr<Evoral::Note<MidiModel::TimeType> >
|
boost::shared_ptr<Evoral::Note<MidiModel::TimeType> >
|
||||||
MidiModel::find_note (boost::shared_ptr<Evoral::Note<TimeType> > other)
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* XXX optimize by using a stored iterator and break out
|
||||||
|
when passed start time.
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
if (i == notes().end()) {
|
|
||||||
return boost::shared_ptr<Evoral::Note<TimeType> > ();
|
return boost::shared_ptr<Evoral::Note<TimeType> > ();
|
||||||
}
|
}
|
||||||
|
|
||||||
return *i;
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -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)
|
// This event marks a loop end (i.e. the next event's timestamp will be non-monotonic)
|
||||||
if (ev_type == LoopEventType) {
|
if (ev_type == LoopEventType) {
|
||||||
/*ev_time -= start;
|
/*ev_time -= start;
|
||||||
ev_time += offset;
|
ev_time += offset;*/
|
||||||
cerr << "MRB loop boundary @ " << ev_time << endl;*/
|
cerr << "MRB loop boundary @ " << ev_time << endl;
|
||||||
|
|
||||||
// Return without reading data or writing to buffer (loop events have no data)
|
// 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
|
// FIXME: This is not correct, loses events after the loop this cycle
|
||||||
|
|
|
||||||
|
|
@ -456,6 +456,7 @@ MidiTrack::roll (nframes_t nframes, sframes_t start_frame, sframes_t end_frame,
|
||||||
|
|
||||||
if (did_loop) {
|
if (did_loop) {
|
||||||
/* add necessary note offs */
|
/* add necessary note offs */
|
||||||
|
cerr << "DID LOOP, RESOLVE NOTES\n";
|
||||||
_midi_state_tracker.resolve_notes (mbuf, end_frame-start_frame - 1);
|
_midi_state_tracker.resolve_notes (mbuf, end_frame-start_frame - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -38,9 +38,9 @@ public:
|
||||||
const Note<Time>& operator=(const Note<Time>& copy);
|
const Note<Time>& operator=(const Note<Time>& copy);
|
||||||
|
|
||||||
inline bool operator==(const Note<Time>& other) {
|
inline bool operator==(const Note<Time>& other) {
|
||||||
return time() == other.time() &&
|
return musical_time_equal (time(), other.time()) &&
|
||||||
note() == other.note() &&
|
note() == other.note() &&
|
||||||
length() == other.length() &&
|
musical_time_equal (length(), other.length()) &&
|
||||||
velocity() == other.velocity() &&
|
velocity() == other.velocity() &&
|
||||||
channel() == other.channel();
|
channel() == other.channel();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -64,6 +64,8 @@ public:
|
||||||
|
|
||||||
void flush() {};
|
void flush() {};
|
||||||
|
|
||||||
|
double round_to_file_precision (double val) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string _file_path;
|
std::string _file_path;
|
||||||
smf_t* _smf;
|
smf_t* _smf;
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <list>
|
#include <list>
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
namespace Evoral {
|
namespace Evoral {
|
||||||
|
|
||||||
|
|
@ -30,6 +31,11 @@ typedef uint32_t FrameTime;
|
||||||
/** Musical time: beats relative to some defined origin */
|
/** Musical time: beats relative to some defined origin */
|
||||||
typedef double MusicalTime;
|
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) */
|
/** Type of an event (opaque, mapped by application) */
|
||||||
typedef uint32_t EventType;
|
typedef uint32_t EventType;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
_off_event.buffer()[2] = 0x40;
|
||||||
|
|
||||||
assert(time() == t);
|
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(note() == n);
|
||||||
assert(velocity() == v);
|
assert(velocity() == v);
|
||||||
assert(_on_event.channel() == _off_event.channel());
|
assert(_on_event.channel() == _off_event.channel());
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
#define __STDC_LIMIT_MACROS 1
|
#define __STDC_LIMIT_MACROS 1
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
#include <cmath>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "libsmf/smf.h"
|
#include "libsmf/smf.h"
|
||||||
|
|
@ -262,5 +263,13 @@ SMF::end_write() THROW_FILE_ERROR
|
||||||
throw FileError();
|
throw FileError();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double
|
||||||
|
SMF::round_to_file_precision (double val) const
|
||||||
|
{
|
||||||
|
double div = ppqn();
|
||||||
|
|
||||||
|
return round (val * div) / div;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} // namespace Evoral
|
} // namespace Evoral
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue