mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-17 04:06:26 +01:00
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.
This commit is contained in:
parent
97c637e399
commit
eb0dded095
4 changed files with 82 additions and 37 deletions
|
|
@ -126,6 +126,8 @@ public:
|
||||||
|
|
||||||
MonitorState monitoring_state () const;
|
MonitorState monitoring_state () const;
|
||||||
|
|
||||||
|
MidiBuffer const& immediate_event_buffer () const { return _immediate_event_buffer; }
|
||||||
|
|
||||||
void set_input_active (bool);
|
void set_input_active (bool);
|
||||||
bool input_active () const;
|
bool input_active () const;
|
||||||
PBD::Signal0<void> InputActiveChanged;
|
PBD::Signal0<void> InputActiveChanged;
|
||||||
|
|
@ -136,8 +138,13 @@ protected:
|
||||||
void act_on_mute ();
|
void act_on_mute ();
|
||||||
void monitoring_changed (bool, PBD::Controllable::GroupControlDisposition);
|
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:
|
private:
|
||||||
MidiRingBuffer<samplepos_t> _immediate_events;
|
MidiRingBuffer<samplepos_t> _immediate_events;
|
||||||
|
MidiBuffer _immediate_event_buffer;
|
||||||
MidiRingBuffer<samplepos_t> _step_edit_ring_buffer;
|
MidiRingBuffer<samplepos_t> _step_edit_ring_buffer;
|
||||||
NoteMode _note_mode;
|
NoteMode _note_mode;
|
||||||
bool _step_editing;
|
bool _step_editing;
|
||||||
|
|
@ -145,8 +152,6 @@ private:
|
||||||
MidiChannelFilter _playback_filter;
|
MidiChannelFilter _playback_filter;
|
||||||
MidiChannelFilter _capture_filter;
|
MidiChannelFilter _capture_filter;
|
||||||
|
|
||||||
void write_out_of_band_data (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_sample, samplecnt_t nframes);
|
|
||||||
|
|
||||||
void set_state_part_two ();
|
void set_state_part_two ();
|
||||||
void set_state_part_three ();
|
void set_state_part_three ();
|
||||||
|
|
||||||
|
|
@ -157,7 +162,7 @@ private:
|
||||||
void map_input_active (bool);
|
void map_input_active (bool);
|
||||||
|
|
||||||
/** Update automation controls to reflect any changes in buffers. */
|
/** Update automation controls to reflect any changes in buffers. */
|
||||||
void update_controls (const BufferSet& bufs);
|
void update_controls (BufferSet const& bufs);
|
||||||
void restore_controls ();
|
void restore_controls ();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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 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,
|
void process_output_buffers (BufferSet& bufs,
|
||||||
samplepos_t start_sample, samplepos_t end_sample,
|
samplepos_t start_sample, samplepos_t end_sample,
|
||||||
|
|
|
||||||
|
|
@ -73,6 +73,7 @@ using namespace PBD;
|
||||||
MidiTrack::MidiTrack (Session& sess, string name, TrackMode mode)
|
MidiTrack::MidiTrack (Session& sess, string name, TrackMode mode)
|
||||||
: Track (sess, name, PresentationInfo::MidiTrack, mode, DataType::MIDI)
|
: Track (sess, name, PresentationInfo::MidiTrack, mode, DataType::MIDI)
|
||||||
, _immediate_events(6096) // FIXME: size?
|
, _immediate_events(6096) // FIXME: size?
|
||||||
|
, _immediate_event_buffer(6096)
|
||||||
, _step_edit_ring_buffer(64) // FIXME: size?
|
, _step_edit_ring_buffer(64) // FIXME: size?
|
||||||
, _note_mode (Sustained)
|
, _note_mode (Sustained)
|
||||||
, _step_editing (false)
|
, _step_editing (false)
|
||||||
|
|
@ -303,7 +304,7 @@ MidiTrack::restore_controls ()
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
MidiTrack::update_controls(const BufferSet& bufs)
|
MidiTrack::update_controls (BufferSet const& bufs)
|
||||||
{
|
{
|
||||||
const MidiBuffer& buf = bufs.get_midi(0);
|
const MidiBuffer& buf = bufs.get_midi(0);
|
||||||
for (MidiBuffer::const_iterator e = buf.begin(); e != buf.end(); ++e) {
|
for (MidiBuffer::const_iterator e = buf.begin(); e != buf.end(); ++e) {
|
||||||
|
|
@ -311,10 +312,13 @@ MidiTrack::update_controls(const BufferSet& bufs)
|
||||||
const Evoral::Parameter param = midi_parameter(ev.buffer(), ev.size());
|
const Evoral::Parameter param = midi_parameter(ev.buffer(), ev.size());
|
||||||
const boost::shared_ptr<AutomationControl> control = automation_control (param);
|
const boost::shared_ptr<AutomationControl> control = automation_control (param);
|
||||||
if (control) {
|
if (control) {
|
||||||
control->set_double(ev.value(), _session.transport_sample(), false);
|
double old = control->get_double (false, 0);
|
||||||
|
control->set_double (ev.value(), 0, false);
|
||||||
|
if (old != ev.value()) {
|
||||||
control->Changed (false, Controllable::NoGroup);
|
control->Changed (false, Controllable::NoGroup);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
|
@ -416,15 +420,14 @@ MidiTrack::push_midi_input_to_step_edit_ringbuffer (samplecnt_t nframes)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
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));
|
_immediate_event_buffer.clear ();
|
||||||
|
if (0 == _immediate_events.read_space()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
update_controls (bufs);
|
assert (nframes > 0);
|
||||||
|
|
||||||
// Append immediate events
|
|
||||||
|
|
||||||
if (_immediate_events.read_space()) {
|
|
||||||
|
|
||||||
DEBUG_TRACE (DEBUG::MidiIO, string_compose ("%1 has %2 of immediate events to deliver\n",
|
DEBUG_TRACE (DEBUG::MidiIO, string_compose ("%1 has %2 of immediate events to deliver\n",
|
||||||
name(), _immediate_events.read_space()));
|
name(), _immediate_events.read_space()));
|
||||||
|
|
@ -438,8 +441,14 @@ MidiTrack::write_out_of_band_data (BufferSet& bufs, samplepos_t /*start*/, sampl
|
||||||
* violate monotonicity when writing. Port::port_offset() will
|
* violate monotonicity when writing. Port::port_offset() will
|
||||||
* be non-zero if we're in a split process cycle.
|
* be non-zero if we're in a split process cycle.
|
||||||
*/
|
*/
|
||||||
_immediate_events.read (buf, 0, 1, Port::port_offset() + nframes - 1, true);
|
_immediate_events.read (_immediate_event_buffer, 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
|
int
|
||||||
|
|
|
||||||
|
|
@ -402,7 +402,8 @@ Route::process_output_buffers (BufferSet& bufs,
|
||||||
* Also during remaining_latency_preroll, transport_rolling () is false, but
|
* Also during remaining_latency_preroll, transport_rolling () is false, but
|
||||||
* we may need to monitor disk instead.
|
* 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);
|
_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);
|
/* 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;
|
double pspeed = speed;
|
||||||
if ((!run_disk_reader && (*i) == _disk_reader) || (!run_disk_writer && (*i) == _disk_writer)) {
|
if ((!run_disk_reader && (*i) == _disk_reader) || (!run_disk_writer && (*i) == _disk_writer)) {
|
||||||
/* run with speed 0, no-roll */
|
/* 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());
|
(*i)->run (bufs, start_sample - latency, end_sample - latency, pspeed, nframes, *i != _processors.back());
|
||||||
|
|
||||||
bufs.set_count ((*i)->output_streams());
|
bufs.set_count ((*i)->output_streams());
|
||||||
|
|
||||||
/* Note: plugin latency may change. While the plugin does inform the session via
|
/* 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 ()) {
|
if ((*i)->active ()) {
|
||||||
latency += (*i)->signal_latency ();
|
latency += (*i)->signal_latency ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (re_inject_oob_data) {
|
||||||
|
write_out_of_band_data (bufs, nframes);
|
||||||
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
if ((*i) == _delayline) {
|
if ((*i) == _delayline) {
|
||||||
latency += _delayline->get_delay ();
|
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);
|
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) */
|
/* 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 */
|
/* run processor chain */
|
||||||
|
|
||||||
process_output_buffers (bufs, start_sample, end_sample, nframes, declick, gain_automation_ok, run_disk_reader);
|
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);
|
flush_processor_buffers_locked (nframes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue