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

Revision 277, 6.2 kB (checked in by jwoithe, 17 years ago)

Start of work leading to MOTU iso transmission.
Fix use of uninitialised local variable in DelayLockedLoop::setIntegrator().

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