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.

349 lines
11KB

  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. void AddValue(jack_time_t val)
  40. {
  41. memcpy(&fTable[1], &fTable[0], sizeof(jack_time_t) * (MAX_SIZE - 1));
  42. fTable[0] = val;
  43. }
  44. jack_time_t GetVal()
  45. {
  46. jack_time_t mean = 0;
  47. for (int i = 0; i < MAX_SIZE; i++)
  48. mean += fTable[i];
  49. return mean / MAX_SIZE;
  50. }
  51. } POST_PACKED_STRUCTURE;
  52. PRE_PACKED_STRUCTURE
  53. class JackDelayLockedLoop
  54. {
  55. private:
  56. jack_nframes_t fFrames;
  57. jack_time_t fCurrentWakeup;
  58. jack_time_t fCurrentCallback;
  59. jack_time_t fNextWakeUp;
  60. float fSecondOrderIntegrator;
  61. jack_nframes_t fBufferSize;
  62. jack_nframes_t fSampleRate;
  63. jack_time_t fPeriodUsecs;
  64. float fFilterCoefficient; /* set once, never altered */
  65. bool fUpdating;
  66. public:
  67. JackDelayLockedLoop()
  68. {}
  69. JackDelayLockedLoop(jack_nframes_t buffer_size, jack_nframes_t sample_rate)
  70. {
  71. Init(buffer_size, sample_rate);
  72. }
  73. void Init(jack_nframes_t buffer_size, jack_nframes_t sample_rate)
  74. {
  75. fFrames = 0;
  76. fCurrentWakeup = 0;
  77. fCurrentCallback = 0;
  78. fNextWakeUp = 0;
  79. fFilterCoefficient = 0.01f;
  80. fSecondOrderIntegrator = 0.0f;
  81. fBufferSize = buffer_size;
  82. fSampleRate = sample_rate;
  83. fPeriodUsecs = jack_time_t(1000000.f / fSampleRate * fBufferSize); // in microsec
  84. }
  85. void Init(jack_time_t callback_usecs)
  86. {
  87. fFrames = 0;
  88. fCurrentWakeup = 0;
  89. fSecondOrderIntegrator = 0.0f;
  90. fCurrentCallback = callback_usecs;
  91. fNextWakeUp = callback_usecs + fPeriodUsecs;
  92. }
  93. void IncFrame(jack_time_t callback_usecs)
  94. {
  95. float delta = (int64_t)callback_usecs - (int64_t)fNextWakeUp;
  96. fCurrentWakeup = fNextWakeUp;
  97. fCurrentCallback = callback_usecs;
  98. fFrames += fBufferSize;
  99. fSecondOrderIntegrator += 0.5f * fFilterCoefficient * delta;
  100. fNextWakeUp = fCurrentWakeup + fPeriodUsecs + (int64_t) floorf((fFilterCoefficient * (delta + fSecondOrderIntegrator)));
  101. }
  102. jack_nframes_t Time2Frames(jack_time_t time)
  103. {
  104. long delta = (long) rint(((double) ((long long)(time - fCurrentWakeup)) / ((long long)(fNextWakeUp - fCurrentWakeup))) * fBufferSize);
  105. return (delta < 0) ? ((fFrames > 0) ? fFrames : 1) : (fFrames + delta);
  106. }
  107. jack_time_t Frames2Time(jack_nframes_t frames)
  108. {
  109. long delta = (long) rint(((double) ((long long)(frames - fFrames)) * ((long long)(fNextWakeUp - fCurrentWakeup))) / fBufferSize);
  110. return (delta < 0) ? ((fCurrentWakeup > 0) ? fCurrentWakeup : 1) : (fCurrentWakeup + delta);
  111. }
  112. jack_nframes_t CurFrame()
  113. {
  114. return fFrames;
  115. }
  116. jack_time_t CurTime()
  117. {
  118. return fCurrentWakeup;
  119. }
  120. } POST_PACKED_STRUCTURE;
  121. PRE_PACKED_STRUCTURE
  122. class JackAtomicDelayLockedLoop : public JackAtomicState<JackDelayLockedLoop>
  123. {
  124. public:
  125. JackAtomicDelayLockedLoop(jack_nframes_t buffer_size, jack_nframes_t sample_rate)
  126. {
  127. fState[0].Init(buffer_size, sample_rate);
  128. fState[1].Init(buffer_size, sample_rate);
  129. }
  130. void Init(jack_time_t callback_usecs)
  131. {
  132. JackDelayLockedLoop* dll = WriteNextStateStart();
  133. dll->Init(callback_usecs);
  134. WriteNextStateStop();
  135. TrySwitchState(); // always succeed since there is only one writer
  136. }
  137. void Init(jack_nframes_t buffer_size, jack_nframes_t sample_rate)
  138. {
  139. JackDelayLockedLoop* dll = WriteNextStateStart();
  140. dll->Init(buffer_size, sample_rate);
  141. WriteNextStateStop();
  142. TrySwitchState(); // always succeed since there is only one writer
  143. }
  144. void IncFrame(jack_time_t callback_usecs)
  145. {
  146. JackDelayLockedLoop* dll = WriteNextStateStart();
  147. dll->IncFrame(callback_usecs);
  148. WriteNextStateStop();
  149. TrySwitchState(); // always succeed since there is only one writer
  150. }
  151. jack_nframes_t Time2Frames(jack_time_t time)
  152. {
  153. UInt16 next_index = GetCurrentIndex();
  154. UInt16 cur_index;
  155. jack_nframes_t res;
  156. do {
  157. cur_index = next_index;
  158. res = ReadCurrentState()->Time2Frames(time);
  159. next_index = GetCurrentIndex();
  160. } while (cur_index != next_index); // Until a coherent state has been read
  161. return res;
  162. }
  163. jack_time_t Frames2Time(jack_nframes_t frames)
  164. {
  165. UInt16 next_index = GetCurrentIndex();
  166. UInt16 cur_index;
  167. jack_time_t res;
  168. do {
  169. cur_index = next_index;
  170. res = ReadCurrentState()->Frames2Time(frames);
  171. next_index = GetCurrentIndex();
  172. } while (cur_index != next_index); // Until a coherent state has been read
  173. return res;
  174. }
  175. } POST_PACKED_STRUCTURE;
  176. #endif
  177. /*
  178. Torben Hohn PI controler from JACK1
  179. */
  180. struct JackPIControler {
  181. double resample_mean;
  182. double static_resample_factor;
  183. double* offset_array;
  184. double* window_array;
  185. int offset_differential_index;
  186. double offset_integral;
  187. double catch_factor;
  188. double catch_factor2;
  189. double pclamp;
  190. double controlquant;
  191. int smooth_size;
  192. double hann(double x)
  193. {
  194. return 0.5 * (1.0 - cos(2 * M_PI * x));
  195. }
  196. JackPIControler(double resample_factor, int fir_size)
  197. {
  198. resample_mean = resample_factor;
  199. static_resample_factor = resample_factor;
  200. offset_array = new double[fir_size];
  201. window_array = new double[fir_size];
  202. offset_differential_index = 0;
  203. offset_integral = 0.0;
  204. smooth_size = fir_size;
  205. for (int i = 0; i < fir_size; i++) {
  206. offset_array[i] = 0.0;
  207. window_array[i] = hann(double(i) / (double(fir_size) - 1.0));
  208. }
  209. // These values could be configurable
  210. catch_factor = 100000;
  211. catch_factor2 = 10000;
  212. pclamp = 15.0;
  213. controlquant = 10000.0;
  214. }
  215. ~JackPIControler()
  216. {
  217. delete[] offset_array;
  218. delete[] window_array;
  219. }
  220. void Init(double resample_factor)
  221. {
  222. resample_mean = resample_factor;
  223. static_resample_factor = resample_factor;
  224. }
  225. /*
  226. double GetRatio(int fill_level)
  227. {
  228. double offset = fill_level;
  229. // Save offset.
  230. offset_array[(offset_differential_index++) % smooth_size] = offset;
  231. // Build the mean of the windowed offset array basically fir lowpassing.
  232. double smooth_offset = 0.0;
  233. for (int i = 0; i < smooth_size; i++) {
  234. smooth_offset += offset_array[(i + offset_differential_index - 1) % smooth_size] * window_array[i];
  235. }
  236. smooth_offset /= double(smooth_size);
  237. // This is the integral of the smoothed_offset
  238. offset_integral += smooth_offset;
  239. // Clamp offset : the smooth offset still contains unwanted noise which would go straigth onto the resample coeff.
  240. // It only used in the P component and the I component is used for the fine tuning anyways.
  241. if (fabs(smooth_offset) < pclamp)
  242. smooth_offset = 0.0;
  243. // Ok, now this is the PI controller.
  244. // u(t) = K * (e(t) + 1/T \int e(t') dt')
  245. // Kp = 1/catch_factor and T = catch_factor2 Ki = Kp/T
  246. double current_resample_factor
  247. = static_resample_factor - smooth_offset / catch_factor - offset_integral / catch_factor / catch_factor2;
  248. // Now quantize this value around resample_mean, so that the noise which is in the integral component doesnt hurt.
  249. current_resample_factor = floor((current_resample_factor - resample_mean) * controlquant + 0.5) / controlquant + resample_mean;
  250. // Calculate resample_mean so we can init ourselves to saner values.
  251. resample_mean = 0.9999 * resample_mean + 0.0001 * current_resample_factor;
  252. return current_resample_factor;
  253. }
  254. */
  255. double GetRatio(int error)
  256. {
  257. double smooth_offset = error;
  258. // This is the integral of the smoothed_offset
  259. offset_integral += smooth_offset;
  260. // Ok, now this is the PI controller.
  261. // u(t) = K * (e(t) + 1/T \int e(t') dt')
  262. // Kp = 1/catch_factor and T = catch_factor2 Ki = Kp/T
  263. return static_resample_factor - smooth_offset/catch_factor - offset_integral/catch_factor/catch_factor2;
  264. }
  265. void OurOfBounds()
  266. {
  267. int i;
  268. // Set the resample_rate... we need to adjust the offset integral, to do this.
  269. // first look at the PI controller, this code is just a special case, which should never execute once
  270. // everything is swung in.
  271. offset_integral = - (resample_mean - static_resample_factor) * catch_factor * catch_factor2;
  272. // Also clear the array. we are beginning a new control cycle.
  273. for (i = 0; i < smooth_size; i++) {
  274. offset_array[i] = 0.0;
  275. }
  276. }
  277. };
  278. }
  279. #endif