* refactor Session::follow_slave to be easier to read and understand
authorHans Baier <hansfbaier@googlemail.com>
Thu, 1 Jan 2009 21:26:23 +0000 (21:26 +0000)
committerHans Baier <hansfbaier@googlemail.com>
Thu, 1 Jan 2009 21:26:23 +0000 (21:26 +0000)
git-svn-id: svn://localhost/ardour2/branches/3.0@4370 d708f5d6-7413-0410-9779-e7cbd77b26cf

libs/ardour/ardour/session.h
libs/ardour/ardour/slave.h
libs/ardour/session_process.cc

index 16db305f943c62d4ba9bd3de6f79a1606a9749db..180bb3dc8d67f90eef3d9f3f960735aca8e11951 100644 (file)
@@ -1079,6 +1079,13 @@ class Session : public PBD::StatefulDestructible
 
        void reset_slave_state ();
        bool follow_slave (nframes_t, nframes_t);
+       void calculate_moving_average_of_slave_delta(int dir, nframes_t this_delta);
+       void track_slave_state(
+                       float slave_speed, 
+                       nframes_t slave_transport_frame, 
+                       nframes_t this_delta,
+                       bool starting);
+       
        void set_slave_source (SlaveSource);
 
        SlaveSource post_export_slave;
index 1f21e28f406e60f1469383c94914ef7dda2c391f..2c9ef70cac4b8e3fe571c8546808302525feda2d 100644 (file)
@@ -103,6 +103,7 @@ class Slave {
         * 
         * @param speed - The transport speed requested
         * @param position - The transport position requested
+        * @return - The return value is currently ignored (see Session::follow_slave)
         */
        virtual bool speed_and_position (float& speed, nframes_t& position) = 0;
        
index 1ceb2b70faa09cc5ede76b18f6c5fa0633b5de12..b0c838bf8a1dd4befa43ee9c28f784a1f7c1603f 100644 (file)
@@ -495,16 +495,6 @@ Session::follow_slave (nframes_t nframes, nframes_t offset)
                slave_speed = 0.0f;
        }
 
-#ifdef DEBUG_SLAVES
-       if (slave_speed != 0.0)
-       cerr << "delta = " << (int) (dir * this_delta)
-            << " speed = " << slave_speed 
-            << " ts = " << _transport_speed 
-            << " M@ "<< slave_transport_frame << " S@ " << _transport_frame 
-            << " avgdelta = " << average_slave_delta 
-            << endl;
-#endif 
-
        if (_slave->is_always_synced() || Config->get_timecode_source_is_synced()) {
 
                /* if the TC source is synced, then we assume that its 
@@ -522,30 +512,157 @@ Session::follow_slave (nframes_t nframes, nframes_t offset)
                   our speed to remain locked.
                */
 
-               if (delta_accumulator_cnt >= delta_accumulator_size) {
-                       have_first_delta_accumulator = true;
-                       delta_accumulator_cnt = 0;
+               calculate_moving_average_of_slave_delta(dir, this_delta);
+       }
+       
+       track_slave_state(slave_speed, slave_transport_frame, this_delta, starting);
+
+       if (slave_state == Running && !_slave->is_always_synced() && !Config->get_timecode_source_is_synced()) {
+
+               if (_transport_speed != 0.0f) {
+                       
+                       /* 
+                          note that average_dir is +1 or -1 
+                       */
+                       
+                       float delta;
+
+                       #ifdef USE_MOVING_AVERAGE_OF_SLAVE
+                               if (average_slave_delta == 0) {
+                                       delta = this_delta;
+                                       delta *= dir;
+                               } else {
+                                       delta = average_slave_delta;
+                                       delta *= average_dir;
+                               }
+                       #else
+                               delta = this_delta;
+                               delta *= dir;
+                       #endif
+
+                       float adjusted_speed = slave_speed +
+                               (delta /  float(_current_frame_rate));
+                       
+                       #ifdef DEBUG_SLAVES
+                       cerr << "adjust using " << delta
+                            << " towards " << adjusted_speed
+                            << " ratio = " << adjusted_speed / slave_speed
+                            << " current = " << _transport_speed
+                            << " slave @ " << slave_speed
+                            << endl;
+                       #endif
+                       
+                       request_transport_speed (adjusted_speed);
+                       
+                       if (abs(average_slave_delta) > (long) _slave->resolution()) {
+                               cerr << "average slave delta greater than slave resolution, going to silent motion\n";
+                               goto silent_motion;
+                       }
                }
+       } 
+       
+       #ifdef DEBUG_SLAVES
+       if (slave_speed != 0.0)
+       cerr << "delta = " << (int) (dir * this_delta)
+                << " speed = " << slave_speed 
+                << " ts = " << _transport_speed 
+                << " M@ "<< slave_transport_frame << " S@ " << _transport_frame 
+                << " avgdelta = " << average_slave_delta 
+                << endl;
+       #endif  
+
+       if (!starting && !non_realtime_work_pending()) {
+               /* speed is set, we're locked, and good to go */
+               return true;
+       }
 
-               if (delta_accumulator_cnt != 0 || this_delta < _current_frame_rate) {
-                       delta_accumulator[delta_accumulator_cnt++] = long(dir) * long(this_delta);
+  silent_motion:
+#ifdef DEBUG_SLAVES    
+       cerr << "reached silent_motion:" <<endl;
+#endif
+       
+       if (slave_speed && _transport_speed) {
+
+               /* something isn't right, but we should move with the master
+                  for now.
+               */
+
+               bool need_butler;
+               
+               prepare_diskstreams ();
+               silent_process_routes (nframes, offset);
+               commit_diskstreams (nframes, need_butler);
+
+               if (need_butler) {
+                       summon_butler ();
                }
                
-               if (have_first_delta_accumulator) {
-                       average_slave_delta = 0L;
-                       for (int i = 0; i < delta_accumulator_size; ++i) {
-                               average_slave_delta += delta_accumulator[i];
-                       }
-                       average_slave_delta /= long(delta_accumulator_size);
-                       if (average_slave_delta < 0L) {
-                               average_dir = -1;
-                               average_slave_delta = abs(average_slave_delta);
+               int32_t frames_moved = (int32_t) floor (_transport_speed * nframes);
+               
+               if (frames_moved < 0) {
+                       decrement_transport_position (-frames_moved);
+               } else {
+                       increment_transport_position (frames_moved);
+               }
+               
+               nframes_t stop_limit;
+               
+               if (actively_recording()) {
+                       stop_limit = max_frames;
+               } else {
+                       if (Config->get_stop_at_session_end()) {
+                               stop_limit = current_end_frame();
                        } else {
-                               average_dir = 1;
+                               stop_limit = max_frames;
                        }
                }
+
+               maybe_stop (stop_limit);
+       }
+
+  noroll:
+       /* don't move at all */
+#ifdef DEBUG_SLAVES    
+       cerr << "reached no_roll:" <<endl;
+#endif
+       no_roll (nframes, 0);
+       return false;
+}
+
+void
+Session::calculate_moving_average_of_slave_delta(int dir, nframes_t this_delta)
+{
+       if (delta_accumulator_cnt >= delta_accumulator_size) {
+               have_first_delta_accumulator = true;
+               delta_accumulator_cnt = 0;
+       }
+
+       if (delta_accumulator_cnt != 0 || this_delta < _current_frame_rate) {
+               delta_accumulator[delta_accumulator_cnt++] = long(dir) * long(this_delta);
+       }
+       
+       if (have_first_delta_accumulator) {
+               average_slave_delta = 0L;
+               for (int i = 0; i < delta_accumulator_size; ++i) {
+                       average_slave_delta += delta_accumulator[i];
+               }
+               average_slave_delta /= long(delta_accumulator_size);
+               if (average_slave_delta < 0L) {
+                       average_dir = -1;
+                       average_slave_delta = abs(average_slave_delta);
+               } else {
+                       average_dir = 1;
+               }
        }
+}
 
+void
+Session::track_slave_state(
+               float slave_speed, 
+               nframes_t slave_transport_frame, 
+               nframes_t this_delta,
+               bool starting)
+{
        if (slave_speed != 0.0f) {
 
                /* slave is running */
@@ -631,7 +748,7 @@ Session::follow_slave (nframes_t nframes, nframes_t offset)
                        start_transport ();
                } 
 
-       } else {
+       } else { // slave_speed is 0
 
                /* slave has stopped */
 
@@ -658,104 +775,6 @@ Session::follow_slave (nframes_t nframes, nframes_t offset)
 
                slave_state = Stopped;
        }
-
-       if (slave_state == Running && !_slave->is_always_synced() && !Config->get_timecode_source_is_synced()) {
-
-
-               if (_transport_speed != 0.0f) {
-                       
-                       /* 
-                          note that average_dir is +1 or -1 
-                       */
-                       
-                       const float adjust_seconds = 1.0f;
-                       float delta;
-
-                       //if (average_slave_delta == 0) {
-                               delta = this_delta;
-                               delta *= dir;
-//                     } else {
-//                             delta = average_slave_delta;
-//                             delta *= average_dir;
-//                     }
-
-                       float adjusted_speed = slave_speed +
-                               (delta / (adjust_seconds * _current_frame_rate));
-                       
-#ifdef DEBUG_DELAY_LOCKED_LOOP
-                       cerr << "adjust using " << delta
-                            << " towards " << adjusted_speed
-                            << " ratio = " << adjusted_speed / slave_speed
-                            << " current = " << _transport_speed
-                            << " slave @ " << slave_speed
-                            << endl;
-#endif
-                       
-                       request_transport_speed (adjusted_speed);
-                       
-                       if (abs(average_slave_delta) > (long) _slave->resolution()) {
-                               cerr << "average slave delta greater than slave resolution, going to silent motion\n";
-                               goto silent_motion;
-                       }
-               }
-       } 
-
-       if (!starting && !non_realtime_work_pending()) {
-               /* speed is set, we're locked, and good to go */
-               return true;
-       }
-
-  silent_motion:
-#ifdef DEBUG_SLAVES    
-       cerr << "reached silent_motion:" <<endl;
-#endif
-       
-       if (slave_speed && _transport_speed) {
-
-               /* something isn't right, but we should move with the master
-                  for now.
-               */
-
-               bool need_butler;
-               
-               prepare_diskstreams ();
-               silent_process_routes (nframes, offset);
-               commit_diskstreams (nframes, need_butler);
-
-               if (need_butler) {
-                       summon_butler ();
-               }
-               
-               int32_t frames_moved = (int32_t) floor (_transport_speed * nframes);
-               
-               if (frames_moved < 0) {
-                       decrement_transport_position (-frames_moved);
-               } else {
-                       increment_transport_position (frames_moved);
-               }
-               
-               nframes_t stop_limit;
-               
-               if (actively_recording()) {
-                       stop_limit = max_frames;
-               } else {
-                       if (Config->get_stop_at_session_end()) {
-                               stop_limit = current_end_frame();
-                       } else {
-                               stop_limit = max_frames;
-                       }
-               }
-
-               maybe_stop (stop_limit);
-       }
-
-  noroll:
-       /* don't move at all */
-#ifdef DEBUG_SLAVES    
-       cerr << "reached no_roll:" <<endl;
-#endif
-       no_roll (nframes, 0);
-       return false;
 }
 
 void