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.

204 lines
6.4KB

  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. return fFrames + (long) rint(((double) (long(time - fCurrentWakeup)) / ((jack_time_t)(fNextWakeUp - fCurrentWakeup))) * fBufferSize);
  97. }
  98. jack_time_t Frames2Time(jack_nframes_t frames)
  99. {
  100. return fCurrentWakeup + (long) rint(((double) (long(frames - fFrames)) * ((jack_time_t)(fNextWakeUp - fCurrentWakeup))) / fBufferSize);
  101. }
  102. jack_time_t CurFrame2Time()
  103. {
  104. return fCurrentWakeup;
  105. }
  106. jack_nframes_t CurTime2Frame()
  107. {
  108. return fFrames;
  109. }
  110. };
  111. class JackAtomicDelayLockedLoop : public JackAtomicState<JackDelayLockedLoop>
  112. {
  113. public:
  114. JackAtomicDelayLockedLoop(jack_nframes_t buffer_size, jack_nframes_t sample_rate)
  115. {
  116. fState[0].Init(buffer_size, sample_rate);
  117. fState[1].Init(buffer_size, sample_rate);
  118. }
  119. void Init(jack_time_t callback_usecs)
  120. {
  121. JackDelayLockedLoop* dll = WriteNextStateStart();
  122. dll->Init(callback_usecs);
  123. WriteNextStateStop();
  124. TrySwitchState(); // always succeed since there is only one writer
  125. }
  126. void IncFrame(jack_time_t callback_usecs)
  127. {
  128. JackDelayLockedLoop* dll = WriteNextStateStart();
  129. dll->IncFrame(callback_usecs);
  130. WriteNextStateStop();
  131. TrySwitchState(); // always succeed since there is only one writer
  132. }
  133. jack_nframes_t Time2Frames(jack_time_t time)
  134. {
  135. UInt16 next_index = GetCurrentIndex();
  136. UInt16 cur_index;
  137. jack_nframes_t res;
  138. do {
  139. cur_index = next_index;
  140. res = ReadCurrentState()->Time2Frames(time);
  141. next_index = GetCurrentIndex();
  142. } while (cur_index != next_index); // Until a coherent state has been read
  143. return res;
  144. }
  145. jack_time_t Frames2Time(jack_nframes_t frames)
  146. {
  147. UInt16 next_index = GetCurrentIndex();
  148. UInt16 cur_index;
  149. jack_time_t res;
  150. do {
  151. cur_index = next_index;
  152. res = ReadCurrentState()->Frames2Time(frames);
  153. next_index = GetCurrentIndex();
  154. } while (cur_index != next_index); // Until a coherent state has been read
  155. return res;
  156. }
  157. };
  158. inline float Range(float min, float max, float val)
  159. {
  160. return (val < min) ? min : ((val > max) ? max : val);
  161. }
  162. }
  163. #endif