Jack2 1.9.6
|
00001 /* 00002 Copyright (C) 2008 Grame 00003 00004 This program is free software; you can redistribute it and/or modify 00005 it under the terms of the GNU General Public License as published by 00006 the Free Software Foundation; either version 2 of the License, or 00007 (at your option) any later version. 00008 00009 This program is distributed in the hope that it will be useful, 00010 but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 GNU General Public License for more details. 00013 00014 You should have received a copy of the GNU General Public License 00015 along with this program; if not, write to the Free Software 00016 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00017 00018 */ 00019 00020 #ifndef __JackFilters__ 00021 #define __JackFilters__ 00022 00023 #include "jack.h" 00024 #include "JackAtomicState.h" 00025 #include <math.h> 00026 #include <stdlib.h> 00027 00028 namespace Jack 00029 { 00030 00031 #define MAX_SIZE 64 00032 00033 struct JackFilter 00034 { 00035 00036 jack_time_t fTable[MAX_SIZE]; 00037 00038 JackFilter() 00039 { 00040 for (int i = 0; i < MAX_SIZE; i++) 00041 fTable[i] = 0; 00042 } 00043 00044 void AddValue(jack_time_t val) 00045 { 00046 memcpy(&fTable[1], &fTable[0], sizeof(jack_time_t) * (MAX_SIZE - 1)); 00047 fTable[0] = val; 00048 } 00049 00050 jack_time_t GetVal() 00051 { 00052 jack_time_t mean = 0; 00053 for (int i = 0; i < MAX_SIZE; i++) 00054 mean += fTable[i]; 00055 return mean / MAX_SIZE; 00056 } 00057 00058 } POST_PACKED_STRUCTURE; 00059 00060 class JackDelayLockedLoop 00061 { 00062 00063 private: 00064 00065 jack_nframes_t fFrames; 00066 jack_time_t fCurrentWakeup; 00067 jack_time_t fCurrentCallback; 00068 jack_time_t fNextWakeUp; 00069 float fSecondOrderIntegrator; 00070 jack_nframes_t fBufferSize; 00071 jack_nframes_t fSampleRate; 00072 jack_time_t fPeriodUsecs; 00073 float fFilterCoefficient; /* set once, never altered */ 00074 bool fUpdating; 00075 00076 public: 00077 00078 JackDelayLockedLoop() 00079 {} 00080 00081 JackDelayLockedLoop(jack_nframes_t buffer_size, jack_nframes_t sample_rate) 00082 { 00083 Init(buffer_size, sample_rate); 00084 } 00085 00086 void Init(jack_nframes_t buffer_size, jack_nframes_t sample_rate) 00087 { 00088 fFrames = 0; 00089 fCurrentWakeup = 0; 00090 fCurrentCallback = 0; 00091 fNextWakeUp = 0; 00092 fFilterCoefficient = 0.01f; 00093 fSecondOrderIntegrator = 0.0f; 00094 fBufferSize = buffer_size; 00095 fSampleRate = sample_rate; 00096 fPeriodUsecs = jack_time_t(1000000.f / fSampleRate * fBufferSize); // in microsec 00097 } 00098 00099 void Init(jack_time_t callback_usecs) 00100 { 00101 fFrames = 0; 00102 fCurrentWakeup = 0; 00103 fSecondOrderIntegrator = 0.0f; 00104 fCurrentCallback = callback_usecs; 00105 fNextWakeUp = callback_usecs + fPeriodUsecs; 00106 } 00107 00108 void IncFrame(jack_time_t callback_usecs) 00109 { 00110 float delta = (int64_t)callback_usecs - (int64_t)fNextWakeUp; 00111 fCurrentWakeup = fNextWakeUp; 00112 fCurrentCallback = callback_usecs; 00113 fFrames += fBufferSize; 00114 fSecondOrderIntegrator += 0.5f * fFilterCoefficient * delta; 00115 fNextWakeUp = fCurrentWakeup + fPeriodUsecs + (int64_t) floorf((fFilterCoefficient * (delta + fSecondOrderIntegrator))); 00116 } 00117 00118 jack_nframes_t Time2Frames(jack_time_t time) 00119 { 00120 long delta = (long) rint(((double) ((long long)(time - fCurrentWakeup)) / ((long long)(fNextWakeUp - fCurrentWakeup))) * fBufferSize); 00121 return (delta < 0) ? ((fFrames > 0) ? fFrames : 1) : (fFrames + delta); 00122 } 00123 00124 jack_time_t Frames2Time(jack_nframes_t frames) 00125 { 00126 long delta = (long) rint(((double) ((long long)(frames - fFrames)) * ((long long)(fNextWakeUp - fCurrentWakeup))) / fBufferSize); 00127 return (delta < 0) ? ((fCurrentWakeup > 0) ? fCurrentWakeup : 1) : (fCurrentWakeup + delta); 00128 } 00129 00130 jack_nframes_t CurFrame() 00131 { 00132 return fFrames; 00133 } 00134 00135 jack_time_t CurTime() 00136 { 00137 return fCurrentWakeup; 00138 } 00139 00140 } POST_PACKED_STRUCTURE; 00141 00142 class JackAtomicDelayLockedLoop : public JackAtomicState<JackDelayLockedLoop> 00143 { 00144 public: 00145 00146 JackAtomicDelayLockedLoop(jack_nframes_t buffer_size, jack_nframes_t sample_rate) 00147 { 00148 fState[0].Init(buffer_size, sample_rate); 00149 fState[1].Init(buffer_size, sample_rate); 00150 } 00151 00152 void Init(jack_time_t callback_usecs) 00153 { 00154 JackDelayLockedLoop* dll = WriteNextStateStart(); 00155 dll->Init(callback_usecs); 00156 WriteNextStateStop(); 00157 TrySwitchState(); // always succeed since there is only one writer 00158 } 00159 00160 void Init(jack_nframes_t buffer_size, jack_nframes_t sample_rate) 00161 { 00162 JackDelayLockedLoop* dll = WriteNextStateStart(); 00163 dll->Init(buffer_size, sample_rate); 00164 WriteNextStateStop(); 00165 TrySwitchState(); // always succeed since there is only one writer 00166 } 00167 00168 void IncFrame(jack_time_t callback_usecs) 00169 { 00170 JackDelayLockedLoop* dll = WriteNextStateStart(); 00171 dll->IncFrame(callback_usecs); 00172 WriteNextStateStop(); 00173 TrySwitchState(); // always succeed since there is only one writer 00174 } 00175 00176 jack_nframes_t Time2Frames(jack_time_t time) 00177 { 00178 UInt16 next_index = GetCurrentIndex(); 00179 UInt16 cur_index; 00180 jack_nframes_t res; 00181 00182 do { 00183 cur_index = next_index; 00184 res = ReadCurrentState()->Time2Frames(time); 00185 next_index = GetCurrentIndex(); 00186 } while (cur_index != next_index); // Until a coherent state has been read 00187 00188 return res; 00189 } 00190 00191 jack_time_t Frames2Time(jack_nframes_t frames) 00192 { 00193 UInt16 next_index = GetCurrentIndex(); 00194 UInt16 cur_index; 00195 jack_time_t res; 00196 00197 do { 00198 cur_index = next_index; 00199 res = ReadCurrentState()->Frames2Time(frames); 00200 next_index = GetCurrentIndex(); 00201 } while (cur_index != next_index); // Until a coherent state has been read 00202 00203 return res; 00204 } 00205 } POST_PACKED_STRUCTURE; 00206 00207 /* 00208 Torben Hohn PI controler from JACK1 00209 */ 00210 00211 struct JackPIControler { 00212 00213 double resample_mean; 00214 double static_resample_factor; 00215 00216 double* offset_array; 00217 double* window_array; 00218 int offset_differential_index; 00219 00220 double offset_integral; 00221 00222 double catch_factor; 00223 double catch_factor2; 00224 double pclamp; 00225 double controlquant; 00226 int smooth_size; 00227 00228 double hann(double x) 00229 { 00230 return 0.5 * (1.0 - cos(2 * M_PI * x)); 00231 } 00232 00233 JackPIControler(double resample_factor, int fir_size) 00234 { 00235 resample_mean = resample_factor; 00236 static_resample_factor = resample_factor; 00237 offset_array = new double[fir_size]; 00238 window_array = new double[fir_size]; 00239 offset_differential_index = 0; 00240 offset_integral = 0.0; 00241 smooth_size = fir_size; 00242 00243 for (int i = 0; i < fir_size; i++) { 00244 offset_array[i] = 0.0; 00245 window_array[i] = hann(double(i) / (double(fir_size) - 1.0)); 00246 } 00247 00248 // These values could be configurable 00249 catch_factor = 100000; 00250 catch_factor2 = 10000; 00251 pclamp = 15.0; 00252 controlquant = 10000.0; 00253 } 00254 00255 ~JackPIControler() 00256 { 00257 delete[] offset_array; 00258 delete[] window_array; 00259 } 00260 00261 void Init(double resample_factor) 00262 { 00263 resample_mean = resample_factor; 00264 static_resample_factor = resample_factor; 00265 } 00266 00267 /* 00268 double GetRatio(int fill_level) 00269 { 00270 double offset = fill_level; 00271 00272 // Save offset. 00273 offset_array[(offset_differential_index++) % smooth_size] = offset; 00274 00275 // Build the mean of the windowed offset array basically fir lowpassing. 00276 double smooth_offset = 0.0; 00277 for (int i = 0; i < smooth_size; i++) { 00278 smooth_offset += offset_array[(i + offset_differential_index - 1) % smooth_size] * window_array[i]; 00279 } 00280 smooth_offset /= double(smooth_size); 00281 00282 // This is the integral of the smoothed_offset 00283 offset_integral += smooth_offset; 00284 00285 // Clamp offset : the smooth offset still contains unwanted noise which would go straigth onto the resample coeff. 00286 // It only used in the P component and the I component is used for the fine tuning anyways. 00287 if (fabs(smooth_offset) < pclamp) 00288 smooth_offset = 0.0; 00289 00290 // Ok, now this is the PI controller. 00291 // u(t) = K * (e(t) + 1/T \int e(t') dt') 00292 // Kp = 1/catch_factor and T = catch_factor2 Ki = Kp/T 00293 double current_resample_factor 00294 = static_resample_factor - smooth_offset / catch_factor - offset_integral / catch_factor / catch_factor2; 00295 00296 // Now quantize this value around resample_mean, so that the noise which is in the integral component doesnt hurt. 00297 current_resample_factor = floor((current_resample_factor - resample_mean) * controlquant + 0.5) / controlquant + resample_mean; 00298 00299 // Calculate resample_mean so we can init ourselves to saner values. 00300 resample_mean = 0.9999 * resample_mean + 0.0001 * current_resample_factor; 00301 return current_resample_factor; 00302 } 00303 */ 00304 00305 double GetRatio(int error) 00306 { 00307 double smooth_offset = error; 00308 00309 // This is the integral of the smoothed_offset 00310 offset_integral += smooth_offset; 00311 00312 // Ok, now this is the PI controller. 00313 // u(t) = K * (e(t) + 1/T \int e(t') dt') 00314 // Kp = 1/catch_factor and T = catch_factor2 Ki = Kp/T 00315 return static_resample_factor - smooth_offset/catch_factor - offset_integral/catch_factor/catch_factor2; 00316 } 00317 00318 void OurOfBounds() 00319 { 00320 int i; 00321 // Set the resample_rate... we need to adjust the offset integral, to do this. 00322 // first look at the PI controller, this code is just a special case, which should never execute once 00323 // everything is swung in. 00324 offset_integral = - (resample_mean - static_resample_factor) * catch_factor * catch_factor2; 00325 // Also clear the array. we are beginning a new control cycle. 00326 for (i = 0; i < smooth_size; i++) { 00327 offset_array[i] = 0.0; 00328 } 00329 } 00330 00331 }; 00332 00333 } 00334 00335 #endif