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.

208 lines
6.8KB

  1. /*
  2. Copyright (C) 2008 Grame
  3. This program is free software; you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation; either version 2 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  14. */
  15. #ifndef __JackFilters__
  16. #define __JackFilters__
  17. #include "jack.h"
  18. #include "JackAtomicState.h"
  19. #include <math.h>
  20. namespace Jack
  21. {
  22. #define MAX_SIZE 64
  23. struct JackFilter
  24. {
  25. jack_time_t fTable[MAX_SIZE];
  26. JackFilter()
  27. {
  28. for (int i = 0; i < MAX_SIZE; i++)
  29. fTable[i] = 0;
  30. }
  31. void AddValue(jack_time_t val)
  32. {
  33. memcpy(&fTable[1], &fTable[0], sizeof(jack_time_t) * (MAX_SIZE - 1));
  34. fTable[0] = val;
  35. }
  36. jack_time_t GetVal()
  37. {
  38. jack_time_t mean = 0;
  39. for (int i = 0; i < MAX_SIZE; i++)
  40. mean += fTable[i];
  41. return mean / MAX_SIZE;
  42. }
  43. };
  44. class JackDelayLockedLoop
  45. {
  46. private:
  47. jack_nframes_t fFrames;
  48. jack_time_t fCurrentWakeup;
  49. jack_time_t fCurrentCallback;
  50. jack_time_t fNextWakeUp;
  51. float fSecondOrderIntegrator;
  52. jack_nframes_t fBufferSize;
  53. jack_nframes_t fSampleRate;
  54. jack_time_t fPeriodUsecs;
  55. float fFilterCoefficient; /* set once, never altered */
  56. bool fUpdating;
  57. public:
  58. JackDelayLockedLoop()
  59. {}
  60. JackDelayLockedLoop(jack_nframes_t buffer_size, jack_nframes_t sample_rate)
  61. {
  62. Init(buffer_size, sample_rate);
  63. }
  64. void Init(jack_nframes_t buffer_size, jack_nframes_t sample_rate)
  65. {
  66. fFrames = 0;
  67. fCurrentWakeup = 0;
  68. fCurrentCallback = 0;
  69. fNextWakeUp = 0;
  70. fFilterCoefficient = 0.01f;
  71. fSecondOrderIntegrator = 0.0f;
  72. fBufferSize = buffer_size;
  73. fSampleRate = sample_rate;
  74. fPeriodUsecs = jack_time_t(1000000.f / fSampleRate * fBufferSize); // in microsec
  75. }
  76. void Init(jack_time_t callback_usecs)
  77. {
  78. fFrames = 0;
  79. fCurrentWakeup = 0;
  80. fSecondOrderIntegrator = 0.0f;
  81. fCurrentCallback = callback_usecs;
  82. fNextWakeUp = callback_usecs + fPeriodUsecs;
  83. }
  84. void IncFrame(jack_time_t callback_usecs)
  85. {
  86. float delta = (int64_t)callback_usecs - (int64_t)fNextWakeUp;
  87. fCurrentWakeup = fNextWakeUp;
  88. fCurrentCallback = callback_usecs;
  89. fFrames += fBufferSize;
  90. fSecondOrderIntegrator += 0.5f * fFilterCoefficient * delta;
  91. fNextWakeUp = fCurrentWakeup + fPeriodUsecs + (int64_t) floorf((fFilterCoefficient * (delta + fSecondOrderIntegrator)));
  92. }
  93. jack_nframes_t Time2Frames(jack_time_t time)
  94. {
  95. long delta = (long) rint(((double) ((long long)(time - fCurrentWakeup)) / ((long long)(fNextWakeUp - fCurrentWakeup))) * fBufferSize);
  96. return (delta < 0) ? ((fFrames > 0) ? fFrames : 1) : (fFrames + delta);
  97. }
  98. jack_time_t Frames2Time(jack_nframes_t frames)
  99. {
  100. long delta = (long) rint(((double) ((long long)(frames - fFrames)) * ((long long)(fNextWakeUp - fCurrentWakeup))) / fBufferSize);
  101. return (delta < 0) ? ((fCurrentWakeup > 0) ? fCurrentWakeup : 1) : (fCurrentWakeup + delta);
  102. }
  103. jack_nframes_t CurFrame()
  104. {
  105. return fFrames;
  106. }
  107. jack_time_t CurTime()
  108. {
  109. return fCurrentWakeup;
  110. }
  111. };
  112. class JackAtomicDelayLockedLoop : public JackAtomicState<JackDelayLockedLoop>
  113. {
  114. public:
  115. JackAtomicDelayLockedLoop(jack_nframes_t buffer_size, jack_nframes_t sample_rate)
  116. {
  117. fState[0].Init(buffer_size, sample_rate);
  118. fState[1].Init(buffer_size, sample_rate);
  119. }
  120. void Init(jack_time_t callback_usecs)
  121. {
  122. JackDelayLockedLoop* dll = WriteNextStateStart();
  123. dll->Init(callback_usecs);
  124. WriteNextStateStop();
  125. TrySwitchState(); // always succeed since there is only one writer
  126. }
  127. void Init(jack_nframes_t buffer_size, jack_nframes_t sample_rate)
  128. {
  129. JackDelayLockedLoop* dll = WriteNextStateStart();
  130. dll->Init(buffer_size, sample_rate);
  131. WriteNextStateStop();
  132. TrySwitchState(); // always succeed since there is only one writer
  133. }
  134. void IncFrame(jack_time_t callback_usecs)
  135. {
  136. JackDelayLockedLoop* dll = WriteNextStateStart();
  137. dll->IncFrame(callback_usecs);
  138. WriteNextStateStop();
  139. TrySwitchState(); // always succeed since there is only one writer
  140. }
  141. jack_nframes_t Time2Frames(jack_time_t time)
  142. {
  143. UInt16 next_index = GetCurrentIndex();
  144. UInt16 cur_index;
  145. jack_nframes_t res;
  146. do {
  147. cur_index = next_index;
  148. res = ReadCurrentState()->Time2Frames(time);
  149. next_index = GetCurrentIndex();
  150. } while (cur_index != next_index); // Until a coherent state has been read
  151. return res;
  152. }
  153. jack_time_t Frames2Time(jack_nframes_t frames)
  154. {
  155. UInt16 next_index = GetCurrentIndex();
  156. UInt16 cur_index;
  157. jack_time_t res;
  158. do {
  159. cur_index = next_index;
  160. res = ReadCurrentState()->Frames2Time(frames);
  161. next_index = GetCurrentIndex();
  162. } while (cur_index != next_index); // Until a coherent state has been read
  163. return res;
  164. }
  165. };
  166. }
  167. #endif