jack2 codebase
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

110 lines
3.7KB

  1. /*
  2. Copyright (C) 2001 Paul Davis
  3. Copyright (C) 2004-2006 Grame
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. */
  16. #include "JackFrameTimer.h"
  17. #include "JackError.h"
  18. #include <math.h>
  19. namespace Jack
  20. {
  21. JackTimer::JackTimer()
  22. {
  23. fInitialized = false;
  24. fFrames = 0;
  25. fCurrentWakeup = 0;
  26. fCurrentCallback = 0;
  27. fNextWakeUp = 0;
  28. fFilterCoefficient = 0.01f;
  29. fSecondOrderIntegrator = 0.0f;
  30. }
  31. void JackFrameTimer::Init()
  32. {
  33. fFirstWakeUp = true;
  34. }
  35. void JackFrameTimer::IncFrameTime(jack_nframes_t nframes, jack_time_t callback_usecs, jack_time_t period_usecs)
  36. {
  37. if (fFirstWakeUp) {
  38. InitFrameTime(callback_usecs, period_usecs);
  39. fFirstWakeUp = false;
  40. } else {
  41. IncFrameTimeAux(nframes, callback_usecs, period_usecs);
  42. }
  43. }
  44. void JackFrameTimer::InitFrameTime(jack_time_t callback_usecs, jack_time_t period_usecs)
  45. {
  46. JackTimer* timer = WriteNextStateStart();
  47. timer->fSecondOrderIntegrator = 0.0f;
  48. timer->fCurrentCallback = callback_usecs;
  49. timer->fNextWakeUp = callback_usecs + period_usecs;
  50. WriteNextStateStop();
  51. TrySwitchState();
  52. }
  53. void JackFrameTimer::ResetFrameTime(jack_nframes_t frames_rate, jack_time_t callback_usecs, jack_time_t period_usecs)
  54. {
  55. if (!fFirstWakeUp) { // ResetFrameTime may be called by a xrun/delayed wakeup on the first cycle
  56. JackTimer* timer = WriteNextStateStart();
  57. jack_nframes_t period_size_guess = (jack_nframes_t)(frames_rate * ((timer->fNextWakeUp - timer->fCurrentWakeup) / 1000000.0));
  58. timer->fFrames += ((callback_usecs - timer->fNextWakeUp) / period_size_guess) * period_size_guess;
  59. timer->fCurrentWakeup = callback_usecs;
  60. timer->fCurrentCallback = callback_usecs;
  61. timer->fNextWakeUp = callback_usecs + period_usecs;
  62. WriteNextStateStop();
  63. TrySwitchState();
  64. }
  65. }
  66. void JackFrameTimer::IncFrameTimeAux(jack_nframes_t nframes, jack_time_t callback_usecs, jack_time_t period_usecs)
  67. {
  68. JackTimer* timer = WriteNextStateStart();
  69. float delta = (int64_t)callback_usecs - (int64_t)timer->fNextWakeUp;
  70. timer->fCurrentWakeup = timer->fNextWakeUp;
  71. timer->fCurrentCallback = callback_usecs;
  72. timer->fFrames += nframes;
  73. timer->fSecondOrderIntegrator += 0.5f * timer->fFilterCoefficient * delta;
  74. timer->fNextWakeUp = timer->fCurrentWakeup + period_usecs + (int64_t) floorf((timer->fFilterCoefficient * (delta + timer->fSecondOrderIntegrator)));
  75. timer->fInitialized = true;
  76. WriteNextStateStop();
  77. TrySwitchState();
  78. }
  79. /*
  80. Use the state returned by ReadCurrentState and check that the state was not changed during the read operation.
  81. The operation is lock-free since there is no intermediate state in the write operation that could cause the
  82. read to loop forever.
  83. */
  84. void JackFrameTimer::ReadFrameTime(JackTimer* timer)
  85. {
  86. UInt16 next_index = GetCurrentIndex();
  87. UInt16 cur_index;
  88. do {
  89. cur_index = next_index;
  90. memcpy(timer, ReadCurrentState(), sizeof(JackTimer));
  91. next_index = GetCurrentIndex();
  92. } while (cur_index != next_index); // Until a coherent state has been read
  93. }
  94. } // end of namespace