summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2009-02-19 04:12:54 +0000
committerDavid Robillard <d@drobilla.net>2009-02-19 04:12:54 +0000
commit0f71728a925eb8f16c14c74f0dae9fdd53406a20 (patch)
tree01e056fde9fdcbe90c9bccdc03dce57b4bc043f9
parent8f572c3d3f79a86e6b86ccb71f9bee772e6fe738 (diff)
Interpret tempo time based on read position (not source timeline position which is more or less meaningless).
Move time conversion into the region view rather than the source. Adapt MIDI (including controllers) regions to the destination tempo when moved (e.g. dragging a region to a location with half the tempo will make the notes twice as long). git-svn-id: svn://localhost/ardour2/branches/3.0@4635 d708f5d6-7413-0410-9779-e7cbd77b26cf
-rw-r--r--gtk2_ardour/automation_region_view.cc3
-rw-r--r--gtk2_ardour/midi_region_view.cc4
-rw-r--r--gtk2_ardour/region_view.cc31
-rw-r--r--gtk2_ardour/region_view.h3
-rw-r--r--libs/ardour/ardour/midi_source.h39
-rw-r--r--libs/ardour/ardour/smf_source.h12
-rw-r--r--libs/ardour/ardour/source.h5
-rw-r--r--libs/ardour/import.cc4
-rw-r--r--libs/ardour/midi_diskstream.cc2
-rw-r--r--libs/ardour/midi_region.cc16
-rw-r--r--libs/ardour/midi_source.cc26
-rw-r--r--libs/ardour/smf_source.cc29
12 files changed, 92 insertions, 82 deletions
diff --git a/gtk2_ardour/automation_region_view.cc b/gtk2_ardour/automation_region_view.cc
index 98d402e348..3ba0794b17 100644
--- a/gtk2_ardour/automation_region_view.cc
+++ b/gtk2_ardour/automation_region_view.cc
@@ -70,8 +70,7 @@ AutomationRegionView::create_line (boost::shared_ptr<ARDOUR::AutomationList> lis
{
_line = boost::shared_ptr<AutomationLine>(new AutomationLine(
ARDOUR::EventTypeMap::instance().to_symbol(list->parameter()),
- trackview, *get_canvas_group(), list,
- &_region->source(0)->time_converter()));
+ trackview, *get_canvas_group(), list, &_time_converter));
_line->set_colors();
_line->set_interpolation(list->interpolation());
_line->show();
diff --git a/gtk2_ardour/midi_region_view.cc b/gtk2_ardour/midi_region_view.cc
index bb46a3d098..3087d3436e 100644
--- a/gtk2_ardour/midi_region_view.cc
+++ b/gtk2_ardour/midi_region_view.cc
@@ -1405,13 +1405,13 @@ MidiRegionView::get_position_pixels()
nframes64_t
MidiRegionView::beats_to_frames(double beats) const
{
- return midi_region()->midi_source()->time_converter().to(beats);
+ return _time_converter.to(beats);
}
double
MidiRegionView::frames_to_beats(nframes64_t frames) const
{
- return midi_region()->midi_source()->time_converter().from(frames);
+ return _time_converter.from(frames);
}
void
diff --git a/gtk2_ardour/region_view.cc b/gtk2_ardour/region_view.cc
index 54e0a9ef5e..1819df0401 100644
--- a/gtk2_ardour/region_view.cc
+++ b/gtk2_ardour/region_view.cc
@@ -65,25 +65,25 @@ RegionView::RegionView (ArdourCanvas::Group* parent,
double spu,
Gdk::Color& basic_color)
: TimeAxisViewItem (r->name(), *parent, tv, spu, basic_color, r->position(), r->length(), false,
-
- TimeAxisViewItem::Visibility (TimeAxisViewItem::ShowNameText|
- TimeAxisViewItem::ShowNameHighlight|
- TimeAxisViewItem::ShowFrame))
- , _region (r)
- , sync_mark(0)
- , sync_line(0)
- , editor(0)
- , current_visible_sync_position(0.0)
- , valid(false)
- , _enable_display(false)
- , _pixel_width(1.0)
- , in_destructor(false)
- , wait_for_data(false)
+ TimeAxisViewItem::Visibility (TimeAxisViewItem::ShowNameText|
+ TimeAxisViewItem::ShowNameHighlight| TimeAxisViewItem::ShowFrame))
+ , _region (r)
+ , sync_mark(0)
+ , sync_line(0)
+ , editor(0)
+ , current_visible_sync_position(0.0)
+ , valid(false)
+ , _enable_display(false)
+ , _pixel_width(1.0)
+ , in_destructor(false)
+ , wait_for_data(false)
+ , _time_converter(r->session(), r->position())
{
}
RegionView::RegionView (const RegionView& other)
: TimeAxisViewItem (other)
+ , _time_converter(other._time_converter)
{
/* derived concrete type will call init () */
@@ -96,6 +96,7 @@ RegionView::RegionView (const RegionView& other)
RegionView::RegionView (const RegionView& other, boost::shared_ptr<Region> other_region)
: TimeAxisViewItem (other)
+ , _time_converter(other._time_converter)
{
/* this is a pseudo-copy constructor used when dragging regions
around on the canvas.
@@ -128,6 +129,7 @@ RegionView::RegionView (ArdourCanvas::Group* parent,
, _pixel_width(1.0)
, in_destructor(false)
, wait_for_data(false)
+ , _time_converter(r->session(), r->position())
{
}
@@ -246,6 +248,7 @@ RegionView::region_resized (Change what_changed)
if (what_changed & ARDOUR::PositionChanged) {
set_position (_region->position(), 0);
+ _time_converter.set_origin(_region->position());
}
if (what_changed & Change (StartChanged|LengthChanged)) {
diff --git a/gtk2_ardour/region_view.h b/gtk2_ardour/region_view.h
index de9d95ccf3..0db41c24f9 100644
--- a/gtk2_ardour/region_view.h
+++ b/gtk2_ardour/region_view.h
@@ -25,6 +25,7 @@
#include <libgnomecanvasmm/polygon.h>
#include <sigc++/signal.h>
#include <ardour/region.h>
+#include <ardour/beats_frames_converter.h>
#include "time_axis_view_item.h"
#include "automation_line.h"
@@ -149,6 +150,8 @@ class RegionView : public TimeAxisViewItem
that will be played at any given time.
*/
std::list<ArdourCanvas::SimpleRect*> _coverage_frames;
+
+ ARDOUR::BeatsFramesConverter _time_converter;
};
#endif /* __gtk_ardour_region_view_h__ */
diff --git a/libs/ardour/ardour/midi_source.h b/libs/ardour/ardour/midi_source.h
index 774b3ab372..1b2188e8dd 100644
--- a/libs/ardour/ardour/midi_source.h
+++ b/libs/ardour/ardour/midi_source.h
@@ -47,12 +47,28 @@ class MidiSource : virtual public Source
MidiSource (Session& session, const XMLNode&);
virtual ~MidiSource ();
- virtual nframes_t midi_read (MidiRingBuffer<nframes_t>& dst, nframes_t start, nframes_t cnt,
+ /** Read the data in a given time range from the MIDI source.
+ * All time stamps in parameters are in audio frames (even if the source has tempo time).
+ * \param dst Ring buffer where read events are written
+ * \param position Start position of the SOURCE in this read context
+ * \param start Start of range to be read
+ * \param cnt Length of range to be read (in audio frames)
+ * \param stamp_offset Offset to add to event times written to dst
+ * \param negative_stamp_offset Offset to subtract from event times written to dst
+ */
+ virtual nframes_t midi_read (MidiRingBuffer<nframes_t>& dst,
+ nframes_t position,
+ nframes_t start, nframes_t cnt,
nframes_t stamp_offset, nframes_t negative_stamp_offset) const;
- virtual nframes_t midi_write (MidiRingBuffer<nframes_t>& src, nframes_t cnt);
+
+ virtual nframes_t midi_write (MidiRingBuffer<nframes_t>& src,
+ nframes_t position,
+ nframes_t cnt);
virtual void append_event_unlocked_beats(const Evoral::Event<double>& ev) = 0;
- virtual void append_event_unlocked_frames(const Evoral::Event<nframes_t>& ev) = 0;
+
+ virtual void append_event_unlocked_frames(const Evoral::Event<nframes_t>& ev,
+ nframes_t position) = 0;
virtual void mark_streaming_midi_write_started (NoteMode mode, nframes_t start_time);
virtual void mark_streaming_write_started ();
@@ -86,29 +102,26 @@ class MidiSource : virtual public Source
void set_note_mode(NoteMode mode);
- void set_timeline_position (int64_t pos);
-
boost::shared_ptr<MidiModel> model() { return _model; }
void set_model(boost::shared_ptr<MidiModel> m) { _model = m; }
void drop_model() { _model.reset(); }
- const Evoral::TimeConverter<double, nframes_t>& time_converter() const {
- return _converter;
- }
-
protected:
virtual void flush_midi() = 0;
- virtual nframes_t read_unlocked (MidiRingBuffer<nframes_t>& dst, nframes_t start, nframes_t cnt,
+ virtual nframes_t read_unlocked (MidiRingBuffer<nframes_t>& dst,
+ nframes_t position,
+ nframes_t start, nframes_t cnt,
nframes_t stamp_offset, nframes_t negative_stamp_offset) const = 0;
- virtual nframes_t write_unlocked (MidiRingBuffer<nframes_t>& dst, nframes_t cnt) = 0;
+
+ virtual nframes_t write_unlocked (MidiRingBuffer<nframes_t>& dst,
+ nframes_t position,
+ nframes_t cnt) = 0;
std::string _captured_for;
mutable uint32_t _read_data_count; ///< modified in read()
mutable uint32_t _write_data_count; ///< modified in write()
- BeatsFramesConverter _converter;
-
boost::shared_ptr<MidiModel> _model;
bool _writing;
diff --git a/libs/ardour/ardour/smf_source.h b/libs/ardour/ardour/smf_source.h
index 259328c5fa..7942a118af 100644
--- a/libs/ardour/ardour/smf_source.h
+++ b/libs/ardour/ardour/smf_source.h
@@ -52,7 +52,7 @@ public:
bool set_name (const std::string& newname) { return (set_source_name(newname, false) == 0); }
void append_event_unlocked_beats (const Evoral::Event<double>& ev);
- void append_event_unlocked_frames (const Evoral::Event<nframes_t>& ev);
+ void append_event_unlocked_frames (const Evoral::Event<nframes_t>& ev, nframes_t position);
void mark_streaming_midi_write_started (NoteMode mode, nframes_t start_time);
void mark_streaming_write_completed ();
@@ -70,15 +70,15 @@ public:
static bool safe_midi_file_extension (const Glib::ustring& path);
private:
- nframes_t read_unlocked (
- MidiRingBuffer<nframes_t>& dst,
+ nframes_t read_unlocked (MidiRingBuffer<nframes_t>& dst,
+ nframes_t position,
nframes_t start,
- nframes_t cn,
+ nframes_t cnt,
nframes_t stamp_offset,
nframes_t negative_stamp_offset) const;
- nframes_t write_unlocked (
- MidiRingBuffer<nframes_t>& src,
+ nframes_t write_unlocked (MidiRingBuffer<nframes_t>& src,
+ nframes_t position,
nframes_t cnt);
void set_default_controls_interpolation ();
diff --git a/libs/ardour/ardour/source.h b/libs/ardour/ardour/source.h
index a388c8db3a..dd86ebe521 100644
--- a/libs/ardour/ardour/source.h
+++ b/libs/ardour/ardour/source.h
@@ -26,7 +26,6 @@
#include <boost/utility.hpp>
#include <sigc++/signal.h>
#include <pbd/statefuldestructible.h>
-#include <evoral/TimeConverter.hpp>
#include <ardour/ardour.h>
#include <ardour/session_object.h>
@@ -112,10 +111,6 @@ class Source : public SessionObject, public boost::noncopyable
void set_allow_remove_if_empty (bool yn);
- virtual const Evoral::TimeConverter<double, nframes_t>& time_converter() const {
- return Evoral::IdentityConverter<double, nframes_t>();
- }
-
Glib::Mutex& mutex() { return _lock; }
Flag flags() const { return _flags; }
diff --git a/libs/ardour/import.cc b/libs/ardour/import.cc
index 92ecaec753..306247f009 100644
--- a/libs/ardour/import.cc
+++ b/libs/ardour/import.cc
@@ -352,8 +352,10 @@ write_midi_data_to_new_files (Evoral::SMF* source, Session::ImportStatus& status
status.progress += 0.01;
}
+ const nframes64_t pos = 0;
const double length_beats = ceil(t / (double)source->ppqn());
- smfs->update_length(0, smfs->time_converter().to(length_beats));
+ BeatsFramesConverter converter(smfs->session(), pos);
+ smfs->update_length(pos, converter.to(length_beats));
smfs->end_write();
if (status.cancel) {
diff --git a/libs/ardour/midi_diskstream.cc b/libs/ardour/midi_diskstream.cc
index ff6d05a4ac..4e124425b9 100644
--- a/libs/ardour/midi_diskstream.cc
+++ b/libs/ardour/midi_diskstream.cc
@@ -904,7 +904,7 @@ MidiDiskstream::do_flush (RunContext context, bool force_flush)
assert(!destructive());
if (record_enabled() && _session.transport_frame() - _last_flush_frame > disk_io_chunk_frames) {
- if ((!_write_source) || _write_source->midi_write (*_capture_buf, to_write) != to_write) {
+ if ((!_write_source) || _write_source->midi_write (*_capture_buf, capture_start_frame, to_write) != to_write) {
error << string_compose(_("MidiDiskstream %1: cannot write to disk"), _id) << endmsg;
return -1;
} else {
diff --git a/libs/ardour/midi_region.cc b/libs/ardour/midi_region.cc
index fcbf187721..1ce4bbdb7f 100644
--- a/libs/ardour/midi_region.cc
+++ b/libs/ardour/midi_region.cc
@@ -184,16 +184,12 @@ MidiRegion::_read_at (const SourceList& srcs, MidiRingBuffer<nframes_t>& dst, nf
}
if (src->midi_read (
- // the destination buffer
- dst,
- // where to start reading in the region
- _start + internal_offset,
- // how many bytes
- to_read,
- // the offset in the output buffer
- output_buffer_position,
- // what to substract from note times written in the output buffer
- negative_output_buffer_position
+ dst, // destination buffer
+ _position - _start, // start position of the source in this read context
+ _start + internal_offset, // where to start reading in the region
+ to_read, // read duration in frames
+ output_buffer_position, // the offset in the output buffer
+ negative_output_buffer_position // amount to substract from note times
) != to_read) {
return 0; /* "read nothing" */
}
diff --git a/libs/ardour/midi_source.cc b/libs/ardour/midi_source.cc
index 06437852c6..b9f7776df8 100644
--- a/libs/ardour/midi_source.cc
+++ b/libs/ardour/midi_source.cc
@@ -53,7 +53,6 @@ MidiSource::MidiSource (Session& s, string name, Source::Flag flags)
: Source (s, DataType::MIDI, name, flags)
, _read_data_count(0)
, _write_data_count(0)
- , _converter(s, _timeline_position)
, _writing (false)
, _last_read_end(0)
{
@@ -63,7 +62,6 @@ MidiSource::MidiSource (Session& s, const XMLNode& node)
: Source (s, node)
, _read_data_count(0)
, _write_data_count(0)
- , _converter(s, _timeline_position)
, _writing (false)
, _last_read_end(0)
{
@@ -110,13 +108,16 @@ MidiSource::invalidate ()
}
nframes_t
-MidiSource::midi_read (MidiRingBuffer<nframes_t>& dst, nframes_t start, nframes_t cnt,
+MidiSource::midi_read (MidiRingBuffer<nframes_t>& dst, nframes_t position,
+ nframes_t start, nframes_t cnt,
nframes_t stamp_offset, nframes_t negative_stamp_offset) const
{
-
Glib::Mutex::Lock lm (_lock);
+
+ BeatsFramesConverter converter(_session, position);
+
if (_model) {
-#define BEATS_TO_FRAMES(t) (_converter.to(t) + stamp_offset - negative_stamp_offset)
+#define BEATS_TO_FRAMES(t) (converter.to(t) + stamp_offset - negative_stamp_offset)
Evoral::Sequence<double>::const_iterator& i = _model_iter;
@@ -141,15 +142,15 @@ MidiSource::midi_read (MidiRingBuffer<nframes_t>& dst, nframes_t start, nframes_
}
return cnt;
} else {
- return read_unlocked (dst, start, cnt, stamp_offset, negative_stamp_offset);
+ return read_unlocked (dst, position, start, cnt, stamp_offset, negative_stamp_offset);
}
}
nframes_t
-MidiSource::midi_write (MidiRingBuffer<nframes_t>& dst, nframes_t cnt)
+MidiSource::midi_write (MidiRingBuffer<nframes_t>& dst, nframes_t position, nframes_t cnt)
{
Glib::Mutex::Lock lm (_lock);
- return write_unlocked (dst, cnt);
+ return write_unlocked (dst, position, cnt);
}
bool
@@ -163,16 +164,9 @@ MidiSource::file_changed (string path)
}
void
-MidiSource::set_timeline_position (int64_t pos)
-{
- Source::set_timeline_position(pos);
- _converter.set_origin(pos);
-}
-
-void
MidiSource::mark_streaming_midi_write_started (NoteMode mode, nframes_t start_frame)
{
- set_timeline_position(start_frame); // why do I have a feeling this can break somehow...
+ set_timeline_position(start_frame);
if (_model) {
_model->set_note_mode(mode);
diff --git a/libs/ardour/smf_source.cc b/libs/ardour/smf_source.cc
index be9b9dd3f1..128acca742 100644
--- a/libs/ardour/smf_source.cc
+++ b/libs/ardour/smf_source.cc
@@ -95,7 +95,8 @@ SMFSource::~SMFSource ()
/** All stamps in audio frames */
nframes_t
-SMFSource::read_unlocked (MidiRingBuffer<nframes_t>& dst, nframes_t start, nframes_t dur,
+SMFSource::read_unlocked (MidiRingBuffer<nframes_t>& dst, nframes_t position,
+ nframes_t start, nframes_t dur,
nframes_t stamp_offset, nframes_t negative_stamp_offset) const
{
int ret = 0;
@@ -110,8 +111,10 @@ SMFSource::read_unlocked (MidiRingBuffer<nframes_t>& dst, nframes_t start, nfram
uint8_t* ev_buffer = 0;
size_t scratch_size = 0; // keep track of scratch to minimize reallocs
+
+ BeatsFramesConverter converter(_session, position);
- const uint64_t start_ticks = (uint64_t)(_converter.from(start) * ppqn());
+ const uint64_t start_ticks = (uint64_t)(converter.from(start) * ppqn());
if (_last_read_end == 0 || start != _last_read_end) {
cerr << "SMFSource::read_unlocked seeking to " << start << endl;
@@ -143,7 +146,7 @@ SMFSource::read_unlocked (MidiRingBuffer<nframes_t>& dst, nframes_t start, nfram
ev_type = EventTypeMap::instance().midi_event_type(ev_buffer[0]);
assert(time >= start_ticks);
- const nframes_t ev_frame_time = _converter.to(time / (double)ppqn()) + stamp_offset;
+ const nframes_t ev_frame_time = converter.to(time / (double)ppqn()) + stamp_offset;
if (ev_frame_time < start + dur) {
dst.write(ev_frame_time - negative_stamp_offset, ev_type, ev_size, ev_buffer);
@@ -164,7 +167,7 @@ SMFSource::read_unlocked (MidiRingBuffer<nframes_t>& dst, nframes_t start, nfram
/** All stamps in audio frames */
nframes_t
-SMFSource::write_unlocked (MidiRingBuffer<nframes_t>& src, nframes_t dur)
+SMFSource::write_unlocked (MidiRingBuffer<nframes_t>& src, nframes_t position, nframes_t dur)
{
_write_data_count = 0;
@@ -183,7 +186,7 @@ SMFSource::write_unlocked (MidiRingBuffer<nframes_t>& src, nframes_t dur)
while (true) {
bool ret = src.peek_time(&time);
- if (!ret || time - _timeline_position > _length + dur) {
+ if (!ret || time - position > _length + dur) {
break;
}
@@ -203,8 +206,8 @@ SMFSource::write_unlocked (MidiRingBuffer<nframes_t>& src, nframes_t dur)
break;
}
- assert(time >= _timeline_position);
- time -= _timeline_position;
+ assert(time >= position);
+ time -= position;
ev.set(buf, size, time);
ev.set_event_type(EventTypeMap::instance().midi_event_type(ev.buffer()[0]));
@@ -214,7 +217,7 @@ SMFSource::write_unlocked (MidiRingBuffer<nframes_t>& src, nframes_t dur)
continue;
}
- append_event_unlocked_frames(ev);
+ append_event_unlocked_frames(ev, position);
}
if (_model) {
@@ -227,7 +230,7 @@ SMFSource::write_unlocked (MidiRingBuffer<nframes_t>& src, nframes_t dur)
const nframes_t oldlen = _length;
update_length(oldlen, dur);
- ViewDataRangeReady(_timeline_position + oldlen, dur); /* EMIT SIGNAL */
+ ViewDataRangeReady(position + oldlen, dur); /* EMIT SIGNAL */
return dur;
}
@@ -266,7 +269,7 @@ SMFSource::append_event_unlocked_beats (const Evoral::Event<double>& ev)
/** Append an event with a timestamp in frames (nframes_t) */
void
-SMFSource::append_event_unlocked_frames (const Evoral::Event<nframes_t>& ev)
+SMFSource::append_event_unlocked_frames (const Evoral::Event<nframes_t>& ev, nframes_t position)
{
if (ev.size() == 0) {
return;
@@ -282,8 +285,10 @@ SMFSource::append_event_unlocked_frames (const Evoral::Event<nframes_t>& ev)
return;
}
+ BeatsFramesConverter converter(_session, position);
+
const nframes_t delta_time_frames = ev.time() - _last_ev_time_frames;
- const double delta_time_beats = _converter.from(delta_time_frames);
+ const double delta_time_beats = converter.from(delta_time_frames);
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());
@@ -292,7 +297,7 @@ SMFSource::append_event_unlocked_frames (const Evoral::Event<nframes_t>& ev)
_write_data_count += ev.size();
if (_model) {
- const double ev_time_beats = _converter.from(ev.time());
+ const double ev_time_beats = converter.from(ev.time());
const Evoral::Event<double> beat_ev(
ev.event_type(), ev_time_beats, ev.size(), (uint8_t*)ev.buffer());
_model->append(beat_ev);