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.

279 lines
8.2KB

  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. #ifdef __APPLE__
  18. #include <TargetConditionals.h>
  19. #endif
  20. #include "jack.h"
  21. #ifndef MY_TARGET_OS_IPHONE
  22. #include "JackAtomicState.h"
  23. #endif
  24. #include <math.h>
  25. #include <stdlib.h>
  26. namespace Jack
  27. {
  28. #ifndef TARGET_OS_IPHONE
  29. #define MAX_SIZE 64
  30. PRE_PACKED_STRUCTURE
  31. struct JackFilter
  32. {
  33. jack_time_t fTable[MAX_SIZE];
  34. JackFilter()
  35. {
  36. for (int i = 0; i < MAX_SIZE; i++) {
  37. fTable[i] = 0;
  38. }
  39. }
  40. void AddValue(jack_time_t val)
  41. {
  42. memcpy(&fTable[1], &fTable[0], sizeof(jack_time_t) * (MAX_SIZE - 1));
  43. fTable[0] = val;
  44. }
  45. jack_time_t GetVal()
  46. {
  47. jack_time_t mean = 0;
  48. for (int i = 0; i < MAX_SIZE; i++) {
  49. mean += fTable[i];
  50. }
  51. return mean / MAX_SIZE;
  52. }
  53. } POST_PACKED_STRUCTURE;
  54. PRE_PACKED_STRUCTURE
  55. class JackDelayLockedLoop
  56. {
  57. private:
  58. jack_nframes_t fFrames;
  59. jack_time_t fCurrentWakeup;
  60. jack_time_t fCurrentCallback;
  61. jack_time_t fNextWakeUp;
  62. float fSecondOrderIntegrator;
  63. jack_nframes_t fBufferSize;
  64. jack_nframes_t fSampleRate;
  65. jack_time_t fPeriodUsecs;
  66. float fFilterCoefficient; /* set once, never altered */
  67. bool fUpdating;
  68. public:
  69. JackDelayLockedLoop()
  70. {}
  71. JackDelayLockedLoop(jack_nframes_t buffer_size, jack_nframes_t sample_rate)
  72. {
  73. Init(buffer_size, sample_rate);
  74. }
  75. void Init(jack_nframes_t buffer_size, jack_nframes_t sample_rate)
  76. {
  77. fFrames = 0;
  78. fCurrentWakeup = 0;
  79. fCurrentCallback = 0;
  80. fNextWakeUp = 0;
  81. fFilterCoefficient = 0.01f;
  82. fSecondOrderIntegrator = 0.0f;
  83. fBufferSize = buffer_size;
  84. fSampleRate = sample_rate;
  85. fPeriodUsecs = jack_time_t(1000000.f / fSampleRate * fBufferSize); // in microsec
  86. }
  87. void Init(jack_time_t callback_usecs)
  88. {
  89. fFrames = 0;
  90. fCurrentWakeup = 0;
  91. fSecondOrderIntegrator = 0.0f;
  92. fCurrentCallback = callback_usecs;
  93. fNextWakeUp = callback_usecs + fPeriodUsecs;
  94. }
  95. void IncFrame(jack_time_t callback_usecs)
  96. {
  97. float delta = (int64_t)callback_usecs - (int64_t)fNextWakeUp;
  98. fCurrentWakeup = fNextWakeUp;
  99. fCurrentCallback = callback_usecs;
  100. fFrames += fBufferSize;
  101. fSecondOrderIntegrator += 0.5f * fFilterCoefficient * delta;
  102. fNextWakeUp = fCurrentWakeup + fPeriodUsecs + (int64_t) floorf((fFilterCoefficient * (delta + fSecondOrderIntegrator)));
  103. }
  104. jack_nframes_t Time2Frames(jack_time_t time)
  105. {
  106. long delta = (long) rint(((double) ((long long)(time - fCurrentWakeup)) / ((long long)(fNextWakeUp - fCurrentWakeup))) * fBufferSize);
  107. return (delta < 0) ? ((fFrames > 0) ? fFrames : 1) : (fFrames + delta);
  108. }
  109. jack_time_t Frames2Time(jack_nframes_t frames)
  110. {
  111. long delta = (long) rint(((double) ((long long)(frames - fFrames)) * ((long long)(fNextWakeUp - fCurrentWakeup))) / fBufferSize);
  112. return (delta < 0) ? ((fCurrentWakeup > 0) ? fCurrentWakeup : 1) : (fCurrentWakeup + delta);
  113. }
  114. jack_nframes_t CurFrame()
  115. {
  116. return fFrames;
  117. }
  118. jack_time_t CurTime()
  119. {
  120. return fCurrentWakeup;
  121. }
  122. } POST_PACKED_STRUCTURE;
  123. PRE_PACKED_STRUCTURE
  124. class JackAtomicDelayLockedLoop : public JackAtomicState<JackDelayLockedLoop>
  125. {
  126. public:
  127. JackAtomicDelayLockedLoop(jack_nframes_t buffer_size, jack_nframes_t sample_rate)
  128. {
  129. fState[0].Init(buffer_size, sample_rate);
  130. fState[1].Init(buffer_size, sample_rate);
  131. }
  132. void Init(jack_time_t callback_usecs)
  133. {
  134. JackDelayLockedLoop* dll = WriteNextStateStart();
  135. dll->Init(callback_usecs);
  136. WriteNextStateStop();
  137. TrySwitchState(); // always succeed since there is only one writer
  138. }
  139. void Init(jack_nframes_t buffer_size, jack_nframes_t sample_rate)
  140. {
  141. JackDelayLockedLoop* dll = WriteNextStateStart();
  142. dll->Init(buffer_size, sample_rate);
  143. WriteNextStateStop();
  144. TrySwitchState(); // always succeed since there is only one writer
  145. }
  146. void IncFrame(jack_time_t callback_usecs)
  147. {
  148. JackDelayLockedLoop* dll = WriteNextStateStart();
  149. dll->IncFrame(callback_usecs);
  150. WriteNextStateStop();
  151. TrySwitchState(); // always succeed since there is only one writer
  152. }
  153. jack_nframes_t Time2Frames(jack_time_t time)
  154. {
  155. UInt16 next_index = GetCurrentIndex();
  156. UInt16 cur_index;
  157. jack_nframes_t res;
  158. do {
  159. cur_index = next_index;
  160. res = ReadCurrentState()->Time2Frames(time);
  161. next_index = GetCurrentIndex();
  162. } while (cur_index != next_index); // Until a coherent state has been read
  163. return res;
  164. }
  165. jack_time_t Frames2Time(jack_nframes_t frames)
  166. {
  167. UInt16 next_index = GetCurrentIndex();
  168. UInt16 cur_index;
  169. jack_time_t res;
  170. do {
  171. cur_index = next_index;
  172. res = ReadCurrentState()->Frames2Time(frames);
  173. next_index = GetCurrentIndex();
  174. } while (cur_index != next_index); // Until a coherent state has been read
  175. return res;
  176. }
  177. } POST_PACKED_STRUCTURE;
  178. #endif
  179. /*
  180. Torben Hohn PI controler from JACK1
  181. */
  182. struct JackPIController {
  183. double static_resample_factor;
  184. double offset_integral;
  185. double catch_factor;
  186. double catch_factor2;
  187. double hann(double x)
  188. {
  189. return 0.5 * (1.0 - cos(2 * M_PI * x));
  190. }
  191. JackPIController(double resample_factor)
  192. {
  193. static_resample_factor = resample_factor;
  194. offset_integral = 0.0;
  195. // These values could be configurable
  196. catch_factor = 100000;
  197. catch_factor2 = 10000;
  198. }
  199. ~JackPIController()
  200. {
  201. }
  202. void Init(double resample_factor)
  203. {
  204. static_resample_factor = resample_factor;
  205. }
  206. void Reset()
  207. {
  208. offset_integral = 0.0;
  209. }
  210. double GetRatio(int error)
  211. {
  212. double smooth_offset = error;
  213. // This is the integral of the smoothed_offset
  214. offset_integral += smooth_offset;
  215. // Ok, now this is the PI controller.
  216. // u(t) = K * (e(t) + 1/T \int e(t') dt')
  217. // Kp = 1/catch_factor and T = catch_factor2 Ki = Kp/T
  218. return static_resample_factor - smooth_offset/catch_factor - offset_integral/catch_factor/catch_factor2;
  219. }
  220. };
  221. }
  222. #endif