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.

351 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. }
  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 controller from JACK1
  181. */
  182. struct JackPIControler {
  183. double resample_mean;
  184. double static_resample_factor;
  185. double* offset_array;
  186. double* window_array;
  187. int offset_differential_index;
  188. double offset_integral;
  189. double catch_factor;
  190. double catch_factor2;
  191. double pclamp;
  192. double controlquant;
  193. int smooth_size;
  194. double hann(double x)
  195. {
  196. return 0.5 * (1.0 - cos(2 * M_PI * x));
  197. }
  198. JackPIControler(double resample_factor, int fir_size)
  199. {
  200. resample_mean = resample_factor;
  201. static_resample_factor = resample_factor;
  202. offset_array = new double[fir_size];
  203. window_array = new double[fir_size];
  204. offset_differential_index = 0;
  205. offset_integral = 0.0;
  206. smooth_size = fir_size;
  207. for (int i = 0; i < fir_size; i++) {
  208. offset_array[i] = 0.0;
  209. window_array[i] = hann(double(i) / (double(fir_size) - 1.0));
  210. }
  211. // These values could be configurable
  212. catch_factor = 100000;
  213. catch_factor2 = 10000;
  214. pclamp = 15.0;
  215. controlquant = 10000.0;
  216. }
  217. ~JackPIControler()
  218. {
  219. delete[] offset_array;
  220. delete[] window_array;
  221. }
  222. void Init(double resample_factor)
  223. {
  224. resample_mean = resample_factor;
  225. static_resample_factor = resample_factor;
  226. }
  227. /*
  228. double GetRatio(int fill_level)
  229. {
  230. double offset = fill_level;
  231. // Save offset.
  232. offset_array[(offset_differential_index++) % smooth_size] = offset;
  233. // Build the mean of the windowed offset array basically fir lowpassing.
  234. double smooth_offset = 0.0;
  235. for (int i = 0; i < smooth_size; i++) {
  236. smooth_offset += offset_array[(i + offset_differential_index - 1) % smooth_size] * window_array[i];
  237. }
  238. smooth_offset /= double(smooth_size);
  239. // This is the integral of the smoothed_offset
  240. offset_integral += smooth_offset;
  241. // Clamp offset : the smooth offset still contains unwanted noise which would go straight onto the resample coeff.
  242. // It only used in the P component and the I component is used for the fine tuning anyways.
  243. if (fabs(smooth_offset) < pclamp)
  244. smooth_offset = 0.0;
  245. // Ok, now this is the PI controller.
  246. // u(t) = K * (e(t) + 1/T \int e(t') dt')
  247. // Kp = 1/catch_factor and T = catch_factor2 Ki = Kp/T
  248. double current_resample_factor
  249. = static_resample_factor - smooth_offset / catch_factor - offset_integral / catch_factor / catch_factor2;
  250. // Now quantize this value around resample_mean, so that the noise which is in the integral component doesn't hurt.
  251. current_resample_factor = floor((current_resample_factor - resample_mean) * controlquant + 0.5) / controlquant + resample_mean;
  252. // Calculate resample_mean so we can init ourselves to saner values.
  253. resample_mean = 0.9999 * resample_mean + 0.0001 * current_resample_factor;
  254. return current_resample_factor;
  255. }
  256. */
  257. double GetRatio(int error)
  258. {
  259. double smooth_offset = error;
  260. // This is the integral of the smoothed_offset
  261. offset_integral += smooth_offset;
  262. // Ok, now this is the PI controller.
  263. // u(t) = K * (e(t) + 1/T \int e(t') dt')
  264. // Kp = 1/catch_factor and T = catch_factor2 Ki = Kp/T
  265. return static_resample_factor - smooth_offset/catch_factor - offset_integral/catch_factor/catch_factor2;
  266. }
  267. void OurOfBounds()
  268. {
  269. int i;
  270. // Set the resample_rate... we need to adjust the offset integral, to do this.
  271. // first look at the PI controller, this code is just a special case, which should never execute once
  272. // everything is swung in.
  273. offset_integral = - (resample_mean - static_resample_factor) * catch_factor * catch_factor2;
  274. // Also clear the array. we are beginning a new control cycle.
  275. for (i = 0; i < smooth_size; i++) {
  276. offset_array[i] = 0.0;
  277. }
  278. }
  279. };
  280. }
  281. #endif