tempo doc explains that currently Tempo::beats_per_minute means something else.
[ardour.git] / libs / ardour / tempo.cc
index a060b93b347f6cdbc43beb18ba3b2687a999b60f..92419c5712e14d068a09583051047973e8a542ab 100644 (file)
@@ -227,7 +227,7 @@ TempoSection::set_type (Type type)
        _type = type;
 }
 
-/** returns the tempo in beats per minute at the zero-based (relative to session) minute.
+/** returns the tempo on note types per minute at the zero-based (relative to session) minute.
 */
 double
 TempoSection::tempo_at_minute (const double& m) const
@@ -241,7 +241,7 @@ TempoSection::tempo_at_minute (const double& m) const
 }
 
 /** returns the zero-based minute (relative to session)
-   where the tempo in beats per minute occurs in this section.
+   where the tempo in note types per minute occurs in this section.
    pulse p is only used for constant tempi.
    note that the tempo map may have multiple such values.
 */
@@ -254,7 +254,8 @@ TempoSection::minute_at_tempo (const double& bpm, const double& p) const
 
        return _time_at_tempo (bpm) + minute();
 }
-/** returns the tempo in beats per minute at the zero-based (relative to session) pulse.
+
+/** returns the tempo in note types per minute at the supplied pulse.
 */
 double
 TempoSection::tempo_at_pulse (const double& p) const
@@ -267,9 +268,9 @@ TempoSection::tempo_at_pulse (const double& p) const
        return _tempo_at_pulse (p - pulse());
 }
 
-/** returns the zero-based pulse (relative to session)
-   where the tempo in qn beats per minute occurs given frame f. frame f is only used for constant tempi.
-   note that the session tempo map may have multiple beats at a given tempo.
+/** returns the pulse where the tempo in note types per minute occurs given minute m.
+    minute m is only used for constant tempi.
+    note that the session tempo map may have multiple locations where a given tempo occurs.
 */
 double
 TempoSection::pulse_at_tempo (const double& bpm, const double& m) const
@@ -282,16 +283,8 @@ TempoSection::pulse_at_tempo (const double& bpm, const double& m) const
        return _pulse_at_tempo (bpm) + pulse();
 }
 
-/** returns the zero-based pulse (relative to session origin)
-   where the zero-based frame (relative to session)
-   lies.
+/** returns the pulse at the supplied session-relative minute.
 */
-double
-TempoSection::pulse_at_frame (const framepos_t& f) const
-{
-       return pulse_at_minute (minute_at_frame (f));
-}
-
 double
 TempoSection::pulse_at_minute (const double& m) const
 {
@@ -302,17 +295,8 @@ TempoSection::pulse_at_minute (const double& m) const
        return _pulse_at_time (m - minute()) + pulse();
 }
 
-/** returns the zero-based frame (relative to session start frame)
-   where the zero-based pulse (relative to session start)
-   falls.
+/** returns the minute (relative to session start) at the supplied pulse.
 */
-
-framepos_t
-TempoSection::frame_at_pulse (const double& p) const
-{
-       return frame_at_minute (minute_at_pulse (p));
-}
-
 double
 TempoSection::minute_at_pulse (const double& p) const
 {
@@ -399,8 +383,9 @@ https://www.zhdk.ch/fileadmin/data_subsites/data_icst/Downloads/Timegrid/ICST_Te
 */
 
 /*
-  compute this ramp's function constant using the end tempo (in qn beats per minute)
-  and duration (pulses into global start) of some later tempo section.
+  compute this ramp's function constant from some tempo-pulse point
+  end tempo (in note types per minute)
+  duration (pulses into global start) of some other position.
 */
 double
 TempoSection::compute_c_func_pulse (const double& end_bpm, const double& end_pulse) const
@@ -409,7 +394,10 @@ TempoSection::compute_c_func_pulse (const double& end_bpm, const double& end_pul
        return (beats_per_minute() * expm1 (log_tempo_ratio)) / ((end_pulse - pulse()) * _note_type);
 }
 
-/* compute the function constant from some later tempo section, given tempo (quarter notes/min.) and distance (in frames) from session origin */
+/* compute the function constant from some tempo-time point.
+   tempo (note types/min.)
+   distance (in minutes) from session origin
+*/
 double
 TempoSection::compute_c_func_minute (const double& end_bpm, const double& end_minute) const
 {
@@ -430,28 +418,28 @@ TempoSection::c_func (double end_bpm, double end_time) const
        return log (end_bpm / beats_per_minute()) / end_time;
 }
 
-/* tempo in bpm at time in minutes */
+/* tempo in note types per minute at time in minutes */
 double
 TempoSection::_tempo_at_time (const double& time) const
 {
        return exp (_c_func * time) * beats_per_minute();
 }
 
-/* time in minutes at tempo in bpm */
+/* time in minutes at tempo in note types per minute */
 double
 TempoSection::_time_at_tempo (const double& tempo) const
 {
        return log (tempo / beats_per_minute()) / _c_func;
 }
 
-/* pulse at tempo in bpm */
+/* pulse at tempo in note types per minute */
 double
 TempoSection::_pulse_at_tempo (const double& tempo) const
 {
        return ((tempo - beats_per_minute()) / _c_func) / _note_type;
 }
 
-/* tempo in bpm at pulse */
+/* tempo in note types per minute at pulse */
 double
 TempoSection::_tempo_at_pulse (const double& pulse) const
 {
@@ -620,47 +608,38 @@ MeterSection::get_state() const
 /*
   Tempo Map Overview
 
-  The Shaggs - Things I Wonder
-  https://www.youtube.com/watch?v=9wQK6zMJOoQ
-
-  Tempo is the rate of the musical pulse.
-  Meter divides pulse into measures and beats.
+  Tempo determines the rate of musical pulse determined by its components
+        note types per minute - the rate per minute of the whole note divisor _note_type
+       note type             - the division of whole notes (pulses) which occur at the rate of note types per minute.
+  Meter divides the musical pulse into measures and beats according to its components
+        divisions_per_bar
+       note_divisor
+
+  TempoSection - translates between time, musical pulse and tempo.
+        has a musical location in whole notes (pulses).
+       has a time location in minutes.
+       Note that 'beats' in Tempo::beats_per_minute() are in fact note types per minute.
+       (In the rest of tempo map,'beat' usually refers to accumulated BBT beats (pulse and meter based).
+
+  MeterSection - translates between BBT, meter-based beat and musical pulse.
+        has a musical location in whole notes (pulses)
+       has a musical location in meter-based beats
+       has a musical location in BBT time
+       has a time location expressed in minutes.
 
-  TempoSection - provides pulse in the form of beats_per_minute() - the number of quarter notes in one minute.
-  Note that 'beats' in Tempo::beats_per_minute() are quarter notes (pulse based). In the rest of tempo map,
-  'beat' usually refers to accumulated BBT beats (pulse and meter based).
-
-  MeterSecion - divides pulse into measures (via divisions_per_bar) and beats (via note_divisor).
-
-  Both tempo and meter have a pulse position and a frame position.
-  Meters also have a beat position, which is always 0.0 for the first one.
   TempoSection and MeterSection may be locked to either audio or music (position lock style).
-  The lock style determines the 'true' position of the section wich is used to calculate the other postion parameters of the section.
-
-  The first tempo and first meter are special. they must move together, and must be locked to audio.
-  Audio locked tempos which lie before the first meter are made inactive.
-  They will be re-activated if the first meter is again placed before them.
-
-  With tempo sections potentially being ramped, meters provide a way of mapping beats to whole pulses without
-  referring to the tempo function(s) involved as the distance in whole pulses between a meter and a subsequent beat is
-  sb->beat() - meter->beat() / meter->note_divisor().
-  Because every meter falls on a known pulse, (derived from its bar), the rest is easy as the duration in pulses between
-  two meters is of course
-  (meater_b->bar - meter_a->bar) * meter_a->divisions_per_bar / meter_a->note_divisor.
+  The lock style determines the location type to be kept as a reference when location is recalculated.
 
-  Beat calculations are based on meter sections and all pulse and tempo calculations are based on tempo sections.
-  Beat to frame conversion of course requires the use of meter and tempo.
+  The first tempo and meter are special. they must move together, and are locked to audio.
+  Audio locked tempi which lie before the first meter are made inactive.
 
-  Remembering that ramped tempo sections interact, it is important to avoid referring to any other tempos when moving tempo sections,
-  Here, beats (meters) are used to determine the new pulse (see predict_tempo_position())
+  Recomputing the map is the process where the 'missing' location types are calculated.
+        We construct the tempo map by first using the locked location type of each section
+       to determine non-locked location types (pulse or minute position).
+        We then use this map to find the pulse or minute position of each meter (again depending on lock style).
 
-  Recomputing the map is the process where the 'missing' position
-  (tempo pulse or meter pulse & beat in the case of AudioTime, frame for MusicTime) is calculated.
-  We construct the tempo map by first using the frame or pulse position (depending on position lock style) of each tempo.
-  We then use this tempo map (really just the tempos) to find the pulse or frame position of each meter (again depending on lock style).
-
-  Having done this, we can now find any musical duration by selecting the tempo and meter covering the position (or tempo) in question
-  and querying its appropriate meter/tempo.
+  Having done this, we can now traverse the Metrics list by pulse or minute
+  to query its relevant meter/tempo.
 
   It is important to keep the _metrics in an order that makes sense.
   Because ramped MusicTime and AudioTime tempos can interact with each other,
@@ -697,11 +676,14 @@ MeterSection::get_state() const
   beat_at_frame (frame_at_beat (beat)) != beat due to the time quantization of frame_at_beat().
 
   Doing the second one will result in a beat distance error of up to 0.5 audio samples.
-  So instead work in pulses and/or beats and only use beat position to caclulate frame position (e.g. after tempo change).
-  For audio-locked objects, use frame position to calculate beat position.
+  frames_between_quarter_notes () eliminats this effect when determining time duration
+  from Beats distance, or instead work in quarter-notes and/or beats and convert to frames last.
 
-  The above pointless example would then do:
-  beat_at_pulse (pulse_at_beat (beat)) to avoid rounding.
+  The above pointless example could instead do:
+  beat_at_quarter_note (quarter_note_at_beat (beat)) to avoid rounding.
+
+  The Shaggs - Things I Wonder
+  https://www.youtube.com/watch?v=9wQK6zMJOoQ
 
 */
 struct MetricSectionSorter {
@@ -1584,7 +1566,7 @@ TempoMap::minute_at_beat_locked (const Metrics& metrics, const double& beat) con
        return prev_t->minute_at_pulse (((beat - prev_m->beat()) / prev_m->note_divisor()) + prev_m->pulse());
 }
 
-/** Returns a Tempo corresponding to the supplied frame.
+/** Returns a Tempo corresponding to the supplied frame position.
  * @param frame The audio frame.
  * @return a Tempo according to the tempo map at the supplied frame.
  *
@@ -1739,47 +1721,43 @@ TempoMap::pulse_at_tempo_locked (const Metrics& metrics, const Tempo& tempo) con
                }
        }
 
-       return prev_t->minute();
+       return prev_t->pulse();
 }
 
-/** Returns a Tempo corresponding to the supplied BBT (meter-based) beat.
- * @param beat The BBT (meter-based) beat.
+/** Returns a Tempo corresponding to the supplied position in quarter-note beats.
+ * @param qn the position in quarter note beats.
+ * @return the Tempo at the supplied quarter-note.
  */
 Tempo
-TempoMap::tempo_at_beat (const double& beat) const
+TempoMap::tempo_at_quarter_note (const double& qn) const
 {
        Glib::Threads::RWLock::ReaderLock lm (lock);
-       const MeterSection* prev_m = &meter_section_at_beat_locked (_metrics, beat);
-       const TempoSection* prev_t = &tempo_section_at_beat_locked (_metrics, beat);
 
-       return Tempo (prev_t->tempo_at_pulse (((beat - prev_m->beat()) / prev_m->note_divisor()) + prev_m->pulse()), prev_t->note_type());
+       return tempo_at_pulse_locked (_metrics, qn / 4.0);
 }
 
-/** Returns a BBT (meter-based) beat corresponding to the supplied Tempo.
- * @param tempo The tempo.
+/** Returns the position in quarter-note beats corresponding to the supplied Tempo.
+ * @param tempo the tempo.
+ * @return the position in quarter-note beats where the map bpm
+ * is equal to that of the Tempo. currently ignores note_type.
  */
 double
-TempoMap::beat_at_tempo (const Tempo& tempo) const
+TempoMap::quarter_note_at_tempo (const Tempo& tempo) const
 {
        Glib::Threads::RWLock::ReaderLock lm (lock);
-       const double pulse = pulse_at_tempo_locked (_metrics, tempo);
 
-       return beat_at_pulse_locked (_metrics, pulse);
+       return pulse_at_tempo_locked (_metrics, tempo) * 4.0;;
 }
+
 /** Returns the whole-note pulse corresponding to the supplied  BBT (meter-based) beat.
+ * @param metrics the list of metric sections used to calculate the pulse.
  * @param beat The BBT (meter-based) beat.
+ * @return the whole-note pulse at the supplied BBT (meter-based) beat.
  *
  * a pulse or whole note is the base musical position of a MetricSection.
  * it is equivalent to four quarter notes.
  *
  */
-double
-TempoMap::pulse_at_beat (const double& beat) const
-{
-       Glib::Threads::RWLock::ReaderLock lm (lock);
-       return pulse_at_beat_locked (_metrics, beat);
-}
-
 double
 TempoMap::pulse_at_beat_locked (const Metrics& metrics, const double& beat) const
 {
@@ -1789,18 +1767,13 @@ TempoMap::pulse_at_beat_locked (const Metrics& metrics, const double& beat) cons
 }
 
 /** Returns the BBT (meter-based) beat corresponding to the supplied whole-note pulse .
+ * @param metrics the list of metric sections used to calculate the beat.
  * @param pulse the whole-note pulse.
+ * @return the meter-based beat at the supplied whole-note pulse.
  *
  * a pulse or whole note is the base musical position of a MetricSection.
  * it is equivalent to four quarter notes.
  */
-double
-TempoMap::beat_at_pulse (const double& pulse) const
-{
-       Glib::Threads::RWLock::ReaderLock lm (lock);
-       return beat_at_pulse_locked (_metrics, pulse);
-}
-
 double
 TempoMap::beat_at_pulse_locked (const Metrics& metrics, const double& pulse) const
 {
@@ -1821,13 +1794,6 @@ TempoMap::beat_at_pulse_locked (const Metrics& metrics, const double& pulse) con
        return ret;
 }
 
-double
-TempoMap::pulse_at_frame (const framepos_t& frame) const
-{
-       Glib::Threads::RWLock::ReaderLock lm (lock);
-       return pulse_at_minute_locked (_metrics, minute_at_frame (frame));
-}
-
 /* tempo section based */
 double
 TempoMap::pulse_at_minute_locked (const Metrics& metrics, const double& minute) const
@@ -1861,14 +1827,6 @@ TempoMap::pulse_at_minute_locked (const Metrics& metrics, const double& minute)
        return pulses_in_section + prev_t->pulse();
 }
 
-framepos_t
-TempoMap::frame_at_pulse (const double& pulse) const
-{
-       Glib::Threads::RWLock::ReaderLock lm (lock);
-
-       return frame_at_minute (minute_at_pulse_locked (_metrics, pulse));
-}
-
 /* tempo section based */
 double
 TempoMap::minute_at_pulse_locked (const Metrics& metrics, const double& pulse) const
@@ -1900,6 +1858,7 @@ TempoMap::minute_at_pulse_locked (const Metrics& metrics, const double& pulse) c
 
 /** Returns the BBT (meter-based) beat corresponding to the supplied BBT time.
  * @param bbt The BBT time (meter-based).
+ * @return bbt The BBT beat (meter-based) at the supplied BBT time.
  *
  */
 double
@@ -1944,6 +1903,7 @@ TempoMap::beat_at_bbt_locked (const Metrics& metrics, const Timecode::BBT_Time&
 
 /** Returns the BBT time corresponding to the supplied BBT (meter-based) beat.
  * @param beat The BBT (meter-based) beat.
+ * @return The BBT time (meter-based) at the supplied meter-based beat.
  *
  */
 Timecode::BBT_Time
@@ -2005,31 +1965,32 @@ TempoMap::bbt_at_beat_locked (const Metrics& metrics, const double& b) const
        return ret;
 }
 
-/** Returns the whole-note pulse corresponding to the supplied BBT time (meter-based).
+/** Returns the quarter-note beat corresponding to the supplied BBT time (meter-based).
  * @param bbt The BBT time (meter-based).
+ * @return the quarter note beat at the supplied BBT time
+ *
+ * quarter-notes ignore meter and are based on pulse (the musical unit of MetricSection).
  *
- * a pulse or whole note is the basic musical position of a MetricSection.
- * it is equivalent to four quarter notes.
  * while the input uses meter, the output does not.
  */
 double
-TempoMap::pulse_at_bbt (const Timecode::BBT_Time& bbt)
+TempoMap::quarter_note_at_bbt (const Timecode::BBT_Time& bbt)
 {
        Glib::Threads::RWLock::ReaderLock lm (lock);
 
-       return pulse_at_bbt_locked (_metrics, bbt);
+       return pulse_at_bbt_locked (_metrics, bbt) * 4.0;
 }
 
 double
-TempoMap::pulse_at_bbt_rt (const Timecode::BBT_Time& bbt)
+TempoMap::quarter_note_at_bbt_rt (const Timecode::BBT_Time& bbt)
 {
-       Glib::Threads::RWLock::ReaderLock lm (lock);
+       Glib::Threads::RWLock::ReaderLock lm (lock, Glib::Threads::TRY_LOCK);
 
        if (!lm.locked()) {
-               throw std::logic_error ("TempoMap::pulse_at_bbt_rt() could not lock tempo map");
+               throw std::logic_error ("TempoMap::quarter_note_at_bbt_rt() could not lock tempo map");
        }
 
-       return pulse_at_bbt_locked (_metrics, bbt);
+       return pulse_at_bbt_locked (_metrics, bbt) * 4.0;
 }
 
 double
@@ -2062,21 +2023,31 @@ TempoMap::pulse_at_bbt_locked (const Metrics& metrics, const Timecode::BBT_Time&
 
        return ret;
 }
-/** Returns the BBT time (meter-based) corresponding to the supplied whole-note pulse.
- * @param pulse The whole-note pulse.
+
+/** Returns the BBT time corresponding to the supplied quarter-note beat.
+ * @param qn the quarter-note beat.
+ * @return The BBT time (meter-based) at the supplied meter-based beat.
+ *
+ * quarter-notes ignore meter and are based on pulse (the musical unit of MetricSection).
  *
- * a pulse or whole note is the basic musical position of a MetricSection.
- * it is equivalent to four quarter notes.
- * while the input uses meter, the output does not.
  */
 Timecode::BBT_Time
-TempoMap::bbt_at_pulse (const double& pulse)
+TempoMap::bbt_at_quarter_note (const double& qn)
 {
        Glib::Threads::RWLock::ReaderLock lm (lock);
 
-       return bbt_at_pulse_locked (_metrics, pulse);
+       return bbt_at_pulse_locked (_metrics, qn / 4.0);
 }
 
+/** Returns the BBT time (meter-based) corresponding to the supplied whole-note pulse position.
+ * @param metrics The list of metric sections used to determine the result.
+ * @param pulse The whole-note pulse.
+ * @return The BBT time at the supplied whole-note pulse.
+ *
+ * a pulse or whole note is the basic musical position of a MetricSection.
+ * it is equivalent to four quarter notes.
+ * while the output uses meter, the input does not.
+ */
 Timecode::BBT_Time
 TempoMap::bbt_at_pulse_locked (const Metrics& metrics, const double& pulse) const
 {
@@ -2132,6 +2103,7 @@ TempoMap::bbt_at_pulse_locked (const Metrics& metrics, const double& pulse) cons
 
 /** Returns the BBT time corresponding to the supplied frame position.
  * @param frame the position in audio samples.
+ * @return the BBT time at the frame position .
  *
  */
 BBT_Time
@@ -2232,8 +2204,9 @@ TempoMap::bbt_at_minute_locked (const Metrics& metrics, const double& minute) co
        return ret;
 }
 
-/** Returns the frame corresponding to the supplied BBT time.
+/** Returns the frame position corresponding to the supplied BBT time.
  * @param bbt the position in BBT time.
+ * @return the frame position at bbt.
  *
  */
 framepos_t
@@ -2265,14 +2238,9 @@ TempoMap::minute_at_bbt_locked (const Metrics& metrics, const BBT_Time& bbt) con
 /**
  * Returns the quarter-note beat position corresponding to the supplied frame.
  *
- * @param frame The distance in frames relative to session 0 whose quarter note distance you would like.
+ * @param frame the position in frames.
  * @return The quarter-note position of the supplied frame. Ignores meter.
  *
- * Plugin APIs don't count ticks in the same way PROGRAM_NAME does.
- * We use ticks per beat whereas the rest of the world uses ticks per quarter note.
- * This is more or less the VST's ppqPos (a scalar you use to obtain tick position
- * in whatever ppqn you're using).
- *
 */
 double
 TempoMap::quarter_note_at_frame (const framepos_t frame)
@@ -2307,10 +2275,10 @@ TempoMap::quarter_note_at_frame_rt (const framepos_t frame)
 }
 
 /**
- * Returns the frame corresponding to the supplied quarter-note beat position.
+ * Returns the frame position corresponding to the supplied quarter-note beat.
  *
- * @param quarter_note The quarter-note relative to session 0 whose frame position you would like.
- * @return The frame position of the supplied quarter-note. Ignores meter.
+ * @param quarter_note the quarter-note position.
+ * @return the frame position of the supplied quarter-note. Ignores meter.
  *
  *
 */
@@ -2334,8 +2302,9 @@ TempoMap::minute_at_quarter_note_locked (const Metrics& metrics, const double qu
 
 /** Returns the quarter-note beats corresponding to the supplied BBT (meter-based) beat.
  * @param beat The BBT (meter-based) beat.
+ * @return The quarter-note position of the supplied BBT (meter-based) beat.
  *
- * a quarter-note is the musical unit of Evoral::Beats.
+ * a quarter-note may be compared with and assigned to Evoral::Beats.
  *
  */
 double
@@ -2358,6 +2327,7 @@ TempoMap::quarter_note_at_beat_locked (const Metrics& metrics, const double beat
 
 /** Returns the BBT (meter-based) beat position corresponding to the supplied quarter-note beats.
  * @param quarter_note The position in quarter-note beats.
+ * @return the BBT (meter-based) beat position of the supplied quarter-note beats.
  *
  * a quarter-note is the musical unit of Evoral::Beats.
  *
@@ -2379,9 +2349,10 @@ TempoMap::beat_at_quarter_note_locked (const Metrics& metrics, const double quar
        return beat_at_pulse_locked (metrics, quarter_note / 4.0);
 }
 
-/** Returns the distance in frames between two supplied quarter-note beats.
+/** Returns the duration in frames between two supplied quarter-note beat positions.
  * @param start the first position in quarter-note beats.
  * @param end the end position in quarter-note beats.
+ * @return the frame distance ober the quarter-note beats duration.
  *
  * use this rather than e.g.
  * frame_at-quarter_note (end_beats) - frame_at_quarter_note (start_beats).
@@ -3199,14 +3170,14 @@ TempoMap::gui_change_tempo (TempoSection* ts, const Tempo& bpm)
 }
 
 void
-TempoMap::gui_dilate_tempo (TempoSection* ts, const framepos_t& frame, const framepos_t& end_frame, const double& pulse)
+TempoMap::gui_dilate_tempo (TempoSection* ts, const framepos_t& frame, const framepos_t& end_frame)
 {
        /*
          Ts (future prev_t)   Tnext
          |                    |
          |     [drag^]        |
          |----------|----------
-               e_f  pulse(frame)
+               e_f  qn_beats(frame)
        */
 
        Metrics future_map;
@@ -3251,8 +3222,8 @@ TempoMap::gui_dilate_tempo (TempoSection* ts, const framepos_t& frame, const fra
 
                const frameoffset_t prev_t_frame_contribution = fr_off - (contribution * (double) fr_off);
 
-               const double start_pulse = prev_t->pulse_at_frame (frame);
-               const double end_pulse = prev_t->pulse_at_frame (end_frame);
+               const double start_pulse = prev_t->pulse_at_minute (minute_at_frame (frame));
+               const double end_pulse = prev_t->pulse_at_minute (minute_at_frame (end_frame));
 
                double new_bpm;
 
@@ -3300,7 +3271,7 @@ TempoMap::gui_dilate_tempo (TempoSection* ts, const framepos_t& frame, const fra
 
                        double frame_ratio = 1.0;
                        double pulse_ratio = 1.0;
-                       const double pulse_pos = prev_t->frame_at_pulse (pulse);
+                       const double pulse_pos = frame;
 
                        if (prev_to_prev_t) {
                                if (pulse_pos > prev_to_prev_t->frame() + min_dframe && (pulse_pos - fr_off) > prev_to_prev_t->frame() + min_dframe) {
@@ -3348,6 +3319,7 @@ TempoMap::gui_dilate_tempo (TempoSection* ts, const framepos_t& frame, const fra
 
 /** Returns the exact bbt-based beat corresponding to the bar, beat or quarter note subdivision nearest to
  * the supplied frame, possibly returning a negative value.
+ *
  * @param frame  The session frame position.
  * @param sub_num The subdivision to use when rounding the beat.
  *                A value of -1 indicates rounding to BBT bar. 1 indicates rounding to BBT beats.
@@ -3355,11 +3327,17 @@ TempoMap::gui_dilate_tempo (TempoSection* ts, const framepos_t& frame, const fra
  *                0 indicates that the returned beat should not be rounded (equivalent to quarter_note_at_frame()).
  * @return The beat position of the supplied frame.
  *
+ * when working to a musical grid, the use of sub_nom indicates that
+ * the position should be interpreted musically.
+ *
+ * it effectively snaps to meter bars, meter beats or quarter note divisions
+ * (as per current gui convention) and returns a musical position independent of frame rate.
+ *
  * If the supplied frame lies before the first meter, the return will be negative,
  * in which case the returned beat uses the first meter (for BBT subdivisions) and
  * the continuation of the tempo curve (backwards).
  *
- * This function uses both tempo and meter.
+ * This function is sensitive to tempo and meter.
  */
 double
 TempoMap::exact_beat_at_frame (const framepos_t& frame, const int32_t sub_num)
@@ -3377,8 +3355,6 @@ TempoMap::exact_beat_at_frame_locked (const Metrics& metrics, const framepos_t&
 
 /** Returns the exact quarter note corresponding to the bar, beat or quarter note subdivision nearest to
  * the supplied frame, possibly returning a negative value.
- * Supplying a frame position with a non-zero sub_num is equivalent to supplying
- * a quarter-note musical position without frame rounding (see below)
  *
  * @param frame  The session frame position.
  * @param sub_num The subdivision to use when rounding the quarter note.
@@ -3387,11 +3363,17 @@ TempoMap::exact_beat_at_frame_locked (const Metrics& metrics, const framepos_t&
  *                0 indicates that the returned quarter note should not be rounded (equivalent to quarter_note_at_frame()).
  * @return The quarter note position of the supplied frame.
  *
+ * When working to a musical grid, the use of sub_nom indicates that
+ * the frame position should be interpreted musically.
+ *
+ * it effectively snaps to meter bars, meter beats or quarter note divisions
+ * (as per current gui convention) and returns a musical position independent of frame rate.
+ *
  * If the supplied frame lies before the first meter, the return will be negative,
  * in which case the returned quarter note uses the first meter (for BBT subdivisions) and
  * the continuation of the tempo curve (backwards).
  *
- * This function uses both tempo and meter.
+ * This function is tempo-sensitive.
  */
 double
 TempoMap::exact_qn_at_frame (const framepos_t& frame, const int32_t sub_num)