root/SigProc/trunk/SigProc/filters.cpp @ 3805

Revision 3805, 13.4 KB (checked in by jgaeddert, 6 years ago)

Correcting filter bank indexing to address problems with SymbolSyncPoly and MultirateSynchronizer? components

  • Property svn:eol-style set to native
Line 
1/****************************************************************************
2
3Copyright 2006, Virginia Polytechnic Institute and State University
4
5This file is part of the OSSIE Signal Processing Library.
6
7OSSIE Core Framework is free software; you can redistribute it and/or modify
8it under the terms of the Lesser GNU General Public License as published by
9the Free Software Foundation; either version 2.1 of the License, or
10(at your option) any later version.
11
12The OSSIE Signal Processing library is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15Lesser GNU General Public License for more details.
16
17You should have received a copy of the Lesser GNU General Public License
18along with OSSIE Core Framework; if not, write to the Free Software
19Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20
21****************************************************************************/
22
23#include "SigProc.h"
24
25#include <math.h>
26
27//-----------------------------------------------------------------------------
28//
29// Design root raised-cosine filter
30//
31//-----------------------------------------------------------------------------
32/** \brief Calculate square-root raised-cosine filter coefficients
33
34  DesignRRCFilter calculates the coefficients for a square-root raised-cosine
35  (RRC) finite impulse response (FIR) filter commonly used in digital
36  communications.  The input parameters are as follows
37
38    - \f$k\f$ : samples per symbol
39    - \f$m\f$ : sample delay
40    - \f$\beta\f$ : excess bandwidth (rolloff) factor
41
42  The function returns a pointer to the filter coefficients as well as an
43  integer value describing the length of the filter.  The length of the
44  filter is always
45
46  \f[
47    h_{len} = 2 k m + 1
48  \f]
49
50  The filter coefficients themselves are derived from the following equation
51
52  \f[
53    h\left[z\right] =
54      4\beta \frac{ \cos\left[(1+\beta)\pi z\right] +
55                    \sin\left[(1+\beta)\pi z\right] / (4\beta z) }
56                  { \pi \sqrt{T}\left[ 1-16\beta^2z^2\right] }
57  \f]
58
59  where \f$z=n/k-m\f$, and \f$T=1\f$ for most cases.
60
61  The function compensates for the two cases where \f$h[n]\f$ might be
62  undefined in the above equation, viz.
63
64  \f[
65    \mathop {\lim }\limits_{z \to 0 } h(z) =
66      \frac{ 4\beta \left[ 1 + \frac{1-\beta\pi }{ 4\beta } \right] }
67           { \pi\sqrt{T}\left( 1-16\beta^2 z^2 \right) }
68  \f]
69
70  and
71
72  \f[
73    \mathop {\lim }\limits_{z \to \pm \frac{1}{4\beta} } h(z) =
74        \frac{(1+\beta)}{2\pi}\sin\left[\frac{(1+\beta)\pi}{4\beta}\right]
75      - \frac{(1-\beta)}{2}\cos\left[\frac{(1-\beta)\pi}{4\beta}\right]
76      + \frac{2\beta}{\pi}\sin\left[\frac{(1-\beta)\pi}{4\beta}\right]
77
78  \f]
79
80  \param[in]  k         samples per symbol
81  \param[in]  m         symbol delay
82  \param[in]  beta      excess bandwidth/rolloff factor ( 0 < beta < 1 )
83  \param[out] h         pointer to filter coefficients
84  \param[out] h_len     length of filter, h_len = 2*m*k+1
85
86 */
87
88void SigProc::DesignRRCFilter(
89  unsigned int k,      // samples per symbol
90  unsigned int m,      // delay
91  float beta,          // rolloff factor ( 0 < beta <= 1 )
92  float *& h,          // pointer to filter coefficients
93  unsigned int & h_len // length of filter (len = 2*m*k+1)
94)
95{
96    h_len = 0;
97
98    if ( k < 1 ) {
99        std::cerr << "ERROR: SigProc::DesignRRCFilter: k must be greater than 0"
100                  << std::endl;
101        throw 0;
102    } else if ( m < 1 ) {
103        std::cerr << "ERROR: SigProc::DesignRRCFilter: m must be greater than 0"
104                  << std::endl;
105        return;
106    } else if ( (beta < 0.0f) || (beta > 1.0f) ) {
107        std::cerr << "ERROR: SigProc::DesignRRCFilter: beta must be in [0,1]"
108                  << std::endl;
109        throw 0;
110    } else;
111
112    unsigned int n;
113    float z, t1, t2, t3, t4, T(1.0f);
114    float pi(3.14159265358979f);
115
116    h_len = 2*k*m+1;
117    h = new float[h_len];
118
119    // Calculate filter coefficients
120    for (n=0; n<h_len; n++)
121    {
122
123        z = float(n)/float(k)-float(m);
124        t1 = cosf((1+beta)*pi*z);
125        t2 = sinf((1-beta)*pi*z);
126
127        // Check for special condition where z equals zero
128        if ( n == k*m )
129        {
130            t4 = 4*beta/(pi*sqrtf(T)*(1-(16*beta*beta*z*z)));
131            h[n] = t4*( 1 + (1-beta)*pi/(4*beta) );
132        }
133        else
134        {
135            t3 = 1/((4*beta*z));
136
137            float g = 1-16*beta*beta*z*z;
138            g *= g;
139
140            // Check for special condition where 16*beta^2*z^2 equals 1
141            if ( g < 1e-3 )
142            {
143                float g1, g2, g3, g4;
144                g1 = -(1+beta)*pi*sin((1+beta)*pi/(4*beta));
145                g2 = cos((1-beta)*pi/(4*beta))*(1-beta)*pi;
146                g3 = -sin((1-beta)*pi/(4*beta))*4*beta;
147                g4 = -2*pi;
148
149                h[n] = (g1+g2+g3)/g4;
150            }
151            else
152            {
153                t4 = 4*beta/(pi*sqrtf(T)*(1-(16*beta*beta*z*z)));
154                h[n] = t4*( t1 + (t2*t3) );
155            }
156        }
157
158    }
159}
160
161//-----------------------------------------------------------------------------
162//
163// FIR polyphase filter bank
164//
165//-----------------------------------------------------------------------------
166
167/// Initializing constructor
168SigProc::FIRPolyphaseFilterBank::FIRPolyphaseFilterBank(
169        char * _type,       // type of filter
170        unsigned int _k,    // samples per symbol
171        unsigned int _m,    // delay
172        float _beta,        // excess bandwidth factor
173        unsigned int _Npfb  // number of filters
174        )
175{
176    k = _k;
177    m = _m;
178    beta = _beta;
179    Npfb = _Npfb;
180
181    H = NULL;
182
183    if ( strcmp(_type,"rrcos")==0 ) {
184        // Square-root raised-cosine filter
185        CalculateRRCFilterCoefficients();
186        TransposeCoefficientMatrix();
187    } else if ( strcmp(_type,"drrcos")==0 ) {
188        // Derivative square-root raised-cosine filter
189        CalculateRRCFilterCoefficients();
190        CalculateDerivativeFilterCoefficients();
191        TransposeCoefficientMatrix();
192    } else if ( strcmp(_type,"gaussian")==0 ) {
193        // Gaussian filter
194        CalculateGaussianFilterCoefficients();
195        TransposeCoefficientMatrix();
196    } else if ( strcmp(_type,"dgaussian")==0 ) {
197        // Derivative gaussian filter
198        CalculateGaussianFilterCoefficients();
199        CalculateDerivativeFilterCoefficients();
200        TransposeCoefficientMatrix();
201    } else {
202        std::cerr << "ERROR: FIRPolyphaseFilterBank: unknown filter type : " << _type << std::endl;
203        throw 0;
204    }
205
206    // At this point, H should be initialized and h_len should store
207    // the correct length of each filter in the bank.
208    v.SetBufferSize(h_len);
209
210    // memset input buffer to zeros
211    ResetBuffer();
212}
213
214/// Initializing constructor
215SigProc::FIRPolyphaseFilterBank::FIRPolyphaseFilterBank(
216        float * _H,         // filter bank coefficients
217        unsigned int _h_len,// length of each filter
218        unsigned int _Npfb  // number of filters
219        )
220{
221    /// \todo perform check on input?
222
223    h_len = _h_len;
224    Npfb = _Npfb;
225
226    // perform deep copy of memory
227    H = new float[Npfb*h_len];
228    for (unsigned int i=0; i<(Npfb*h_len); i++)
229        H[i] = _H[i];
230
231    v.SetBufferSize(h_len);
232
233    // memset input buffer to zeros
234    ResetBuffer();
235}
236
237/// destructor
238SigProc::FIRPolyphaseFilterBank::~FIRPolyphaseFilterBank()
239{
240    // delete filter bank coefficients matrix
241    if ( H != NULL )
242        delete [] H;
243
244}
245
246/// push input value into buffer
247void SigProc::FIRPolyphaseFilterBank::PushInput(short _x)
248{
249    // Add _x to input buffer
250    v.Push( _x );
251}
252
253/// compute filter output from current buffer state using specific filter
254void SigProc::FIRPolyphaseFilterBank::ComputeOutput(
255        short &y,           // output sample
256        unsigned int _b     // filter bank index
257        )
258{
259    // Ensure the requested filter bank index does not exceed the number
260    // of filters actually in the bank
261    if ( _b >= Npfb )
262    {
263        std::cerr << "ERROR: SigProc::FIRPolyphaseFitlerBank::ComputeOutput, "
264                  << " index exceeds filter bank size ("
265                  << _b << " > " << Npfb << ")" << std::endl;
266        throw 0;
267    }
268
269    // Initialize floating point value for output
270    /// \todo make this compatable with FPM
271    float yf(0.0f);
272
273    // Set B to memory block in filter bank array
274    unsigned int B;
275    B = _b*h_len;
276
277    // Accumulate (apply filter)
278    for (unsigned int i=0; i<h_len; i++)
279        yf += float( v[i] ) * H[B+i];
280
281    // Ensure yf is within the scope of short int
282    if ( yf < SHRT_MIN ) {
283        y = SHRT_MIN;
284    } else if ( yf > SHRT_MAX ) {
285        y = SHRT_MAX;
286    } else {
287        y = (short) yf;
288    }
289
290}
291
292/// Reset filter buffer
293void SigProc::FIRPolyphaseFilterBank::ResetBuffer()
294{
295    v.Release();
296
297    // Load buffer with zeros
298    for (unsigned int i=0; i<h_len; i++)
299        v.Push( 0 );
300}
301
302/// Print filter buffer
303void SigProc::FIRPolyphaseFilterBank::PrintBuffer()
304{
305    v.Print();
306}
307
308/// Print filter bank coefficients to the screen
309void SigProc::FIRPolyphaseFilterBank::PrintFilterBankCoefficients()
310{
311    if ( H == NULL )
312    {
313        std::cout << "ERROR: SigProc::FIRPolyphaseFilterBank: "
314                  << "cannot print filter coefficients (matrix empty)"
315                  << std::endl;
316        return;
317    }
318
319    unsigned int r, c, B;
320    std::cout << "H = [" << std::endl;
321    for (r=0; r<Npfb; r++ ) {
322        B = r*h_len;
323        printf("  ");
324
325        for (c=0; c<h_len; c++) {
326            printf("%0.3f ", H[B + c]);
327        }
328        printf(";\n");
329    }
330    std::cout << "   ]" << std::endl;
331
332}
333
334///
335void SigProc::FIRPolyphaseFilterBank::TransposeCoefficientMatrix()
336{
337    // create temporary pointer
338    float * H_tmp;
339    H_tmp = H;
340
341    // allocate new memory for filter bank coefficients
342    H = new float[h_len*Npfb];
343
344    // reshape matrix
345    unsigned int i(0), r, c;
346    for (r=0; r<Npfb; r++) {
347        for (c=0; c<h_len; c++)
348            H[i++] = H_tmp[c*Npfb + r];
349    }
350
351    delete [] H_tmp;
352}
353
354
355/// Calculate root raised-cosine coefficients
356void SigProc::FIRPolyphaseFilterBank::CalculateRRCFilterCoefficients()
357{
358    if ( H != NULL )
359        delete [] H;
360
361    // create over-sampled pulse
362    SigProc::DesignRRCFilter(Npfb*k, m, beta, H, h_len);
363
364    // Apply scaling factor to filter coefficients
365    float h_scale = float(k);
366    for (unsigned int i=0; i<h_len; i++)
367        H[i] /= h_scale;
368
369    //
370    h_len = ( h_len - 1 ) / Npfb;
371
372}
373
374///
375void SigProc::FIRPolyphaseFilterBank::CalculateGaussianFilterCoefficients()
376{
377    if ( H != NULL )
378        delete [] H;
379
380}
381
382// Calculate derivative filter coefficients
383void SigProc::FIRPolyphaseFilterBank::CalculateDerivativeFilterCoefficients()
384{
385    unsigned int N = h_len*Npfb;
386
387    float * dH = new float[N];
388
389    for (unsigned int i=0; i<N; i++) {
390        if ( i==0 ) {
391            dH[0] = H[1] - H[N-1];
392        } else if ( i==N-1 ) {
393            dH[N-1] = H[0] - H[N-2];
394        } else {
395            dH[i] = H[i+1] - H[i-1];
396        }
397        dH[i] /= 2.0f;
398    }
399
400    delete [] H;
401    H = dH;
402}
403
404
405SigProc::iir_filter::iir_filter(float a_coeff[], unsigned int len_a, float b_coeff[], unsigned int len_b) : len_A(len_a), len_B(len_b), next_v(0)
406{
407
408    A = new float[len_a];
409    B = new float[len_b];
410
411    for (unsigned int i = 0; i < len_a; ++i)
412        A[i] = a_coeff[i];
413
414    for (unsigned int i = 0; i < len_b; ++i)
415        B[i] = b_coeff[i];
416
417    if (len_A > len_B)
418        len_v = len_A;
419    else
420        len_v = len_B;
421
422    v = new float[len_v];
423
424    for (unsigned int i = 0; i < len_v; ++i)
425        v[i] = 0;
426
427}
428
429void SigProc::iir_filter::ResetBuffer()
430{
431    for (unsigned int i = 0; i < len_v; ++i)
432        v[i] = 0;
433}
434
435void SigProc::iir_filter::do_work(short x, short &y)
436{
437    // calculate new v[n]
438    int v_idx = next_v;
439
440    v[next_v] = x;
441
442    for (unsigned int i = 1; i < len_A; ++i) {
443
444        --v_idx;
445        if (v_idx < 0)
446            v_idx += len_v;
447
448        v[next_v] -= (short) (A[i] * v[v_idx]);
449         
450    }
451
452    // Now calculate the output value
453    v_idx = next_v;
454    float out = 0;
455
456    for (unsigned int i = 0; i < len_B; ++i) {
457        out += (B[i] * v[v_idx]);
458
459        --v_idx;
460        if (v_idx < 0)
461            v_idx += len_v;
462    }
463
464    next_v = (++next_v) % len_v;
465
466    if (out < SHRT_MIN)
467        y = SHRT_MIN;
468    else if (out > SHRT_MAX)
469        y = SHRT_MAX;
470    else
471        y = (short) out;
472}
473
474
475SigProc::fir_filter::fir_filter(float a_coeff[], unsigned int len_a) : len_A(len_a), len_v(len_a),next_v(0)
476 {
477#ifdef FPM
478    A = new mad_fixed_t[len_a];
479    v = new mad_fixed_t[len_v];
480#else
481    A = new float[len_a];
482    v = new short[len_v];
483#endif
484
485    for (unsigned int i = 0; i < len_a; ++i)
486#ifdef FPM
487        A[i] = mad_f_tofixed(a_coeff[i]);
488#else
489        A[i] = a_coeff[i];
490#endif
491
492
493    for (unsigned int i = 0; i < len_v; ++i)
494        v[i] = 0;
495
496
497}
498
499void SigProc::fir_filter::do_work(bool run_filter, short x, short &y)
500{
501    // calculate new v[n]
502    int v_idx = next_v;
503
504    v[next_v] = x;
505    next_v = (++next_v) % len_v;
506
507    if (!run_filter) { // Do not create an output value
508        y = 0;
509        return;
510    }
511
512    // Now calculate the output value
513#ifdef FPM
514    mad_fixed_t out(0);
515#else
516    float out(0.0);
517#endif
518
519    for (unsigned int i = 0; i < len_A; ++i) {
520        if (v[v_idx]) {
521#ifdef FPM
522            out = mad_f_add(out, mad_f_mul(A[i], v[v_idx]));
523#else
524            out += (A[i] * v[v_idx]);
525#endif
526        }
527
528        --v_idx;
529        if (v_idx < 0)
530            v_idx += len_v;
531    }
532
533#ifdef FPM
534        y = (short) out;
535#else
536    if (out < SHRT_MIN)
537        y = SHRT_MIN;
538    else if (out > SHRT_MAX)
539        y = SHRT_MAX;
540    else
541        y = (short) out;
542#endif
543}
544
545void SigProc::fir_filter::reset()
546{
547
548    for (unsigned int i = 0; i < len_v; ++i)
549        v[i] = 0;
550
551    next_v = 0;
552}
Note: See TracBrowser for help on using the browser.