[dasher] Fix framerate changing!



commit a9d64488415bc84671d83ee102c2c40d64a53785
Author: Alan Lawrence <acl33 inf phy cam ac uk>
Date:   Tue Oct 12 16:36:37 2010 +0100

    Fix framerate changing!
    
    LP_FRAMERATE stores decaying average of framerate; used to
    compute m_iSteps & m_dRXMax immediately upon bitrate change.
    
    Removed GetFramerate() etc. methods (use LP_FRAMERATE!)

 Src/DasherCore/AutoSpeedControl.cpp    |   16 +++----
 Src/DasherCore/AutoSpeedControl.h      |    2 +-
 Src/DasherCore/DasherGameMode.cpp      |    5 +-
 Src/DasherCore/DasherInterfaceBase.cpp |    7 ---
 Src/DasherCore/DasherInterfaceBase.h   |    2 -
 Src/DasherCore/DefaultFilter.cpp       |    2 +-
 Src/DasherCore/FrameRate.cpp           |   64 ++++++++++++++++++--------------
 Src/DasherCore/FrameRate.h             |   30 +++++++--------
 Src/DasherCore/Parameters.h            |    2 +-
 Src/Gtk2/GtkDasherControl.cpp          |    6 ---
 Src/Gtk2/GtkDasherControl.h            |    1 -
 11 files changed, 62 insertions(+), 75 deletions(-)
---
diff --git a/Src/DasherCore/AutoSpeedControl.cpp b/Src/DasherCore/AutoSpeedControl.cpp
index be487e2..afafc18 100644
--- a/Src/DasherCore/AutoSpeedControl.cpp
+++ b/Src/DasherCore/AutoSpeedControl.cpp
@@ -129,13 +129,11 @@ inline double CAutoSpeedControl::Variance()
 
 inline int CAutoSpeedControl::UpdateSampleSize(double dFrameRate)
 {
-  double dFramerate = dFrameRate;
-  double dSpeedSamples = 0.0;
-  double dBitrate = m_dBitrate; 
-  if(dBitrate < 1.0)// for the purposes of this function
-    dBitrate = 1.0; // we don't care exactly how slow we're going
-                    // *really* low speeds are ~ equivalent?
-  dSpeedSamples = dFramerate * (m_dSampleScale / dBitrate + m_dSampleOffset);
+  // for the purposes of this function
+  // we don't care exactly how slow we're going
+  // *really* low speeds are ~ equivalent?
+  double dBitrate = std::max(1.0,m_dBitrate); 
+  double dSpeedSamples = dFrameRate * (m_dSampleScale / dBitrate + m_dSampleOffset);
  
   m_nSpeedSamples = int(round(dSpeedSamples));
 
@@ -180,7 +178,7 @@ inline void CAutoSpeedControl::UpdateSigmas(double r, double dFrameRate)
 ////////////////////////////////////////////////////////////////
 
 
-void CAutoSpeedControl::SpeedControl(myint iDasherX, myint iDasherY, double dFrameRate, CDasherView *pView) {
+void CAutoSpeedControl::SpeedControl(myint iDasherX, myint iDasherY, CDasherView *pView) {
   if(GetBoolParameter(BP_AUTO_SPEEDCONTROL)) {
     
 //  Coordinate transforms:
@@ -188,7 +186,7 @@ void CAutoSpeedControl::SpeedControl(myint iDasherX, myint iDasherY, double dFra
 	pView->Dasher2Polar(iDasherX, iDasherY, r, theta);
 
     m_dBitrate = GetLongParameter(LP_MAX_BITRATE) / 100.0; //  stored as long(round(true bitrate * 100))
-
+    double dFrameRate = GetLongParameter(LP_FRAMERATE) / 100.0;
     UpdateSigmas(r, dFrameRate);
 
 //  Data collection:
diff --git a/Src/DasherCore/AutoSpeedControl.h b/Src/DasherCore/AutoSpeedControl.h
index 2a184ff..e41143b 100644
--- a/Src/DasherCore/AutoSpeedControl.h
+++ b/Src/DasherCore/AutoSpeedControl.h
@@ -22,7 +22,7 @@ class CAutoSpeedControl : public Dasher::CDasherComponent {
   /// \param dFrameRate The current frame rate
   /// \param pView The current Dasher view class
   ///
-  void SpeedControl(myint iDasherX, myint iDasherY, double dFrameRate, CDasherView *pView);
+  void SpeedControl(myint iDasherX, myint iDasherY, CDasherView *pView);
 
   virtual void HandleEvent(Dasher::CEvent *pEvent) {
   };
diff --git a/Src/DasherCore/DasherGameMode.cpp b/Src/DasherCore/DasherGameMode.cpp
index 40e0793..aa9bcd9 100644
--- a/Src/DasherCore/DasherGameMode.cpp
+++ b/Src/DasherCore/DasherGameMode.cpp
@@ -438,13 +438,12 @@ void CDasherGameMode::SetTargetY(const std::vector<std::pair<Dasher::myint,bool>
 
 void CDasherGameMode::CalculateDemoParameters()
 {
+  if(GetLongParameter(LP_FRAMERATE) <= 0) return;
   // Recalculates the parameters used in the demo following a change in framerate or speed.
   double spring = GetLongParameter(LP_DEMO_SPRING)/100.0;
   double noisemem = GetLongParameter(LP_DEMO_NOISE_MEM)/100.0;
-  double lambda = 0.7*double(GetLongParameter(LP_MAX_BITRATE))/(100.0*m_pModel->Framerate());
+  double lambda = 0.7*double(GetLongParameter(LP_MAX_BITRATE))/(100.0*GetLongParameter(LP_FRAMERATE));
   
-  if(m_pModel->Framerate() <= 0) return;
-
   m_DemoCfg.dSpring = (1-exp(-spring*lambda));
   m_DemoCfg.dNoiseNew = noisemem*(1-exp(-lambda));
   m_DemoCfg.dNoiseOld = sqrt(1.0-m_DemoCfg.dNoiseNew*m_DemoCfg.dNoiseNew);
diff --git a/Src/DasherCore/DasherInterfaceBase.cpp b/Src/DasherCore/DasherInterfaceBase.cpp
index 52f224c..5a6b008 100644
--- a/Src/DasherCore/DasherInterfaceBase.cpp
+++ b/Src/DasherCore/DasherInterfaceBase.cpp
@@ -1052,13 +1052,6 @@ void CDasherInterfaceBase::ExecuteCommand(const std::string &strName) {
   delete pEvent;
 }
 
-double CDasherInterfaceBase::GetFramerate() {
-  if(m_pDasherModel)
-    return(m_pDasherModel->Framerate());
-  else
-    return 0.0;
-}
-
 void CDasherInterfaceBase::AddActionButton(const std::string &strName) {
   m_vRightButtons.push_back(new CActionButton(this, strName, false));
 }
diff --git a/Src/DasherCore/DasherInterfaceBase.h b/Src/DasherCore/DasherInterfaceBase.h
index d621194..40bfc96 100644
--- a/Src/DasherCore/DasherInterfaceBase.h
+++ b/Src/DasherCore/DasherInterfaceBase.h
@@ -325,8 +325,6 @@ public:
 
   void ResetNats();
 
-  double GetFramerate();
-
   /// @}
 
   /// @name Control hierarchy and action buttons
diff --git a/Src/DasherCore/DefaultFilter.cpp b/Src/DasherCore/DefaultFilter.cpp
index a66336d..c8e9276 100644
--- a/Src/DasherCore/DefaultFilter.cpp
+++ b/Src/DasherCore/DefaultFilter.cpp
@@ -70,7 +70,7 @@ bool CDefaultFilter::Timer(int Time, CDasherView *m_pDasherView, CDasherModel *m
     m_pDasherModel->OneStepTowards(iDasherX,iDasherY, Time, pAdded, pNumDeleted);
     bDidSomething = true;
 
-    m_pAutoSpeedControl->SpeedControl(iDasherX, iDasherY, m_pDasherModel->Framerate(), m_pDasherView);
+    m_pAutoSpeedControl->SpeedControl(iDasherX, iDasherY, m_pDasherView);
   }
 	
   if(m_pStartHandler)
diff --git a/Src/DasherCore/FrameRate.cpp b/Src/DasherCore/FrameRate.cpp
index 2712d02..ff69c24 100644
--- a/Src/DasherCore/FrameRate.cpp
+++ b/Src/DasherCore/FrameRate.cpp
@@ -1,21 +1,20 @@
 #include "FrameRate.h"
-namespace Dasher {
+
+using namespace Dasher;
+
 CFrameRate::CFrameRate(CEventHandler *pEventHandler, CSettingsStore *pSettingsStore) :
   CDasherComponent(pEventHandler, pSettingsStore) {
 
-  //what follows was once the Initialise() method, but
-  // (ACL 21/05/09) is no longer called from elsewhere, hence inlining
-  m_dRXmax = 2;                 // only a transient effect
+  //Sampling parameters...
   m_iFrames = 0;
   m_iSamples = 1;
-
-  // start off very slow until we have sampled framerate adequately
-  m_iSteps = 2000;
   m_iTime = 0;                  // Hmmm, User must reset framerate before starting.
 
-  //Set bitrate and framerate
-  m_dFr = GetLongParameter(LP_FRAMERATE) / 100.0;
-  m_dMaxbitrate = GetLongParameter(LP_MAX_BITRATE) * GetLongParameter(LP_BOOSTFACTOR) / 10000.0;
+  //try and carry on from where we left off at last run
+  CParameterNotificationEvent evt(LP_FRAMERATE);
+  HandleEvent(&evt);
+  evt.m_iParameter = LP_MAX_BITRATE;
+  HandleEvent(&evt); //calls UpdateSteps(), which sets m_dRXMax and m_iSteps
 }
 
 void CFrameRate::RecordFrame(unsigned long Time)
@@ -24,7 +23,7 @@ void CFrameRate::RecordFrame(unsigned long Time)
 
   // Update values once enough samples have been collected
   if(m_iFrames == m_iSamples) {
-    m_iTime2 = Time;
+    int m_iTime2 = Time;
 
     // If samples are collected in < 50ms, collect more
     if(m_iTime2 - m_iTime < 50)
@@ -39,25 +38,19 @@ void CFrameRate::RecordFrame(unsigned long Time)
 
     // Calculate the framerate and reset framerate statistics for next
     // sampling period
+    double dFrNow;
     if(m_iTime2 - m_iTime > 0) {
-      SetLongParameter(LP_FRAMERATE, m_iFrames * 100000.0 / (m_iTime2 - m_iTime));
+      dFrNow = m_iFrames * 1000.0 / (m_iTime2 - m_iTime);
+      SetLongParameter(LP_FRAMERATE, long(GetLongParameter(LP_FRAMERATE) + (dFrNow*100))/2);
       m_iTime = m_iTime2;
       m_iFrames = 0;
-    }
+    } else //best guess: use decaying average
+      dFrNow = GetLongParameter(LP_FRAMERATE) / 100.0;
 
-    // Update auxiliary variables - even if we didn't recalc the framerate
-    //   (means we reach sensible values more quickly after first loading)
-    m_dRXmax = exp(m_dMaxbitrate * LN2 / m_dFr);
-    
-    // Note that m_iSteps is smoothed here - 50:50 interpolation with
-    // previous value
-    m_iSteps = m_iSteps / 2 + (int)(-log(0.2) * m_dFr / LN2 / m_dMaxbitrate) / 2;
+    UpdateSteps(dFrNow);
 
-    // If the framerate slows to < 4 then we end up with steps < 1 ! 
-    if(m_iSteps == 0)
-      m_iSteps = 1;
+    DASHER_TRACEOUTPUT("Fr %f Steps %d Samples %d Time2 %d rxmax %f\n", dFrNow, m_iSteps, m_iSamples, m_iTime2, m_dRXmax);
 
-    DASHER_TRACEOUTPUT("Fr %f Steps %d Samples %d Time2 %d rxmax %f\n", m_dFr, m_iSteps, m_iSamples, m_iTime2, m_dRXmax);
   }
 }
 
@@ -69,14 +62,29 @@ void CFrameRate::HandleEvent(Dasher::CEvent *pEvent) {
     switch (pEvt->m_iParameter) {
     case LP_MAX_BITRATE: // Delibarate fallthrough
     case LP_BOOSTFACTOR:
-      BitrateChanged(GetLongParameter(LP_MAX_BITRATE) * GetLongParameter(LP_BOOSTFACTOR) / 10000.0);
-      //Apply the bit rate fully straightaway (no 50:50 interpolation with previous):
-      m_iSteps = (int)(-log(0.2) * m_dFr / LN2 / m_dMaxbitrate);
+      m_dMaxbitrate=(GetLongParameter(LP_MAX_BITRATE) * GetLongParameter(LP_BOOSTFACTOR)) / 10000.0;
+      UpdateSteps(GetLongParameter(LP_FRAMERATE) / 100.0); //use the decaying average as current
       break;
     case LP_FRAMERATE:
-      FramerateChanged(GetLongParameter(LP_FRAMERATE) / 100.0);
+      m_dFrDecay = GetLongParameter(LP_FRAMERATE) / 100.0;
     }
   }
 }
 
+const double LN2 = log(2.0);
+const double STEPS_COEFF = -log(0.2) / LN2;
+
+void CFrameRate::UpdateSteps(double dFrNow) {
+    // Update auxiliary variables - even if we didn't recalc the framerate
+    //   (means we reach sensible values more quickly after first loading)
+    m_dRXmax = exp(m_dMaxbitrate * LN2 / dFrNow);
+    
+    // Note that m_iSteps is smoothed here - 50:50 interpolation with
+    // previous value
+    m_iSteps = std::max(1,(int)(STEPS_COEFF * m_dFrDecay / m_dMaxbitrate));
+
+    // If the framerate slows to < 4 then we end up with steps < 1 ! 
+    if(m_iSteps == 0)
+      m_iSteps = 1;
+
 }
diff --git a/Src/DasherCore/FrameRate.h b/Src/DasherCore/FrameRate.h
index 11cd288..8e13a80 100644
--- a/Src/DasherCore/FrameRate.h
+++ b/Src/DasherCore/FrameRate.h
@@ -15,14 +15,12 @@
 #include "Parameters.h"
 #include "DasherComponent.h"
 
-const double LN2 = log(2.0);
-
 namespace Dasher {
 /// \ingroup Model
 /// \{
 
-/// keeps track of framerate
-/// computes the Steps parameter
+/// keeps the framerate (LP_FRAMERATE / 100.0) up-to-date,
+/// computes the Steps parameter,
 /// computes RXmax - which controls the maximum rate of zooming in
 class CFrameRate : public CDasherComponent {
 public:
@@ -46,19 +44,10 @@ public:
     return m_iSteps;
   }; 
 
-  ///
-  /// Get the current framerate
-  ///
-  double Framerate() const {
-    return m_dFr;
-  };
-
   double Bitrate() const {
     return m_dMaxbitrate;
   }
 
-  virtual void BitrateChanged(double dMaxbitrate) {m_dMaxbitrate = dMaxbitrate;}
-  virtual void FramerateChanged(double dFr) {m_dFr = dFr;}
   ///
   /// Reset the framerate class
   /// TODO: Need to check semantics here
@@ -69,15 +58,24 @@ public:
     m_iTime = Time;
   }
 
-
   void RecordFrame(unsigned long Time);
   
 private:
-  double m_dFr;                 // current frame rate (cache of LP_FRAMERATE/100.0)
+  double m_dFrDecay;            // current frame rate (cache of LP_FRAMERATE/100.0)
   double m_dMaxbitrate;         // the maximum rate of entering information (cache)
   double m_dRXmax;              // the maximum zoomin per frame
-  int m_iFrames, m_iTime, m_iTime2, m_iSamples;
+  ///number of frames that have been sampled
+  int m_iFrames;
+  ///time at which first sampled frame was rendered
+  int m_iTime;
+  ///number of frames over which we will compute average framerate
+  int m_iSamples;
+
   int m_iSteps;                 // the 'Steps' parameter. See djw thesis.
+
+  ///updates m_dRXMax and m_iSteps
+  /// \param dFrNow current (non-decaying-average) framerate (if available!)
+  void UpdateSteps(double dFrNow);
 };
 /// \}
 }
diff --git a/Src/DasherCore/Parameters.h b/Src/DasherCore/Parameters.h
index dd95cfa..64df3f3 100644
--- a/Src/DasherCore/Parameters.h
+++ b/Src/DasherCore/Parameters.h
@@ -190,7 +190,7 @@ static lp_table longparamtable[] = {
   {LP_ORIENTATION, "ScreenOrientation", PERS, -2, "Screen Orientation"},
   {LP_REAL_ORIENTATION, "RealOrientation", !PERS, 0, "Actual screen orientation (allowing for alphabet default)"},
   {LP_MAX_BITRATE, "MaxBitRateTimes100", PERS, 80, "Max Bit Rate Times 100"},
-  {LP_FRAMERATE, "FrameRate", PERS, 3200, "Last known frame rate, times 100"},
+  {LP_FRAMERATE, "FrameRate", PERS, 3200, "Decaying average of last known frame rates, *100"},
   {LP_VIEW_ID, "ViewID", PERS, 1, "ViewID"},
   {LP_LANGUAGE_MODEL_ID, "LanguageModelID", PERS, 0, "LanguageModelID"},
   {LP_DASHER_FONTSIZE, "DasherFontSize", PERS, 2, "DasherFontSize"},
diff --git a/Src/Gtk2/GtkDasherControl.cpp b/Src/Gtk2/GtkDasherControl.cpp
index e2ea47c..94778e1 100644
--- a/Src/Gtk2/GtkDasherControl.cpp
+++ b/Src/Gtk2/GtkDasherControl.cpp
@@ -289,12 +289,6 @@ gtk_dasher_control_force_pause(GtkDasherControl *pControl) {
   pPrivate->pControl->Stop();
 }
 
-double 
-gtk_dasher_control_get_framerate(GtkDasherControl *pControl) {
-  GtkDasherControlPrivate *pPrivate = GTK_DASHER_CONTROL_GET_PRIVATE(pControl);
-  return pPrivate->pControl->GetFramerate();
-}
-
 void 
 gtk_dasher_control_add_action_button(GtkDasherControl *pControl, const gchar *szCommand) {
   GtkDasherControlPrivate *pPrivate = GTK_DASHER_CONTROL_GET_PRIVATE(pControl);
diff --git a/Src/Gtk2/GtkDasherControl.h b/Src/Gtk2/GtkDasherControl.h
index 1ff3ab1..3856c79 100644
--- a/Src/Gtk2/GtkDasherControl.h
+++ b/Src/Gtk2/GtkDasherControl.h
@@ -87,7 +87,6 @@ void gtk_dasher_control_game_helperreg(GtkDasherControl *pControl, void* gameHel
 void gtk_dasher_control_game_messageout(GtkDasherControl *pControl, int message, const void* messagedata);
 
 void gtk_dasher_control_force_pause(GtkDasherControl *pControl);
-double gtk_dasher_control_get_framerate(GtkDasherControl *pControl);
 void gtk_dasher_control_add_action_button(GtkDasherControl *pControl, const gchar *szCommand);
 void gtk_dasher_user_log_new_trial(GtkDasherControl * pControl);
 void gtk_dasher_control_set_focus(GtkDasherControl * pControl);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]