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.

345 lines
12KB

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