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.

209 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. #include <stdio.h>
  21. namespace Jack
  22. {
  23. #define MAX_SIZE 64
  24. struct JackFilter
  25. {
  26. jack_time_t fTable[MAX_SIZE];
  27. JackFilter()
  28. {
  29. for (int i = 0; i < MAX_SIZE; i++)
  30. fTable[i] = 0;
  31. }
  32. void AddValue(jack_time_t val)
  33. {
  34. memcpy(&fTable[1], &fTable[0], sizeof(jack_time_t) * (MAX_SIZE - 1));
  35. fTable[0] = val;
  36. }
  37. jack_time_t GetVal()
  38. {
  39. jack_time_t mean = 0;
  40. for (int i = 0; i < MAX_SIZE; i++)
  41. mean += fTable[i];
  42. return mean / MAX_SIZE;
  43. }
  44. };
  45. class JackDelayLockedLoop
  46. {
  47. private:
  48. jack_nframes_t fFrames;
  49. jack_time_t fCurrentWakeup;
  50. jack_time_t fCurrentCallback;
  51. jack_time_t fNextWakeUp;
  52. float fSecondOrderIntegrator;
  53. jack_nframes_t fBufferSize;
  54. jack_nframes_t fSampleRate;
  55. jack_time_t fPeriodUsecs;
  56. float fFilterCoefficient; /* set once, never altered */
  57. bool fUpdating;
  58. public:
  59. JackDelayLockedLoop()
  60. {}
  61. JackDelayLockedLoop(jack_nframes_t buffer_size, jack_nframes_t sample_rate)
  62. {
  63. Init(buffer_size, sample_rate);
  64. }
  65. void Init(jack_nframes_t buffer_size, jack_nframes_t sample_rate)
  66. {
  67. fFrames = 0;
  68. fCurrentWakeup = 0;
  69. fCurrentCallback = 0;
  70. fNextWakeUp = 0;
  71. fFilterCoefficient = 0.01f;
  72. fSecondOrderIntegrator = 0.0f;
  73. fBufferSize = buffer_size;
  74. fSampleRate = sample_rate;
  75. fPeriodUsecs = jack_time_t(1000000.f / fSampleRate * fBufferSize); // in microsec
  76. }
  77. void Init(jack_time_t callback_usecs)
  78. {
  79. fFrames = 0;
  80. fCurrentWakeup = 0;
  81. fSecondOrderIntegrator = 0.0f;
  82. fCurrentCallback = callback_usecs;
  83. fNextWakeUp = callback_usecs + fPeriodUsecs;
  84. }
  85. void IncFrame(jack_time_t callback_usecs)
  86. {
  87. float delta = (int64_t)callback_usecs - (int64_t)fNextWakeUp;
  88. fCurrentWakeup = fNextWakeUp;
  89. fCurrentCallback = callback_usecs;
  90. fFrames += fBufferSize;
  91. fSecondOrderIntegrator += 0.5f * fFilterCoefficient * delta;
  92. fNextWakeUp = fCurrentWakeup + fPeriodUsecs + (int64_t) floorf((fFilterCoefficient * (delta + fSecondOrderIntegrator)));
  93. }
  94. jack_nframes_t Time2Frames(jack_time_t time)
  95. {
  96. long delta = (long) rint(((double) ((long long)(time - fCurrentWakeup)) / ((long long)(fNextWakeUp - fCurrentWakeup))) * fBufferSize);
  97. return (delta < 0) ? ((fFrames > 0) ? fFrames : 1) : (fFrames + delta);
  98. }
  99. jack_time_t Frames2Time(jack_nframes_t frames)
  100. {
  101. long delta = (long) rint(((double) ((long long)(frames - fFrames)) * ((long long)(fNextWakeUp - fCurrentWakeup))) / fBufferSize);
  102. return (delta < 0) ? ((fCurrentWakeup > 0) ? fCurrentWakeup : 1) : (fCurrentWakeup + delta);
  103. }
  104. jack_nframes_t CurFrame()
  105. {
  106. return fFrames;
  107. }
  108. jack_time_t CurTime()
  109. {
  110. return fCurrentWakeup;
  111. }
  112. };
  113. class JackAtomicDelayLockedLoop : public JackAtomicState<JackDelayLockedLoop>
  114. {
  115. public:
  116. JackAtomicDelayLockedLoop(jack_nframes_t buffer_size, jack_nframes_t sample_rate)
  117. {
  118. fState[0].Init(buffer_size, sample_rate);
  119. fState[1].Init(buffer_size, sample_rate);
  120. }
  121. void Init(jack_time_t callback_usecs)
  122. {
  123. JackDelayLockedLoop* dll = WriteNextStateStart();
  124. dll->Init(callback_usecs);
  125. WriteNextStateStop();
  126. TrySwitchState(); // always succeed since there is only one writer
  127. }
  128. void Init(jack_nframes_t buffer_size, jack_nframes_t sample_rate)
  129. {
  130. JackDelayLockedLoop* dll = WriteNextStateStart();
  131. dll->Init(buffer_size, sample_rate);
  132. WriteNextStateStop();
  133. TrySwitchState(); // always succeed since there is only one writer
  134. }
  135. void IncFrame(jack_time_t callback_usecs)
  136. {
  137. JackDelayLockedLoop* dll = WriteNextStateStart();
  138. dll->IncFrame(callback_usecs);
  139. WriteNextStateStop();
  140. TrySwitchState(); // always succeed since there is only one writer
  141. }
  142. jack_nframes_t Time2Frames(jack_time_t time)
  143. {
  144. UInt16 next_index = GetCurrentIndex();
  145. UInt16 cur_index;
  146. jack_nframes_t res;
  147. do {
  148. cur_index = next_index;
  149. res = ReadCurrentState()->Time2Frames(time);
  150. next_index = GetCurrentIndex();
  151. } while (cur_index != next_index); // Until a coherent state has been read
  152. return res;
  153. }
  154. jack_time_t Frames2Time(jack_nframes_t frames)
  155. {
  156. UInt16 next_index = GetCurrentIndex();
  157. UInt16 cur_index;
  158. jack_time_t res;
  159. do {
  160. cur_index = next_index;
  161. res = ReadCurrentState()->Frames2Time(frames);
  162. next_index = GetCurrentIndex();
  163. } while (cur_index != next_index); // Until a coherent state has been read
  164. return res;
  165. }
  166. };
  167. }
  168. #endif