root/trunk/libffado/src/libutil/DelayLockedLoop.cpp

Revision 445, 5.9 kB (checked in by pieterpalmers, 14 years ago)

* name change from FreeBoB to FFADO
* replaced tabs by 4 spaces
* got rid of end-of-line spaces
* made all license and copyrights conform

library becomes LGPL, apps become GPL
explicitly state LGPL v2.1 and GPL v2 (don't like v3 draft)

copyrights are 2005-2007 Daniel & Pieter
except for the MotU stuff (C) Jonathan, Pieter

Line 
1 /*
2  * Copyright (C) 2005-2007 by Pieter Palmers
3  *
4  * This file is part of FFADO
5  * FFADO = Free Firewire (pro-)audio drivers for linux
6  *
7  * FFADO is based upon FreeBoB.
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License version 2.1, as published by the Free Software Foundation;
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
21  * MA 02110-1301 USA
22  */
23
24 #include "DelayLockedLoop.h"
25
26 namespace Util {
27
28 /**
29  * Creates a new Delay Locked Loop with a predefined order and
30  * a predefined set of coefficients.
31  *
32  * Make sure coeffs is a float array containing order+1 coefficients.
33  *
34  * @pre order > 0
35  * @param order order of the DLL
36  * @param coeffs coefficients to use
37  */
38 DelayLockedLoop::DelayLockedLoop(unsigned int order, float *coeffs)
39 {
40     unsigned int i;
41
42     m_order=order;
43     if (m_order==0) m_order=1;
44
45     m_coeffs=new float[order];
46     m_nodes=new float[order];
47
48     for (i=0;i<order;i++) {
49         m_coeffs[i]=coeffs[i];
50         m_nodes[i]=0.0;
51     }
52
53 }
54
55 /**
56  * Creates a new Delay Locked Loop with a predefined order.
57  * All coefficients are set to 0.
58  *
59  * @pre order > 0
60  * @param order order of the DLL
61  */
62 DelayLockedLoop::DelayLockedLoop(unsigned int order)
63 {
64     unsigned int i;
65
66     m_order=order;
67     if (m_order==0) m_order=1;
68
69     m_coeffs=new float[order];
70     m_nodes=new float[order];
71
72     for (i=0;i<order;i++) {
73         m_coeffs[i]=0.0;
74         m_nodes[i]=0.0;
75     }
76 }
77
78 /**
79  * Creates a new first order Delay Locked Loop.
80  * The coefficient is set to 0.
81  *
82  */
83 DelayLockedLoop::DelayLockedLoop() {
84     m_order=1;
85
86     m_coeffs=new float[1];
87     m_coeffs[0]=0.0;
88
89     m_nodes=new float[1];
90     m_nodes[0]=0.0;
91 }
92
93 DelayLockedLoop::~DelayLockedLoop() {
94     if(m_coeffs) delete[] m_coeffs;
95     if(m_nodes) delete[] m_nodes;
96
97 }
98
99 /**
100  * Returns the coefficient with index i
101  *
102  * i should be smaller than the DLL order
103  *
104  * @param i index of the coefficient
105  * @return value of the coefficient
106  */
107 float
108 DelayLockedLoop::getCoefficient(unsigned int i) {
109
110     if (i<m_order) {
111         return m_coeffs[i];
112     } else {
113         return 0.0;
114     }
115 }
116 /**
117  * Sets the value of the coefficient with index i
118  *
119  * i should be smaller than the DLL order
120  *
121  * @param i index of the coefficient
122  * @param c value of the coefficient
123  */
124 void
125 DelayLockedLoop::setCoefficient(unsigned int i, float c) {
126
127     if (i<m_order) {
128         m_coeffs[i]=c;
129     }
130 }
131
132 /**
133  * Sets the value of the integrator output with index i.
134  * This allows to set the inital values
135  *
136  * i should be smaller than the DLL order
137  *
138  *
139  * @param i index of the integrator
140  * @param c value of the integrator output
141  */
142 void
143 DelayLockedLoop::setIntegrator(unsigned int i, float c) {
144
145     if (i<m_order) {
146         m_nodes[i]=c;
147     }
148 }
149
150 /**
151  * Clears the internal state of the DLL,
152  * meaning that it will set all internal nodes to 0.0
153  */
154 void
155 DelayLockedLoop::reset() {
156
157     unsigned int i;
158     for (i=0;i<m_order;i++) {
159         m_nodes[i]=0.0;
160     }
161
162 }
163
164 /**
165  * Returns the order of the DLL
166  * @return DLL order
167  */
168 unsigned int
169 DelayLockedLoop::getOrder() {
170     return m_order;
171 }
172
173 /**
174  * Set the order of the DLL
175  * with setting of new coefficients
176  *
177  * Make sure coeffs is a float array containing 'order' coefficients.
178  *
179  * resets the DLL before changing the order
180  *
181  * @pre order > 0
182  * @param order new order for the DLL
183  * @param coeffs coefficients to use
184  */
185 void
186 DelayLockedLoop::setOrder(unsigned int order, float* coeffs) {
187     unsigned int i;
188
189     reset();
190
191     m_order=order;
192     if (m_order==0) m_order=1;
193
194     if(m_coeffs) delete[] m_coeffs;
195     m_coeffs=new float[order];
196
197     if(m_nodes) delete[] m_nodes;
198     m_nodes=new float[order];
199
200     for (i=0;i<order;i++) {
201         m_coeffs[i]=coeffs[i];
202         m_nodes[i]=0.0;
203     }
204
205 }
206
207 /**
208  * Set the order of the DLL,
209  * the coefficients are set to 0
210  *
211  * resets the DLL before changing the order
212  *
213  * @pre order > 0
214  * @param order new order for the DLL
215  */
216 void
217 DelayLockedLoop::setOrder(unsigned int order) {
218     unsigned int i;
219
220     reset();
221
222     m_order=order;
223
224     if (m_order==0) m_order=1;
225
226     if(m_coeffs) delete[] m_coeffs;
227     m_coeffs=new float[order];
228
229     if(m_nodes) delete[] m_nodes;
230     m_nodes=new float[order];
231
232     for (i=0;i<order;i++) {
233         m_coeffs[i]=0.0;
234         m_nodes[i]=0.0;
235     }
236
237 }
238
239 /**
240  * Put a new value in the loop, updating all internal nodes and
241  * the output value.
242  *
243  * @param v new value
244  */
245 void
246 DelayLockedLoop::put(float v) {
247
248     // we write the calculation out
249     // to make use of pipeline-ing and out of order execution
250     // except for very high order loops, then we do it looped
251
252     // error = newval - output
253     m_error=v-m_nodes[0];
254
255     // update the output value
256     m_nodes[0]+=m_error*m_coeffs[0];
257
258     if(m_order==1) return; // we are done
259
260     // add the output of the second integrator
261     m_nodes[0]+=m_nodes[1];
262
263     // update the second integrator
264     m_nodes[1]+=m_error*m_coeffs[1];
265
266     if(m_order==2) return; // we are done
267
268     // if the order is even higher, we are using a loop
269     unsigned int i;
270     for (i=2; i < m_order;i++) {
271         // add the i-th integrator value
272         m_nodes[i-1] += m_nodes[i];
273
274         // update the i-th integrator
275         m_nodes[i] = m_coeffs[i] * m_error;
276     }
277
278     return;
279 }
280
281 /**
282  * Get the output value of the DLL
283  *
284  * @return current output value
285  */
286 float
287 DelayLockedLoop::get() {
288     return m_nodes[0];
289 }
290
291 /**
292  * Get the current error signal value
293  *
294  * @return current error signal value
295  */
296 float
297 DelayLockedLoop::getError() {
298     return m_error;
299 }
300
301 } // end of namespace FFADOUtil
Note: See TracBrowser for help on using the browser.