summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobin Gareus <robin@gareus.org>2017-09-30 23:16:04 +0200
committerRobin Gareus <robin@gareus.org>2017-09-30 23:16:04 +0200
commiteb0dded0954782768834e1d3a494f45cc4a118a1 (patch)
tree7f67841c0c04354f4b20f2f9510493000679e18d
parent97c637e39914a8b68f1d0c83d3f8c37d81fc43c2 (diff)
Immediate-event/out-of-band injection update & tweak clearing buffers
Immediate events are used for MIDI-Panic and to inject GUI generated events e.g. patch-changes, note-events from the track-header (scroomer-keyboard) and patch-change audition. Current behavior: - snapshot copy immediate events from ringbuffer into a buffer at the beginning of each the cycle. - Inject immediate events into input-buffer directly after reading the input - process "normally" - pass immediate event-buffer to disk-writer, so it can skip them (don't write immediate events to disk) - if the Route is not monitoring input: clear buffer before disk-reader and re-inject (original) immediate events after the disk-reader - immediate events process normally and are also sent to outputs.
-rw-r--r--libs/ardour/ardour/midi_track.h21
-rw-r--r--libs/ardour/ardour/route.h4
-rw-r--r--libs/ardour/midi_track.cc55
-rw-r--r--libs/ardour/route.cc33
4 files changed, 79 insertions, 34 deletions
diff --git a/libs/ardour/ardour/midi_track.h b/libs/ardour/ardour/midi_track.h
index dfd5a42d13..93856282c4 100644
--- a/libs/ardour/ardour/midi_track.h
+++ b/libs/ardour/ardour/midi_track.h
@@ -126,6 +126,8 @@ public:
MonitorState monitoring_state () const;
+ MidiBuffer const& immediate_event_buffer () const { return _immediate_event_buffer; }
+
void set_input_active (bool);
bool input_active () const;
PBD::Signal0<void> InputActiveChanged;
@@ -136,16 +138,19 @@ protected:
void act_on_mute ();
void monitoring_changed (bool, PBD::Controllable::GroupControlDisposition);
+ void snapshot_out_of_band_data (samplecnt_t nframes);
+ void write_out_of_band_data (BufferSet& bufs, samplecnt_t /* nframes */) const;
+
+
private:
MidiRingBuffer<samplepos_t> _immediate_events;
+ MidiBuffer _immediate_event_buffer;
MidiRingBuffer<samplepos_t> _step_edit_ring_buffer;
- NoteMode _note_mode;
- bool _step_editing;
- bool _input_active;
- MidiChannelFilter _playback_filter;
- MidiChannelFilter _capture_filter;
-
- void write_out_of_band_data (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_sample, samplecnt_t nframes);
+ NoteMode _note_mode;
+ bool _step_editing;
+ bool _input_active;
+ MidiChannelFilter _playback_filter;
+ MidiChannelFilter _capture_filter;
void set_state_part_two ();
void set_state_part_three ();
@@ -157,7 +162,7 @@ private:
void map_input_active (bool);
/** Update automation controls to reflect any changes in buffers. */
- void update_controls (const BufferSet& bufs);
+ void update_controls (BufferSet const& bufs);
void restore_controls ();
};
diff --git a/libs/ardour/ardour/route.h b/libs/ardour/ardour/route.h
index 1437fd79ed..830ef4bab3 100644
--- a/libs/ardour/ardour/route.h
+++ b/libs/ardour/ardour/route.h
@@ -597,7 +597,9 @@ protected:
virtual int no_roll_unlocked (pframes_t nframes, samplepos_t start_sample, samplepos_t end_sample, bool session_state_changing);
- virtual void write_out_of_band_data (BufferSet& /* bufs */, samplepos_t /* start_sample */, samplepos_t /* end_sample */, samplecnt_t /* nframes */) {}
+ virtual void snapshot_out_of_band_data (samplecnt_t /* nframes */) {}
+ virtual void write_out_of_band_data (BufferSet&, samplecnt_t /* nframes */) const {}
+ virtual void update_controls (BufferSet const&) {}
void process_output_buffers (BufferSet& bufs,
samplepos_t start_sample, samplepos_t end_sample,
diff --git a/libs/ardour/midi_track.cc b/libs/ardour/midi_track.cc
index 2e5fd2a0b4..20faa80bc8 100644
--- a/libs/ardour/midi_track.cc
+++ b/libs/ardour/midi_track.cc
@@ -73,6 +73,7 @@ using namespace PBD;
MidiTrack::MidiTrack (Session& sess, string name, TrackMode mode)
: Track (sess, name, PresentationInfo::MidiTrack, mode, DataType::MIDI)
, _immediate_events(6096) // FIXME: size?
+ , _immediate_event_buffer(6096)
, _step_edit_ring_buffer(64) // FIXME: size?
, _note_mode (Sustained)
, _step_editing (false)
@@ -303,16 +304,19 @@ MidiTrack::restore_controls ()
}
void
-MidiTrack::update_controls(const BufferSet& bufs)
+MidiTrack::update_controls (BufferSet const& bufs)
{
const MidiBuffer& buf = bufs.get_midi(0);
for (MidiBuffer::const_iterator e = buf.begin(); e != buf.end(); ++e) {
- const Evoral::Event<samplepos_t>& ev = *e;
+ const Evoral::Event<samplepos_t>& ev = *e;
const Evoral::Parameter param = midi_parameter(ev.buffer(), ev.size());
const boost::shared_ptr<AutomationControl> control = automation_control (param);
if (control) {
- control->set_double(ev.value(), _session.transport_sample(), false);
- control->Changed (false, Controllable::NoGroup);
+ double old = control->get_double (false, 0);
+ control->set_double (ev.value(), 0, false);
+ if (old != ev.value()) {
+ control->Changed (false, Controllable::NoGroup);
+ }
}
}
}
@@ -416,30 +420,35 @@ MidiTrack::push_midi_input_to_step_edit_ringbuffer (samplecnt_t nframes)
}
void
-MidiTrack::write_out_of_band_data (BufferSet& bufs, samplepos_t /*start*/, samplepos_t /*end*/, samplecnt_t nframes)
+MidiTrack::snapshot_out_of_band_data (samplecnt_t nframes)
{
- MidiBuffer& buf (bufs.get_midi (0));
-
- update_controls (bufs);
+ _immediate_event_buffer.clear ();
+ if (0 == _immediate_events.read_space()) {
+ return;
+ }
- // Append immediate events
+ assert (nframes > 0);
- if (_immediate_events.read_space()) {
+ DEBUG_TRACE (DEBUG::MidiIO, string_compose ("%1 has %2 of immediate events to deliver\n",
+ name(), _immediate_events.read_space()));
- DEBUG_TRACE (DEBUG::MidiIO, string_compose ("%1 has %2 of immediate events to deliver\n",
- name(), _immediate_events.read_space()));
+ /* write as many of the immediate events as we can, but give "true" as
+ * the last argument ("stop on overflow in destination") so that we'll
+ * ship the rest out next time.
+ *
+ * the Port::port_offset() + (nframes-1) argument puts all these events at the last
+ * possible position of the output buffer, so that we do not
+ * violate monotonicity when writing. Port::port_offset() will
+ * be non-zero if we're in a split process cycle.
+ */
+ _immediate_events.read (_immediate_event_buffer, 0, 1, Port::port_offset() + nframes - 1, true);
+}
- /* write as many of the immediate events as we can, but give "true" as
- * the last argument ("stop on overflow in destination") so that we'll
- * ship the rest out next time.
- *
- * the Port::port_offset() + (nframes-1) argument puts all these events at the last
- * possible position of the output buffer, so that we do not
- * violate monotonicity when writing. Port::port_offset() will
- * be non-zero if we're in a split process cycle.
- */
- _immediate_events.read (buf, 0, 1, Port::port_offset() + nframes - 1, true);
- }
+void
+MidiTrack::write_out_of_band_data (BufferSet& bufs, samplecnt_t nframes) const
+{
+ MidiBuffer& buf (bufs.get_midi (0));
+ buf.merge_from (_immediate_event_buffer, nframes);
}
int
diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc
index 0f8c892b24..236f2d7c0c 100644
--- a/libs/ardour/route.cc
+++ b/libs/ardour/route.cc
@@ -402,7 +402,8 @@ Route::process_output_buffers (BufferSet& bufs,
* Also during remaining_latency_preroll, transport_rolling () is false, but
* we may need to monitor disk instead.
*/
- bool silence = _have_internal_generator ? false : (monitoring_state () == MonitoringSilence);
+ MonitorState ms = monitoring_state ();
+ bool silence = _have_internal_generator ? false : (ms == MonitoringSilence);
_main_outs->no_outs_cuz_we_no_monitor (silence);
@@ -524,6 +525,24 @@ Route::process_output_buffers (BufferSet& bufs,
/* input->latency() + */ latency, /* output->latency() + */ playback_latency);
}
+ bool re_inject_oob_data = false;
+ if ((*i) == _disk_reader) {
+ /* Well now, we've made it past the disk-writer and to the disk-reader.
+ * Time to decide what to do about monitoring.
+ *
+ * Even when not doing MonitoringDisk, we need to run the processors,
+ * so that it advances its internal buffers (IFF run_disk_reader is true).
+ *
+ */
+ if (ms == MonitoringDisk || ms == MonitoringSilence) {
+ /* this will clear out-of-band data, too (e.g. MIDI-PC, Panic etc.
+ * OOB data is written at the end of the cycle (nframes - 1),
+ * and jack does not re-order events, so we push them back later */
+ re_inject_oob_data = true;
+ bufs.silence (nframes, 0);
+ }
+ }
+
double pspeed = speed;
if ((!run_disk_reader && (*i) == _disk_reader) || (!run_disk_writer && (*i) == _disk_writer)) {
/* run with speed 0, no-roll */
@@ -531,6 +550,7 @@ Route::process_output_buffers (BufferSet& bufs,
}
(*i)->run (bufs, start_sample - latency, end_sample - latency, pspeed, nframes, *i != _processors.back());
+
bufs.set_count ((*i)->output_streams());
/* Note: plugin latency may change. While the plugin does inform the session via
@@ -542,6 +562,11 @@ Route::process_output_buffers (BufferSet& bufs,
if ((*i)->active ()) {
latency += (*i)->signal_latency ();
}
+
+ if (re_inject_oob_data) {
+ write_out_of_band_data (bufs, nframes);
+ }
+
#if 0
if ((*i) == _delayline) {
latency += _delayline->get_delay ();
@@ -701,14 +726,18 @@ Route::run_route (samplepos_t start_sample, samplepos_t end_sample, pframes_t nf
bufs.silence (nframes, 0);
}
+ snapshot_out_of_band_data (nframes);
/* append immediate messages to the first MIDI buffer (thus sending it to the first output port) */
- write_out_of_band_data (bufs, start_sample, end_sample, nframes);
+ write_out_of_band_data (bufs, nframes);
/* run processor chain */
process_output_buffers (bufs, start_sample, end_sample, nframes, declick, gain_automation_ok, run_disk_reader);
+ /* map events (e.g. MIDI-CC) back to control-parameters */
+ update_controls (bufs);
+
flush_processor_buffers_locked (nframes);
}