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

Revision 864, 5.9 kB (checked in by ppalmers, 16 years ago)

update license to GPLv2 or GPLv3 instead of GPLv2 or any later version. Update copyrights to reflect the new year

Line 
1 /*
2  * Copyright (C) 2005-2008 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 program is free software: you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation, either version 2 of the License, or
12  * (at your option) version 3 of the License.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
21  *
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.