diff --git a/doc/monitor_modes.pdf b/doc/monitor_modes.pdf new file mode 100644 index 0000000000..d4c4232580 Binary files /dev/null and b/doc/monitor_modes.pdf differ diff --git a/libs/ardour/ardour/midi_track.h b/libs/ardour/ardour/midi_track.h index 4270a3be97..86eb8fd680 100644 --- a/libs/ardour/ardour/midi_track.h +++ b/libs/ardour/ardour/midi_track.h @@ -114,9 +114,6 @@ public: protected: XMLNode& state (bool full); - bool ardour_should_monitor () const; - bool send_silence () const; - void act_on_mute (); private: diff --git a/libs/ardour/ardour/route.h b/libs/ardour/ardour/route.h index af659fd4cd..3fab63bb9b 100644 --- a/libs/ardour/ardour/route.h +++ b/libs/ardour/ardour/route.h @@ -107,6 +107,9 @@ class Route : public SessionObject, public Automatable, public RouteGroupMember, bool is_master() const { return _flags & MasterOut; } bool is_monitor() const { return _flags & MonitorOut; } + virtual MonitorState monitoring_state () const; + virtual MeterState metering_state () const; + /* these are the core of the API of a Route. see the protected sections as well */ virtual int roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame, @@ -494,7 +497,6 @@ class Route : public SessionObject, public Automatable, public RouteGroupMember, uint32_t pans_required() const; ChanCount n_process_buffers (); - virtual bool ardour_should_monitor () const; virtual void maybe_declick (BufferSet&, framecnt_t, int); boost::shared_ptr _amp; diff --git a/libs/ardour/ardour/track.h b/libs/ardour/ardour/track.h index 8f68f63d05..08bf170985 100644 --- a/libs/ardour/ardour/track.h +++ b/libs/ardour/ardour/track.h @@ -50,9 +50,11 @@ class Track : public Route, public PublicDiskstream virtual void set_monitoring (MonitorChoice); MonitorChoice monitoring_choice() const { return _monitoring; } - MonitorState monitoring_state(); + MonitorState monitoring_state () const; PBD::Signal0 MonitoringChanged; + MeterState metering_state () const; + virtual int no_roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame, bool state_changing); @@ -213,8 +215,6 @@ class Track : public Route, public PublicDiskstream void maybe_declick (BufferSet&, framecnt_t, int); - virtual bool send_silence () const; - boost::shared_ptr _rec_enable_control; framecnt_t check_initial_delay (framecnt_t nframes, framecnt_t&); diff --git a/libs/ardour/ardour/types.h b/libs/ardour/ardour/types.h index ef2e51e70f..7d5c5626e3 100644 --- a/libs/ardour/ardour/types.h +++ b/libs/ardour/ardour/types.h @@ -371,6 +371,11 @@ namespace ARDOUR { MonitoringDisk = 0x4, }; + enum MeterState { + MeteringInput, ///< meter the input IO, regardless of what is going through the route + MeteringRoute ///< meter what is going through the route + }; + enum PFLPosition { /** PFL signals come from before pre-fader processors */ PFLFromBeforeProcessors, diff --git a/libs/ardour/midi_track.cc b/libs/ardour/midi_track.cc index 6048cb7e16..f5743f4992 100644 --- a/libs/ardour/midi_track.cc +++ b/libs/ardour/midi_track.cc @@ -652,18 +652,6 @@ MidiTrack::diskstream_data_recorded (boost::weak_ptr src) DataRecorded (src); /* EMIT SIGNAL */ } -bool -MidiTrack::ardour_should_monitor () const -{ - return true; -} - -bool -MidiTrack::send_silence () const -{ - return false; -} - bool MidiTrack::input_active () const { diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc index 10806767d3..18ee909689 100644 --- a/libs/ardour/route.cc +++ b/libs/ardour/route.cc @@ -400,8 +400,6 @@ Route::process_output_buffers (BufferSet& bufs, framepos_t start_frame, framepos_t end_frame, pframes_t nframes, int declick, bool gain_automation_ok) { - bool monitor = ardour_should_monitor (); - bufs.set_is_silent (false); /* figure out if we're going to use gain automation */ @@ -411,8 +409,11 @@ Route::process_output_buffers (BufferSet& bufs, _amp->apply_gain_automation (false); } - /* tell main outs what to do about monitoring */ - _main_outs->no_outs_cuz_we_no_monitor (!monitor); + /* Tell main outs what to do about monitoring. We do this so that + on a transition between monitoring states we get a de-clicking gain + change in the _main_outs delivery. + */ + _main_outs->no_outs_cuz_we_no_monitor (monitoring_state () == MonitoringSilence); /* ------------------------------------------------------------------------------------------- @@ -478,12 +479,20 @@ Route::process_output_buffers (BufferSet& bufs, and go .... ----------------------------------------------------------------------------------------- */ + /* set this to be true if the meter will already have been ::run() earlier */ + bool const meter_already_run = metering_state() == MeteringInput; + for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) { if (boost::dynamic_pointer_cast (*i)) { break; } + if (boost::dynamic_pointer_cast (*i) && meter_already_run) { + /* don't ::run() the meter, otherwise it will have its previous peak corrupted */ + continue; + } + #ifndef NDEBUG /* if it has any inputs, make sure they match */ if ((*i)->input_streams() != ChanCount::ZERO) { @@ -3846,22 +3855,6 @@ Route::setup_invisible_processors () } } -/** @return true if Ardour should provide monitoring for this route */ -bool -Route::ardour_should_monitor () const -{ - switch (Config->get_monitoring_model()) { - case HardwareMonitoring: - case ExternalMonitoring: - return !record_enabled() || (_session.config.get_auto_input() && !_session.actively_recording()); - break; - default: - break; - } - - return true; -} - void Route::unpan () { @@ -3919,3 +3912,21 @@ Route::processor_by_id (PBD::ID id) const return boost::shared_ptr (); } + +/** @return the monitoring state, or in other words what data we are pushing + * into the route (data from the inputs, data from disk or silence) + */ +MonitorState +Route::monitoring_state () const +{ + return MonitoringInput; +} + +/** @return what we should be metering; either the data coming from the input + * IO or the data that is flowing through the route. + */ +MeterState +Route::metering_state () const +{ + return MeteringRoute; +} diff --git a/libs/ardour/track.cc b/libs/ardour/track.cc index fa19c3ddcc..7d1f7930a6 100644 --- a/libs/ardour/track.cc +++ b/libs/ardour/track.cc @@ -375,25 +375,25 @@ Track::no_roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame, */ be_silent = true; } else { - be_silent = send_silence (); + MonitorState const s = monitoring_state (); + /* we are not rolling, so be silent even if we are monitoring disk, as there + will be no disk data coming in. + */ + be_silent = (s == MonitoringSilence || s == MonitoringDisk); + } + + if (!_have_internal_generator && metering_state() == MeteringInput) { + _input->process_input (_meter, start_frame, end_frame, nframes); } _amp->apply_gain_automation(false); + /* if have_internal_generator, or .. */ + //_input->process_input (_meter, start_frame, end_frame, nframes); + if (be_silent) { - /* if we're sending silence, but we want the meters to show levels for the signal, - meter right here. - */ - - if (_have_internal_generator) { - passthru_silence (start_frame, end_frame, nframes, 0); - } else { - if (_meter_point == MeterInput) { - _input->process_input (_meter, start_frame, end_frame, nframes); - } - passthru_silence (start_frame, end_frame, nframes, 0); - } + passthru_silence (start_frame, end_frame, nframes, 0); } else { @@ -774,101 +774,57 @@ Track::adjust_capture_buffering () } } -bool -Track::send_silence () const -{ - bool send_silence; - - if (Config->get_tape_machine_mode()) { - - /* ADATs work in a strange way.. - they monitor input always when stopped.and auto-input is engaged. - */ - - if ((Config->get_monitoring_model() == SoftwareMonitoring) - && ((_monitoring & MonitorInput) || (_diskstream->record_enabled()))) { - send_silence = false; - } else { - send_silence = true; - } - - - } else { - - /* Other machines switch to input on stop if the track is record enabled, - regardless of the auto input setting (auto input only changes the - monitoring state when the transport is rolling) - */ - - if ((Config->get_monitoring_model() == SoftwareMonitoring) - && ((_monitoring & MonitorInput) || - (!(_monitoring & MonitorDisk) && (_session.config.get_auto_input () || _diskstream->record_enabled())))){ - - DEBUG_TRACE (DEBUG::Monitor, - string_compose ("%1: no roll, use silence = FALSE, monitoring choice %2 recenable %3 sRA %4 autoinput %5\n", - name(), enum_2_string (_monitoring), - _diskstream->record_enabled(), _session.actively_recording(), - _session.config.get_auto_input())); - - send_silence = false; - } else { - DEBUG_TRACE (DEBUG::Monitor, - string_compose ("%1: no roll, use silence = TRUE, monitoring choice %2 recenable %3 sRA %4 autoinput %5\n", - name(), enum_2_string (_monitoring), - _diskstream->record_enabled(), _session.actively_recording(), - _session.config.get_auto_input())); - send_silence = true; - } - } - - return send_silence; -} - MonitorState -Track::monitoring_state () +Track::monitoring_state () const { - MonitorState ms = MonitoringSilence; - - if (_session.transport_rolling()) { + /* Explicit requests */ + + if (_monitoring & MonitorInput) { + return MonitoringInput; + } - /* roll case */ - - if (_monitoring & MonitorInput) { // explicitly requested input monitoring - - ms = MonitoringInput; + if (_monitoring & MonitorDisk) { + return MonitoringDisk; + } - } else if (_monitoring & MonitorDisk) { // explicitly requested disk monitoring - - ms = MonitoringDisk; + /* This is an implementation of the truth table in doc/monitor_modes.pdf; + I don't think it's ever going to be too pretty too look at. + */ - } else if (_diskstream->record_enabled() && _session.actively_recording()) { // Track actually recording - - ms = MonitoringInput; + bool const roll = _session.transport_rolling (); + bool const track_rec = _diskstream->record_enabled (); + bool const session_rec = _session.get_record_enabled (); + bool const auto_input = _session.config.get_auto_input (); + bool const software_monitor = Config->get_monitoring_model() == SoftwareMonitoring; + bool const tape_machine_mode = Config->get_tape_machine_mode (); - } else if (_diskstream->record_enabled() && !_session.actively_recording() && _session.config.get_auto_input()) { // Track armed but not recording, with auto input enabled - - ms = MonitoringInput; - - } else { // Every other state - - ms = MonitoringDisk; + if (track_rec) { + if (!session_rec && roll && auto_input) { + return MonitoringDisk; + } else { + return software_monitor ? MonitoringInput : MonitoringSilence; } } else { - /* no-roll case */ + if (tape_machine_mode) { + + return MonitoringDisk; - if (send_silence()) { - - ms = MonitoringSilence; } else { + + if (!roll && auto_input) { + return software_monitor ? MonitoringInput : MonitoringSilence; + } else { + return MonitoringDisk; + } - ms = MonitoringInput; } } - return ms; + /* NOTREACHED */ + return MonitoringSilence; } void @@ -954,4 +910,8 @@ Track::parameter_changed (string p) } } - +MeterState +Track::metering_state () const +{ + return _diskstream->record_enabled() ? MeteringInput : MeteringRoute; +}