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.

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