| 1 | /**************************************************************************** |
|---|
| 2 | |
|---|
| 3 | Copyright 2006, Virginia Polytechnic Institute and State University |
|---|
| 4 | |
|---|
| 5 | This file is part of the OSSIE Signal Processing Library. |
|---|
| 6 | |
|---|
| 7 | OSSIE Core Framework is free software; you can redistribute it and/or modify |
|---|
| 8 | it under the terms of the Lesser GNU General Public License as published by |
|---|
| 9 | the Free Software Foundation; either version 2.1 of the License, or |
|---|
| 10 | (at your option) any later version. |
|---|
| 11 | |
|---|
| 12 | The OSSIE Signal Processing library is distributed in the hope that it will be useful, |
|---|
| 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 15 | Lesser GNU General Public License for more details. |
|---|
| 16 | |
|---|
| 17 | You should have received a copy of the Lesser GNU General Public License |
|---|
| 18 | along with OSSIE Core Framework; if not, write to the Free Software |
|---|
| 19 | Foundation, 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 | |
|---|
| 88 | void 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 |
|---|
| 168 | SigProc::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 |
|---|
| 215 | SigProc::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 |
|---|
| 238 | SigProc::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 |
|---|
| 247 | void 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 |
|---|
| 254 | void 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 |
|---|
| 293 | void 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 |
|---|
| 303 | void SigProc::FIRPolyphaseFilterBank::PrintBuffer() |
|---|
| 304 | { |
|---|
| 305 | v.Print(); |
|---|
| 306 | } |
|---|
| 307 | |
|---|
| 308 | /// Print filter bank coefficients to the screen |
|---|
| 309 | void 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 | /// |
|---|
| 335 | void 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 |
|---|
| 356 | void 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 | /// |
|---|
| 375 | void SigProc::FIRPolyphaseFilterBank::CalculateGaussianFilterCoefficients() |
|---|
| 376 | { |
|---|
| 377 | if ( H != NULL ) |
|---|
| 378 | delete [] H; |
|---|
| 379 | |
|---|
| 380 | } |
|---|
| 381 | |
|---|
| 382 | // Calculate derivative filter coefficients |
|---|
| 383 | void 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 | |
|---|
| 405 | SigProc::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 | |
|---|
| 429 | void SigProc::iir_filter::ResetBuffer() |
|---|
| 430 | { |
|---|
| 431 | for (unsigned int i = 0; i < len_v; ++i) |
|---|
| 432 | v[i] = 0; |
|---|
| 433 | } |
|---|
| 434 | |
|---|
| 435 | void 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 | |
|---|
| 475 | SigProc::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 | |
|---|
| 499 | void 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 | |
|---|
| 545 | void 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 | } |
|---|