cue monitoring for audio (libardour aspects)
authorPaul Davis <paul@linuxaudiosystems.com>
Sun, 11 Jun 2017 23:53:02 +0000 (19:53 -0400)
committerPaul Davis <paul@linuxaudiosystems.com>
Mon, 18 Sep 2017 15:40:53 +0000 (11:40 -0400)
libs/ardour/ardour/disk_reader.h
libs/ardour/disk_reader.cc
libs/ardour/disk_writer.cc
libs/ardour/monitor_control.cc
libs/ardour/route.cc
libs/ardour/track.cc

index 46d9c43cb6a0a4a3703b4aa02af1fd2bf7134b05..dabdff67a065d57ddb066afdb403f8757a9fb854 100644 (file)
@@ -121,7 +121,6 @@ class LIBARDOUR_API DiskReader : public DiskIOProcessor
        bool          overwrite_queued;
        IOChange      input_change_pending;
        framecnt_t    wrap_buffer_size;
-       MonitorChoice   _monitoring_choice;
 
        int _do_refill_with_alloc (bool partial_fill);
 
index d84dc52a63b344eb73a4c9ee17e16ae531437ce2..43e6bed9df52dd516875ac46fc67f65f55d99598 100644 (file)
@@ -17,6 +17,7 @@
 
 */
 
+#include "pbd/enumwriter.h"
 #include "pbd/i18n.h"
 #include "pbd/memento_command.h"
 
@@ -51,7 +52,6 @@ DiskReader::DiskReader (Session& s, string const & str, DiskIOProcessor::Flag f)
         , overwrite_offset (0)
         , _pending_overwrite (false)
         , overwrite_queued (false)
-       , _monitoring_choice (MonitorDisk)
        , _gui_feed_buffer (AudioEngine::instance()->raw_buffer_size (DataType::MIDI))
 {
 }
@@ -239,11 +239,23 @@ DiskReader::run (BufferSet& bufs, framepos_t start_frame, framepos_t end_frame,
        uint32_t n;
        boost::shared_ptr<ChannelList> c = channels.reader();
        ChannelList::iterator chan;
-       const bool need_disk_signal = result_required || _monitoring_choice == MonitorDisk || _monitoring_choice == MonitorCue;
        frameoffset_t playback_distance = nframes;
+       MonitorState ms = _route->monitoring_state ();
 
-       _need_butler = false;
+       if (_active) {
+               if (!_pending_active) {
+                       _active = false;
+                       return;
+               }
+       } else {
+               if (_pending_active) {
+                       _active = true;
+               } else {
+                       return;
+               }
+       }
 
+       _need_butler = false;
 
        if (speed != 1.0f && speed != -1.0f) {
                interpolation.set_speed (speed);
@@ -255,91 +267,106 @@ DiskReader::run (BufferSet& bufs, framepos_t start_frame, framepos_t end_frame,
                playback_distance = -playback_distance;
        }
 
-       if (!need_disk_signal) {
+       if (!result_required || ((ms & MonitoringDisk) == 0)) {
+
+               /* no need for actual disk data, just advance read pointer and return */
 
                for (ChannelList::iterator chan = c->begin(); chan != c->end(); ++chan) {
                        (*chan)->buf->increment_read_ptr (playback_distance);
                }
 
-               return;
-       }
-
-       /* we're doing playback */
-
-       size_t n_buffers = bufs.count().n_audio();
-       size_t n_chans = c->size();
-       gain_t scaling;
-
-       if (n_chans > n_buffers) {
-               scaling = ((float) n_buffers)/n_chans;
        } else {
-               scaling = 1.0;
-       }
 
-       for (n = 0, chan = c->begin(); chan != c->end(); ++chan, ++n) {
+               /* we need audio data from disk */
 
-               AudioBuffer& buf (bufs.get_audio (n%n_buffers));
-               Sample* outgoing = buf.data ();
+               size_t n_buffers = bufs.count().n_audio();
+               size_t n_chans = c->size();
+               gain_t scaling;
+               BufferSet& scratch_bufs (_session.get_scratch_buffers (bufs.count()));
 
-               ChannelInfo* chaninfo (*chan);
+               if (n_chans > n_buffers) {
+                       scaling = ((float) n_buffers)/n_chans;
+               } else {
+                       scaling = 1.0;
+               }
 
-               chaninfo->buf->get_read_vector (&(*chan)->rw_vector);
+               for (n = 0, chan = c->begin(); chan != c->end(); ++chan, ++n) {
 
-               if (playback_distance <= (framecnt_t) chaninfo->rw_vector.len[0]) {
+                       ChannelInfo* chaninfo (*chan);
+                       AudioBuffer& buf (bufs.get_audio (n%n_buffers));
+                       Sample* outgoing = 0; /* assignment not really needed but it keeps the compiler quiet and helps track bugs */
 
-                       if (fabsf (speed) != 1.0f) {
-                               (void) interpolation.interpolate (
-                                       n, nframes,
-                                       chaninfo->rw_vector.buf[0],
-                                       outgoing);
+                       if (ms & MonitoringInput) {
+                               /* put disk stream in scratch buffer, blend at end */
+                               outgoing = scratch_bufs.get_audio(n).data ();
                        } else {
-                               memcpy (outgoing, chaninfo->rw_vector.buf[0], sizeof (Sample) * playback_distance);
+                               /* no input stream needed, just overwrite buffers */
+                               outgoing = buf.data ();
                        }
 
-               } else {
+                       chaninfo->buf->get_read_vector (&(*chan)->rw_vector);
 
-                       const framecnt_t total = chaninfo->rw_vector.len[0] + chaninfo->rw_vector.len[1];
-
-                       if (playback_distance <= total) {
-
-                               /* We have enough samples, but not in one lump.
-                               */
+                       if (playback_distance <= (framecnt_t) chaninfo->rw_vector.len[0]) {
 
                                if (fabsf (speed) != 1.0f) {
-                                       interpolation.interpolate (n, chaninfo->rw_vector.len[0],
-                                                                  chaninfo->rw_vector.buf[0],
-                                                                  outgoing);
-                                       outgoing += chaninfo->rw_vector.len[0];
-                                       interpolation.interpolate (n, playback_distance - chaninfo->rw_vector.len[0],
-                                                                  chaninfo->rw_vector.buf[1],
-                                                                  outgoing);
+                                       (void) interpolation.interpolate (
+                                               n, nframes,
+                                               chaninfo->rw_vector.buf[0],
+                                               outgoing);
                                } else {
-                                       memcpy (outgoing,
-                                               chaninfo->rw_vector.buf[0],
-                                               chaninfo->rw_vector.len[0] * sizeof (Sample));
-                                       outgoing += chaninfo->rw_vector.len[0];
-                                       memcpy (outgoing,
-                                               chaninfo->rw_vector.buf[1],
-                                               (playback_distance - chaninfo->rw_vector.len[0]) * sizeof (Sample));
+                                       memcpy (outgoing, chaninfo->rw_vector.buf[0], sizeof (Sample) * playback_distance);
                                }
 
                        } else {
 
-                               cerr << _name << " Need " << playback_distance << " total = " << total << endl;
-                               cerr << "underrun for " << _name << endl;
-                               DEBUG_TRACE (DEBUG::Butler, string_compose ("%1 underrun in %2, total space = %3\n",
-                                                                           DEBUG_THREAD_SELF, name(), total));
-                               Underrun ();
-                               return;
+                               const framecnt_t total = chaninfo->rw_vector.len[0] + chaninfo->rw_vector.len[1];
+
+                               if (playback_distance <= total) {
+
+                                       /* We have enough samples, but not in one lump.
+                                        */
+
+                                       if (fabsf (speed) != 1.0f) {
+                                               interpolation.interpolate (n, chaninfo->rw_vector.len[0],
+                                                                          chaninfo->rw_vector.buf[0],
+                                                                          outgoing);
+                                               outgoing += chaninfo->rw_vector.len[0];
+                                               interpolation.interpolate (n, playback_distance - chaninfo->rw_vector.len[0],
+                                                                          chaninfo->rw_vector.buf[1],
+                                                                          outgoing);
+                                       } else {
+                                               memcpy (outgoing,
+                                                       chaninfo->rw_vector.buf[0],
+                                                       chaninfo->rw_vector.len[0] * sizeof (Sample));
+                                               outgoing += chaninfo->rw_vector.len[0];
+                                               memcpy (outgoing,
+                                                       chaninfo->rw_vector.buf[1],
+                                                       (playback_distance - chaninfo->rw_vector.len[0]) * sizeof (Sample));
+                                       }
+
+                               } else {
 
+                                       cerr << _name << " Need " << playback_distance << " total = " << total << endl;
+                                       cerr << "underrun for " << _name << endl;
+                                       DEBUG_TRACE (DEBUG::Butler, string_compose ("%1 underrun in %2, total space = %3\n",
+                                                                                   DEBUG_THREAD_SELF, name(), total));
+                                       Underrun ();
+                                       return;
+
+                               }
                        }
-               }
 
-               if (scaling != 1.0f) {
-                       apply_gain_to_buffer (outgoing, nframes, scaling);
-               }
+                       if (scaling != 1.0f) {
+                               apply_gain_to_buffer (outgoing, nframes, scaling);
+                       }
+
+                       chaninfo->buf->increment_read_ptr (playback_distance);
 
-               chaninfo->buf->increment_read_ptr (playback_distance);
+                       if (ms & MonitoringInput) {
+                               /* mix the disk signal into the input signal (already in bufs) */
+                               mix_buffers_no_gain (buf.data(), outgoing, speed == 0.0 ? nframes : playback_distance);
+                       }
+               }
        }
 
        /* MIDI data handling */
@@ -367,8 +394,6 @@ DiskReader::run (BufferSet& bufs, framepos_t start_frame, framepos_t end_frame,
                playback_sample += playback_distance;
        }
 
-       ChanCount cnt;
-
        if (_playlists[DataType::AUDIO]) {
                if (!c->empty()) {
                        if (_slaved) {
@@ -385,8 +410,6 @@ DiskReader::run (BufferSet& bufs, framepos_t start_frame, framepos_t end_frame,
                                }
                        }
                }
-
-               cnt.set (DataType::AUDIO, bufs.count().n_audio());
        }
 
        if (_playlists[DataType::MIDI]) {
@@ -439,13 +462,9 @@ DiskReader::run (BufferSet& bufs, framepos_t start_frame, framepos_t end_frame,
                        _need_butler = true;
                }
 
-               cnt.set (DataType::MIDI, 1);
-
        }
 
        DEBUG_TRACE (DEBUG::Butler, string_compose ("%1 reader run, needs butler = %2\n", name(), _need_butler));
-
-       bufs.set_count (cnt);
 }
 
 void
index 5ff7b48e9c51fef7bb2d2184722caf822f90d820..4a1c24c1fdbec0b2f215806faa78d9680fb01529 100644 (file)
@@ -434,6 +434,19 @@ DiskWriter::run (BufferSet& bufs, framepos_t start_frame, framepos_t end_frame,
        bool re = record_enabled ();
        bool can_record = _session.actively_recording ();
 
+       if (_active) {
+               if (!_pending_active) {
+                       _active = false;
+                       return;
+               }
+       } else {
+               if (_pending_active) {
+                       _active = true;
+               } else {
+                       return;
+               }
+       }
+
        _need_butler = false;
 
        check_record_status (start_frame, can_record);
index f4e8fbf71b07e632bc18ab3c0d97d992b6e54d0b..633ceea928629669fc3ede861499684eeb69f204 100644 (file)
@@ -40,19 +40,7 @@ MonitorControl::MonitorControl (Session& session, std::string const & name, Moni
 void
 MonitorControl::actually_set_value (double val, Controllable::GroupControlDisposition gcd)
 {
-       int v = (int) val;
-       switch (v) {
-       case MonitorAuto:
-       case MonitorInput:
-       case MonitorDisk:
-       case MonitorCue:
-               break;
-       default:
-               /* illegal value */
-               return;
-       }
-
-       _monitoring = MonitorChoice (v);
+       _monitoring = MonitorChoice ((int) val);
        AutomationControl::actually_set_value (val, gcd);
 }
 
index 4ebc0cf82bd371cb43246974f18542e74eec343b..352d36a2c5b9c34acfffc2282c6caa4a9e43b582 100644 (file)
@@ -4855,7 +4855,6 @@ Route::fill_buffers_with_input (BufferSet& bufs, boost::shared_ptr<IO> io, pfram
                boost::shared_ptr<AudioPort> source_port = io->audio (i);
                AudioBuffer& buf (bufs.get_audio (i%n_buffers));
 
-
                if (i < n_buffers) {
 
                        /* first time through just copy a channel into
index db267296ebbe309de477ba60de7eda9e854614e7..db70d79aaf7fea7390a63556e0984d6e29c1ea05 100644 (file)
@@ -168,7 +168,7 @@ Track::set_state (const XMLNode& node, int version)
                           (child nodes, properties, etc.) and then call
                           ::set_state() on the writer/reader.
 
-                          But at present (June 2017), there's no such state. 
+                          But at present (June 2017), there's no such state.
                        */
                }
        }
@@ -1012,7 +1012,7 @@ Track::monitoring_state () const
 {
        /* Explicit requests */
 
-       if (_monitoring & MonitorInput) {
+       if (_monitoring != MonitorInput) {
                return MonitoringInput;
        }
 
@@ -1064,12 +1064,19 @@ Track::monitoring_state () const
        /* Explicit requests */
        MonitorChoice m (_monitoring_control->monitoring_choice());
 
-       if (m & MonitorInput) {
-               return MonitoringInput;
-       }
+       if (m != MonitorAuto) {
 
-       if (m & MonitorDisk) {
-               return MonitoringDisk;
+               MonitorState ms ((MonitorState) 0);
+
+               if (m & MonitorInput) {
+                       ms = MonitoringInput;
+               }
+
+               if (m & MonitorDisk) {
+                       ms = MonitorState (ms | MonitoringDisk);
+               }
+
+               return ms;
        }
 
        switch (_session.config.get_session_monitoring ()) {