summaryrefslogtreecommitdiff
path: root/libs/ardour
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2009-08-27 03:09:30 +0000
committerPaul Davis <paul@linuxaudiosystems.com>2009-08-27 03:09:30 +0000
commit3845af6ce92ef15637ffb09410f442e7b4a104c3 (patch)
tree218a29f23c83c3ac57c857d3b1f599f1e6d97a14 /libs/ardour
parentc6be9b688802198e04a07dc902c49d1d6b66340e (diff)
lots of MIDI editing stuff. to be explained on the website when its done
git-svn-id: svn://localhost/ardour2/branches/3.0@5596 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'libs/ardour')
-rw-r--r--libs/ardour/ardour/midi_model.h3
-rw-r--r--libs/ardour/ardour/midi_operator.h42
-rw-r--r--libs/ardour/ardour/midi_source.h4
-rw-r--r--libs/ardour/ardour/midi_track.h3
-rw-r--r--libs/ardour/ardour/quantize.h28
-rw-r--r--libs/ardour/ardour/route.h3
-rw-r--r--libs/ardour/ardour/smf_source.h2
-rw-r--r--libs/ardour/ardour/tempo.h2
-rw-r--r--libs/ardour/ardour/types.h6
-rw-r--r--libs/ardour/delivery.cc2
-rw-r--r--libs/ardour/midi_model.cc29
-rw-r--r--libs/ardour/midi_ring_buffer.cc10
-rw-r--r--libs/ardour/midi_track.cc21
-rw-r--r--libs/ardour/quantize.cc108
-rw-r--r--libs/ardour/route.cc5
-rw-r--r--libs/ardour/tempo.cc98
-rw-r--r--libs/ardour/track.cc3
17 files changed, 289 insertions, 80 deletions
diff --git a/libs/ardour/ardour/midi_model.h b/libs/ardour/ardour/midi_model.h
index 3feda1a22c..967372fa9a 100644
--- a/libs/ardour/ardour/midi_model.h
+++ b/libs/ardour/ardour/midi_model.h
@@ -47,7 +47,7 @@ class MidiSource;
* Because of this MIDI controllers and automatable controllers/widgets/etc
* are easily interchangeable.
*/
-class MidiModel : public AutomatableSequence<double> {
+class MidiModel : public AutomatableSequence<Evoral::MusicalTime> {
public:
typedef double TimeType;
@@ -91,6 +91,7 @@ public:
MidiModel::DeltaCommand* new_delta_command(const std::string name="midi edit");
void apply_command(Session& session, Command* cmd);
+ void apply_command_as_subcommand(Session& session, Command* cmd);
bool write_to(boost::shared_ptr<MidiSource> source);
diff --git a/libs/ardour/ardour/midi_operator.h b/libs/ardour/ardour/midi_operator.h
new file mode 100644
index 0000000000..e3ed6aabfd
--- /dev/null
+++ b/libs/ardour/ardour/midi_operator.h
@@ -0,0 +1,42 @@
+/*
+ Copyright (C) 2009 Paul Davis
+
+ This program 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.
+
+ This program 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 more 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#ifndef __libardour_midi_operator_h__
+#define __libardour_midi_operator_h__
+
+#include <vector>
+#include <string>
+
+#include "evoral/types.hpp"
+#include "evoral/Sequence.hpp"
+
+namespace ARDOUR {
+
+class MidiOperator {
+ public:
+ MidiOperator() {}
+ virtual ~MidiOperator() {}
+
+ virtual int operator() (std::vector<Evoral::Sequence<Evoral::MusicalTime>::Notes>&) = 0;
+ virtual std::string name() const = 0;
+};
+
+} /* namespace */
+
+#endif /* __libardour_midi_operator_h__ */
diff --git a/libs/ardour/ardour/midi_source.h b/libs/ardour/ardour/midi_source.h
index cf49e59458..a479b4a8a8 100644
--- a/libs/ardour/ardour/midi_source.h
+++ b/libs/ardour/ardour/midi_source.h
@@ -65,7 +65,7 @@ class MidiSource : virtual public Source
sframes_t source_start,
nframes_t cnt);
- virtual void append_event_unlocked_beats(const Evoral::Event<double>& ev) = 0;
+ virtual void append_event_unlocked_beats(const Evoral::Event<Evoral::MusicalTime>& ev) = 0;
virtual void append_event_unlocked_frames(const Evoral::Event<nframes_t>& ev,
sframes_t source_start) = 0;
@@ -128,7 +128,7 @@ class MidiSource : virtual public Source
boost::shared_ptr<MidiModel> _model;
bool _writing;
- mutable Evoral::Sequence<double>::const_iterator _model_iter;
+ mutable Evoral::Sequence<Evoral::MusicalTime>::const_iterator _model_iter;
mutable double _length_beats;
mutable sframes_t _last_read_end;
diff --git a/libs/ardour/ardour/midi_track.h b/libs/ardour/ardour/midi_track.h
index e7ffd40d67..5c5ef5c26c 100644
--- a/libs/ardour/ardour/midi_track.h
+++ b/libs/ardour/ardour/midi_track.h
@@ -84,7 +84,8 @@ protected:
int _set_state (const XMLNode&, bool call_base);
private:
- void write_controller_messages(MidiBuffer& buf, sframes_t start_frame, sframes_t end_frame, nframes_t nframes);
+ void write_out_of_band_data (BufferSet& bufs, sframes_t start_frame, sframes_t end_frame,
+ nframes_t nframes);
int set_diskstream (boost::shared_ptr<MidiDiskstream> ds);
void use_new_diskstream ();
diff --git a/libs/ardour/ardour/quantize.h b/libs/ardour/ardour/quantize.h
index f7307c194c..57e5467294 100644
--- a/libs/ardour/ardour/quantize.h
+++ b/libs/ardour/ardour/quantize.h
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2007 Paul Davis
+ Copyright (C) 2007-2009 Paul Davis
Author: Dave Robillard
This program is free software; you can redistribute it and/or modify
@@ -21,19 +21,33 @@
#ifndef __ardour_quantize_h__
#define __ardour_quantize_h__
-#include "ardour/filter.h"
+#include "ardour/types.h"
+#include "ardour/midi_operator.h"
namespace ARDOUR {
-class Quantize : public Filter {
+class Session;
+
+class Quantize : public MidiOperator {
public:
- Quantize (ARDOUR::Session&, double q);
- ~Quantize ();
+ Quantize (ARDOUR::Session&, QuantizeType type,
+ bool snap_start, bool snap_end,
+ double start_grid, double end_grid,
+ float strength, float swing, float threshold);
+ ~Quantize ();
- int run (boost::shared_ptr<ARDOUR::Region>);
+ int operator() (std::vector<Evoral::Sequence<Evoral::MusicalTime>::Notes>&);
+ std::string name() const { return std::string ("quantize"); }
private:
- double _q;
+ ARDOUR::Session& session;
+ bool _snap_start;
+ bool _snap_end;
+ double _start_grid;
+ double _end_grid;
+ float _strength;
+ float _swing;
+ float _threshold;
};
} /* namespace */
diff --git a/libs/ardour/ardour/route.h b/libs/ardour/ardour/route.h
index 9195a50060..34bf9e8d9f 100644
--- a/libs/ardour/ardour/route.h
+++ b/libs/ardour/ardour/route.h
@@ -326,6 +326,9 @@ class Route : public SessionObject, public AutomatableControls
void passthru (sframes_t start_frame, sframes_t end_frame,
nframes_t nframes, int declick);
+ virtual void write_out_of_band_data (BufferSet& /* bufs */, sframes_t /* start_frame */, sframes_t /* end_frame */,
+ nframes_t /* nframes */) {}
+
virtual void process_output_buffers (BufferSet& bufs,
sframes_t start_frame, sframes_t end_frame,
nframes_t nframes, bool with_processors, int declick);
diff --git a/libs/ardour/ardour/smf_source.h b/libs/ardour/ardour/smf_source.h
index dc9cbeee55..73bef5480a 100644
--- a/libs/ardour/ardour/smf_source.h
+++ b/libs/ardour/ardour/smf_source.h
@@ -51,7 +51,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_beats (const Evoral::Event<Evoral::MusicalTime>& ev);
void append_event_unlocked_frames (const Evoral::Event<nframes_t>& ev, sframes_t source_start);
void mark_streaming_midi_write_started (NoteMode mode, sframes_t start_time);
diff --git a/libs/ardour/ardour/tempo.h b/libs/ardour/ardour/tempo.h
index fcda463fe1..843437dab7 100644
--- a/libs/ardour/ardour/tempo.h
+++ b/libs/ardour/ardour/tempo.h
@@ -204,7 +204,7 @@ class TempoMap : public PBD::StatefulDestructible
nframes_t round_to_bar (nframes_t frame, int dir);
nframes_t round_to_beat (nframes_t frame, int dir);
- nframes_t round_to_beat_subdivision (nframes_t fr, int sub_num);
+ nframes_t round_to_beat_subdivision (nframes_t fr, int sub_num, int dir);
nframes_t round_to_tick (nframes_t frame, int dir);
void set_length (nframes_t frames);
diff --git a/libs/ardour/ardour/types.h b/libs/ardour/ardour/types.h
index 809eb5b2b2..1a30cfd769 100644
--- a/libs/ardour/ardour/types.h
+++ b/libs/ardour/ardour/types.h
@@ -446,6 +446,12 @@ namespace ARDOUR {
Rectified
};
+ enum QuantizeType {
+ Plain,
+ Legato,
+ Groove
+ };
+
} // namespace ARDOUR
std::istream& operator>>(std::istream& o, ARDOUR::SampleFormat& sf);
diff --git a/libs/ardour/delivery.cc b/libs/ardour/delivery.cc
index 01ff226b5e..1b5f96d36c 100644
--- a/libs/ardour/delivery.cc
+++ b/libs/ardour/delivery.cc
@@ -22,6 +22,8 @@
#include "pbd/enumwriter.h"
#include "pbd/convert.h"
+#include "ardour/midi_buffer.h"
+
#include "ardour/delivery.h"
#include "ardour/audio_buffer.h"
#include "ardour/amp.h"
diff --git a/libs/ardour/midi_model.cc b/libs/ardour/midi_model.cc
index 0c0c0ead5b..da524307f6 100644
--- a/libs/ardour/midi_model.cc
+++ b/libs/ardour/midi_model.cc
@@ -70,6 +70,19 @@ MidiModel::apply_command(Session& session, Command* cmd)
set_edited(true);
}
+/** Apply a command as part of a larger reversible transaction
+ *
+ * Ownership of cmd is taken, it must not be deleted by the caller.
+ * The command will constitute one item on the undo stack.
+ */
+void
+MidiModel::apply_command_as_subcommand(Session& session, Command* cmd)
+{
+ (*cmd)();
+ session.add_command(cmd);
+ set_edited(true);
+}
+
// DeltaCommand
@@ -107,17 +120,19 @@ MidiModel::DeltaCommand::operator()()
{
// This could be made much faster by using a priority_queue for added and
// removed notes (or sort here), and doing a single iteration over _model
-
+
Glib::Mutex::Lock lm (_model->_midi_source->mutex());
_model->_midi_source->invalidate(); // release model read lock
_model->write_lock();
- for (NoteList::iterator i = _added_notes.begin(); i != _added_notes.end(); ++i)
+ for (NoteList::iterator i = _added_notes.begin(); i != _added_notes.end(); ++i) {
_model->add_note_unlocked(*i);
+ }
- for (NoteList::iterator i = _removed_notes.begin(); i != _removed_notes.end(); ++i)
+ for (NoteList::iterator i = _removed_notes.begin(); i != _removed_notes.end(); ++i) {
_model->remove_note_unlocked(*i);
-
+ }
+
_model->write_unlock();
_model->ContentsChanged(); /* EMIT SIGNAL */
}
@@ -132,11 +147,13 @@ MidiModel::DeltaCommand::undo()
_model->_midi_source->invalidate(); // release model read lock
_model->write_lock();
- for (NoteList::iterator i = _added_notes.begin(); i != _added_notes.end(); ++i)
+ for (NoteList::iterator i = _added_notes.begin(); i != _added_notes.end(); ++i) {
_model->remove_note_unlocked(*i);
+ }
- for (NoteList::iterator i = _removed_notes.begin(); i != _removed_notes.end(); ++i)
+ for (NoteList::iterator i = _removed_notes.begin(); i != _removed_notes.end(); ++i) {
_model->add_note_unlocked(*i);
+ }
_model->write_unlock();
_model->ContentsChanged(); /* EMIT SIGNAL */
diff --git a/libs/ardour/midi_ring_buffer.cc b/libs/ardour/midi_ring_buffer.cc
index 746dc3b3eb..007d5271c8 100644
--- a/libs/ardour/midi_ring_buffer.cc
+++ b/libs/ardour/midi_ring_buffer.cc
@@ -24,7 +24,7 @@ using namespace std;
namespace ARDOUR {
-/** Read a block of MIDI events from buffer.
+/** Read a block of MIDI events from buffer into a MidiBuffer.
*
* Timestamps of events returned are relative to start (i.e. event with stamp 0
* occurred at start), with offset added.
@@ -106,11 +106,13 @@ MidiRingBuffer<T>::read(MidiBuffer& dst, nframes_t start, nframes_t end, nframes
// write MIDI buffer contents
success = Evoral::EventRingBuffer<T>::full_read(ev_size, write_loc);
- /*cerr << "wrote MidiEvent to Buffer: ";
+#if 0
+ cerr << "wrote MidiEvent to Buffer: " << hex;
for (size_t i=0; i < ev_size; ++i) {
- printf("%X ", write_loc[i]);
+ cerr << (int) write_loc[i] << ' ';
}
- printf("\n");*/
+ cerr << dec << endl;
+#endif
if (success) {
if (is_channel_event(status) && get_channel_mode() == ForceChannel) {
diff --git a/libs/ardour/midi_track.cc b/libs/ardour/midi_track.cc
index 5a53cecc3c..4c575e8cc4 100644
--- a/libs/ardour/midi_track.cc
+++ b/libs/ardour/midi_track.cc
@@ -401,7 +401,6 @@ MidiTrack::roll (nframes_t nframes, sframes_t start_frame, sframes_t end_frame,
_silent = false;
if ((dret = diskstream->process (transport_frame, nframes, can_record, rec_monitors_input)) != 0) {
-
silence (nframes);
return dret;
}
@@ -416,10 +415,10 @@ MidiTrack::roll (nframes_t nframes, sframes_t start_frame, sframes_t end_frame,
/* not actually recording, but we want to hear the input material anyway,
at least potentially (depending on monitoring options)
- */
+ */
passthru (start_frame, end_frame, nframes, 0);
-
+
} else {
/*
XXX is it true that the earlier test on n_outputs()
@@ -434,12 +433,15 @@ MidiTrack::roll (nframes_t nframes, sframes_t start_frame, sframes_t end_frame,
//const size_t limit = n_process_buffers().n_audio();
BufferSet& bufs = _session.get_scratch_buffers (n_process_buffers());
+
+ diskstream->get_playback (bufs.get_midi(0), start_frame, end_frame);
+
+ /* append immediate messages to the first MIDI buffer (thus sending it to the first output port) */
- diskstream->get_playback(bufs.get_midi(0), start_frame, end_frame);
+ write_out_of_band_data (bufs, start_frame, end_frame, nframes);
process_output_buffers (bufs, start_frame, end_frame, nframes,
(!_session.get_record_enabled() || !Config->get_do_not_record_plugins()), declick);
-
}
_main_outs->flush (nframes);
@@ -448,13 +450,12 @@ MidiTrack::roll (nframes_t nframes, sframes_t start_frame, sframes_t end_frame,
}
void
-MidiTrack::write_controller_messages(MidiBuffer& output_buf, sframes_t /*start*/, sframes_t /*end*/, nframes_t nframes)
+MidiTrack::write_out_of_band_data (BufferSet& bufs, sframes_t /*start*/, sframes_t /*end*/, nframes_t nframes)
{
- // Append immediate events (UI controls)
-
- // XXX TAKE _port_offset in Port into account???
+ // Append immediate events
- _immediate_events.read (output_buf, 0, 0, nframes - 1); // all stamps = 0
+ MidiBuffer& buf (bufs.get_midi (0));
+ _immediate_events.read (buf, 0, 0, nframes - 1); // all stamps = 0
}
int
diff --git a/libs/ardour/quantize.cc b/libs/ardour/quantize.cc
index e5f4abeccf..becb3bd491 100644
--- a/libs/ardour/quantize.cc
+++ b/libs/ardour/quantize.cc
@@ -16,6 +16,7 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#include <cmath>
#include "pbd/basename.h"
@@ -31,15 +32,24 @@
using namespace std;
using namespace ARDOUR;
-
-/** Quantize notes, valid for MIDI regions only.
+/** Quantize notes
*
- * Q is the quantize value in beats, ie 1.0 = quantize to beats,
+ * grid parameters are the quantize value in beats, ie 1.0 = quantize to beats,
* 0.25 = quantize to beats/4, etc.
*/
-Quantize::Quantize (Session& s, double q)
- : Filter (s)
- , _q(q)
+
+Quantize::Quantize (Session& s, QuantizeType /* type */,
+ bool snap_start, bool snap_end,
+ double start_grid, double end_grid,
+ float strength, float swing, float threshold)
+ : session (s)
+ , _snap_start (snap_start)
+ , _snap_end (snap_end)
+ , _start_grid(start_grid)
+ , _end_grid(end_grid)
+ , _strength (strength/100.0)
+ , _swing (swing/100.0)
+ , _threshold (threshold)
{
}
@@ -48,32 +58,70 @@ Quantize::~Quantize ()
}
int
-Quantize::run (boost::shared_ptr<Region> r)
+Quantize::operator () (std::vector<Evoral::Sequence<Evoral::MusicalTime>::Notes>& seqs)
{
- boost::shared_ptr<MidiRegion> region = boost::dynamic_pointer_cast<MidiRegion>(r);
- if (!region)
- return -1;
-
- // FIXME: how to make a whole file region if it isn't?
- //assert(region->whole_file());
-
- boost::shared_ptr<MidiSource> src = region->midi_source(0);
- src->load_model();
-
- boost::shared_ptr<MidiModel> model = src->model();
-
- for (Evoral::Sequence<MidiModel::TimeType>::Notes::iterator i = model->notes().begin();
- i != model->notes().end(); ++i) {
- const double new_time = lrint((*i)->time() / _q) * _q;
- double new_dur = lrint((*i)->length() / _q) * _q;
- if (new_dur == 0.0)
- new_dur = _q;
-
- (*i)->set_time(new_time);
- (*i)->set_length(new_dur);
+ bool even;
+
+ for (std::vector<Evoral::Sequence<Evoral::MusicalTime>::Notes>::iterator s = seqs.begin();
+ s != seqs.end(); ++s) {
+
+ even = false;
+
+ for (Evoral::Sequence<MidiModel::TimeType>::Notes::iterator i = (*s).begin();
+ i != (*s).end(); ++i) {
+
+ double new_start = round ((*i)->time() / _start_grid) * _start_grid;
+ double new_end = round ((*i)->end_time() / _end_grid) * _end_grid;
+ double delta;
+
+ if (_swing > 0.0 && !even) {
+
+ double next_grid = new_start + _start_grid;
+
+ /* find a spot 2/3 (* swing factor) of the way between the grid point
+ we would put this note at, and the nominal position of the next note.
+ */
+
+ new_start = new_start + (2.0/3.0 * _swing * (next_grid - new_start));
+
+ } else if (_swing < 0.0 && !even) {
+
+ double prev_grid = new_start - _start_grid;
+
+ /* find a spot 2/3 (* swing factor) of the way between the grid point
+ we would put this note at, and the nominal position of the previous note.
+ */
+
+ new_start = new_start - (2.0/3.0 * _swing * (new_start - prev_grid));
+
+ }
+
+ delta = new_start - (*i)->time();
+
+ if (fabs (delta) >= _threshold) {
+ if (_snap_start) {
+ delta *= _strength;
+ (*i)->set_time ((*i)->time() + delta);
+ }
+ }
+
+ if (_snap_end) {
+ delta = new_end - (*i)->end_time();
+
+ if (fabs (delta) >= _threshold) {
+ double new_dur = new_end - new_start;
+
+ if (new_dur == 0.0) {
+ new_dur = _end_grid;
+ }
+
+ (*i)->set_length (new_dur);
+ }
+ }
+
+ even = !even;
+ }
}
- model->set_edited(true);
-
return 0;
}
diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc
index 989cecdd6b..e922a2f33f 100644
--- a/libs/ardour/route.cc
+++ b/libs/ardour/route.cc
@@ -479,13 +479,16 @@ Route::passthru (sframes_t start_frame, sframes_t end_frame, nframes_t nframes,
}
}
+ write_out_of_band_data (bufs, start_frame, end_frame, nframes);
process_output_buffers (bufs, start_frame, end_frame, nframes, true, declick);
}
void
Route::passthru_silence (sframes_t start_frame, sframes_t end_frame, nframes_t nframes, int declick)
{
- process_output_buffers (_session.get_silent_buffers (n_process_buffers()), start_frame, end_frame, nframes, true, declick);
+ BufferSet& bufs (_session.get_silent_buffers (n_process_buffers()));
+ write_out_of_band_data (bufs, start_frame, end_frame, nframes);
+ process_output_buffers (bufs, start_frame, end_frame, nframes, true, declick);
}
void
diff --git a/libs/ardour/tempo.cc b/libs/ardour/tempo.cc
index 3056016752..a2307901bc 100644
--- a/libs/ardour/tempo.cc
+++ b/libs/ardour/tempo.cc
@@ -1099,30 +1099,91 @@ TempoMap::round_to_beat (nframes_t fr, int dir)
}
nframes_t
-
-TempoMap::round_to_beat_subdivision (nframes_t fr, int sub_num)
+TempoMap::round_to_beat_subdivision (nframes_t fr, int sub_num, int dir)
{
BBT_Time the_beat;
uint32_t ticks_one_half_subdivisions_worth;
uint32_t ticks_one_subdivisions_worth;
+ uint32_t difference;
bbt_time(fr, the_beat);
ticks_one_subdivisions_worth = (uint32_t)Meter::ticks_per_beat / sub_num;
ticks_one_half_subdivisions_worth = ticks_one_subdivisions_worth / 2;
+
+ if (dir > 0) {
+
+ /* round to next */
- if (the_beat.ticks % ticks_one_subdivisions_worth > ticks_one_half_subdivisions_worth) {
- uint32_t difference = ticks_one_subdivisions_worth - (the_beat.ticks % ticks_one_subdivisions_worth);
- if (the_beat.ticks + difference >= (uint32_t)Meter::ticks_per_beat) {
- the_beat.beats++;
- the_beat.ticks += difference;
- the_beat.ticks -= (uint32_t)Meter::ticks_per_beat;
- } else {
- the_beat.ticks += difference;
- }
- } else {
- the_beat.ticks -= the_beat.ticks % ticks_one_subdivisions_worth;
+ uint32_t mod = the_beat.ticks % ticks_one_subdivisions_worth;
+
+ if (mod == 0) {
+ /* right on the subdivision, so the difference is just the subdivision ticks */
+ difference = ticks_one_subdivisions_worth;
+
+ } else {
+ /* not on subdivision, compute distance to next subdivision */
+
+ difference = ticks_one_subdivisions_worth - mod;
+ }
+
+ if (the_beat.ticks + difference >= (uint32_t)Meter::ticks_per_beat) {
+ the_beat.beats++;
+ the_beat.ticks += difference;
+ the_beat.ticks -= (uint32_t)Meter::ticks_per_beat;
+ } else {
+ the_beat.ticks += difference;
+ }
+
+ } else if (dir < 0) {
+
+ /* round to previous */
+
+ uint32_t mod = the_beat.ticks % ticks_one_subdivisions_worth;
+
+ if (mod == 0) {
+ /* right on the subdivision, so the difference is just the subdivision ticks */
+ difference = ticks_one_subdivisions_worth;
+ cerr << "On the sub, move by 1 sub = " << difference << endl;
+ } else {
+ /* not on subdivision, compute distance to previous subdivision, which
+ is just the modulus.
+ */
+
+ difference = mod;
+ cerr << "off the sub, move by 1 sub = " << difference << endl;
+ }
+
+
+ cerr << "ticks = " << the_beat.ticks << endl;
+
+ if (the_beat.ticks < difference) {
+ cerr << "backup beats, set ticks to "
+ << (uint32_t)Meter::ticks_per_beat - difference << endl;
+ the_beat.beats--;
+ the_beat.ticks = (uint32_t)Meter::ticks_per_beat - difference;
+ } else {
+ cerr << " reduce ticks\n";
+ the_beat.ticks -= difference;
+ }
+
+ } else {
+ /* round to nearest */
+
+ if (the_beat.ticks % ticks_one_subdivisions_worth > ticks_one_half_subdivisions_worth) {
+ difference = ticks_one_subdivisions_worth - (the_beat.ticks % ticks_one_subdivisions_worth);
+ if (the_beat.ticks + difference >= (uint32_t)Meter::ticks_per_beat) {
+ the_beat.beats++;
+ the_beat.ticks += difference;
+ the_beat.ticks -= (uint32_t)Meter::ticks_per_beat;
+ } else {
+ the_beat.ticks += difference;
+ }
+ } else {
+ // difference = ticks_one_subdivisions_worth - (the_beat.ticks % ticks_one_subdivisions_worth);
+ the_beat.ticks -= the_beat.ticks % ticks_one_subdivisions_worth;
+ }
}
return frame_time (the_beat);
@@ -1139,7 +1200,9 @@ TempoMap::round_to_type (nframes_t frame, int dir, BBTPointType type)
switch (type) {
case Bar:
if (dir < 0) {
- /* relax */
+ if (bbt.bars > 1) {
+ bbt.bars--;
+ }
} else if (dir > 0) {
if (bbt.beats > 0) {
bbt.bars++;
@@ -1157,7 +1220,9 @@ TempoMap::round_to_type (nframes_t frame, int dir, BBTPointType type)
case Beat:
if (dir < 0) {
- /* relax */
+ if (bbt.beats > 1) {
+ bbt.beats--;
+ }
} else if (dir > 0) {
if (bbt.ticks > 0) {
bbt.beats++;
@@ -1178,11 +1243,12 @@ TempoMap::round_to_type (nframes_t frame, int dir, BBTPointType type)
}
- /*
+ /*
cerr << "for " << frame << " round to " << bbt << " using "
<< metric.start()
<< endl;
*/
+
return metric.frame() + count_frames_between (metric.start(), bbt);
}
diff --git a/libs/ardour/track.cc b/libs/ardour/track.cc
index 64ec77b683..23da42f86e 100644
--- a/libs/ardour/track.cc
+++ b/libs/ardour/track.cc
@@ -24,6 +24,7 @@
#include "ardour/audioplaylist.h"
#include "ardour/audioregion.h"
#include "ardour/audiosource.h"
+#include "ardour/delivery.h"
#include "ardour/diskstream.h"
#include "ardour/io_processor.h"
#include "ardour/meter.h"
@@ -316,6 +317,8 @@ Track::no_roll (nframes_t nframes, sframes_t start_frame, sframes_t end_frame,
passthru (start_frame, end_frame, nframes, false);
}
+ _main_outs->flush (nframes);
+
return 0;
}