Statistics
| Branch: | Tag: | Revision:

root / gnuradio-core / src / lib / general / gr_firdes.cc @ 2cc26e4d

History | View | Annotate | Download (22.1 kB)

1
/* -*- c++ -*- */
2
/*
3
 * Copyright 2002,2007,2008 Free Software Foundation, Inc.
4
 * 
5
 * This file is part of GNU Radio
6
 * 
7
 * GNU Radio is free software; you can redistribute it and/or modify
8
 * it under the terms of the GNU General Public License as published by
9
 * the Free Software Foundation; either version 3, or (at your option)
10
 * any later version.
11
 * 
12
 * GNU Radio 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
 * GNU General Public License for more details.
16
 * 
17
 * You should have received a copy of the GNU General Public License
18
 * along with GNU Radio; see the file COPYING.  If not, write to
19
 * the Free Software Foundation, Inc., 51 Franklin Street,
20
 * Boston, MA 02110-1301, USA.
21
 */
22
23
#ifdef HAVE_CONFIG_H
24
#include <config.h>
25
#endif
26
27
#include <gr_firdes.h>
28
#include <stdexcept>
29
30
31
using std::vector;
32
33
#define IzeroEPSILON 1E-21               /* Max error acceptable in Izero */
34
35
static double Izero(double x)
36
{
37
   double sum, u, halfx, temp;
38
   int n;
39
40
   sum = u = n = 1;
41
   halfx = x/2.0;
42
   do {
43
      temp = halfx/(double)n;
44
      n += 1;
45
      temp *= temp;
46
      u *= temp;
47
      sum += u;
48
      } while (u >= IzeroEPSILON*sum);
49
   return(sum);
50
}
51
52
53
//
54
//        === Low Pass ===
55
//
56
57
vector<float>
58
gr_firdes::low_pass_2(double gain,
59
                      double sampling_freq,    // Hz
60
                      double cutoff_freq,      // Hz BEGINNING of transition band
61
                      double transition_width, // Hz width of transition band
62
                      double attenuation_dB,   // attenuation dB
63
                      win_type window_type,
64
                      double beta)             // used only with Kaiser
65
{
66
  sanity_check_1f (sampling_freq, cutoff_freq, transition_width);
67
68
  int ntaps = compute_ntaps_windes (sampling_freq, transition_width,
69
                                    attenuation_dB);
70
71
  // construct the truncated ideal impulse response
72
  // [sin(x)/x for the low pass case]
73
74
  vector<float> taps(ntaps);
75
  vector<float> w = window (window_type, ntaps, beta);
76
77
  int M = (ntaps - 1) / 2;
78
  double fwT0 = 2 * M_PI * cutoff_freq / sampling_freq;
79
  for (int n = -M; n <= M; n++){
80
    if (n == 0)
81
      taps[n + M] = fwT0 / M_PI * w[n + M];
82
    else {
83
      // a little algebra gets this into the more familiar sin(x)/x form
84
      taps[n + M] =  sin (n * fwT0) / (n * M_PI) * w[n + M];
85
    }
86
  }
87
  
88
  // find the factor to normalize the gain, fmax.
89
  // For low-pass, gain @ zero freq = 1.0
90
  
91
  double fmax = taps[0 + M];
92
  for (int n = 1; n <= M; n++)
93
    fmax += 2 * taps[n + M];
94
95
  gain /= fmax;        // normalize
96
97
  for (int i = 0; i < ntaps; i++)
98
    taps[i] *= gain;
99
100
101
  return taps;
102
}
103
104
vector<float>
105
gr_firdes::low_pass (double gain,
106
                     double sampling_freq,
107
                     double cutoff_freq,        // Hz center of transition band
108
                     double transition_width,        // Hz width of transition band
109
                     win_type window_type,
110
                     double beta)                // used only with Kaiser
111
{
112
  sanity_check_1f (sampling_freq, cutoff_freq, transition_width);
113
114
  int ntaps = compute_ntaps (sampling_freq, transition_width,
115
                             window_type, beta);
116
117
  // construct the truncated ideal impulse response
118
  // [sin(x)/x for the low pass case]
119
120
  vector<float> taps(ntaps);
121
  vector<float> w = window (window_type, ntaps, beta);
122
123
  int M = (ntaps - 1) / 2;
124
  double fwT0 = 2 * M_PI * cutoff_freq / sampling_freq;
125
126
  for (int n = -M; n <= M; n++){
127
    if (n == 0)
128
      taps[n + M] = fwT0 / M_PI * w[n + M];
129
    else {
130
      // a little algebra gets this into the more familiar sin(x)/x form
131
      taps[n + M] =  sin (n * fwT0) / (n * M_PI) * w[n + M];
132
    }
133
  }
134
  
135
  // find the factor to normalize the gain, fmax.
136
  // For low-pass, gain @ zero freq = 1.0
137
  
138
  double fmax = taps[0 + M];
139
  for (int n = 1; n <= M; n++)
140
    fmax += 2 * taps[n + M];
141
142
  gain /= fmax;        // normalize
143
144
  for (int i = 0; i < ntaps; i++)
145
    taps[i] *= gain;
146
147
  return taps;
148
}
149
150
151
//
152
//        === High Pass ===
153
//
154
155
vector<float>
156
gr_firdes::high_pass_2 (double gain,
157
                      double sampling_freq,
158
                      double cutoff_freq,       // Hz center of transition band
159
                      double transition_width,  // Hz width of transition band
160
                      double attenuation_dB,   // attenuation dB
161
                      win_type window_type,
162
                      double beta)              // used only with Kaiser
163
{
164
  sanity_check_1f (sampling_freq, cutoff_freq, transition_width);
165
166
  int ntaps = compute_ntaps_windes (sampling_freq, transition_width,
167
                                    attenuation_dB);
168
169
  // construct the truncated ideal impulse response times the window function
170
171
  vector<float> taps(ntaps);
172
  vector<float> w = window (window_type, ntaps, beta);
173
174
  int M = (ntaps - 1) / 2;
175
  double fwT0 = 2 * M_PI * cutoff_freq / sampling_freq;
176
177
  for (int n = -M; n <= M; n++){
178
    if (n == 0)
179
      taps[n + M] = (1 - (fwT0 / M_PI)) * w[n + M];
180
    else {
181
      // a little algebra gets this into the more familiar sin(x)/x form
182
      taps[n + M] =  -sin (n * fwT0) / (n * M_PI) * w[n + M];
183
    }
184
  }
185
186
  // find the factor to normalize the gain, fmax.
187
  // For high-pass, gain @ fs/2 freq = 1.0
188
189
  double fmax = taps[0 + M];
190
  for (int n = 1; n <= M; n++)
191
    fmax += 2 * taps[n + M] * cos (n * M_PI);
192
193
  gain /= fmax; // normalize
194
195
  for (int i = 0; i < ntaps; i++)
196
    taps[i] *= gain;
197
198
199
  return taps;
200
}
201
202
203
vector<float>
204
gr_firdes::high_pass (double gain,
205
                      double sampling_freq,
206
                      double cutoff_freq,       // Hz center of transition band
207
                      double transition_width,  // Hz width of transition band
208
                      win_type window_type,
209
                      double beta)              // used only with Kaiser
210
{
211
  sanity_check_1f (sampling_freq, cutoff_freq, transition_width);
212
213
  int ntaps = compute_ntaps (sampling_freq, transition_width,
214
                             window_type, beta);
215
216
  // construct the truncated ideal impulse response times the window function
217
218
  vector<float> taps(ntaps);
219
  vector<float> w = window (window_type, ntaps, beta);
220
221
  int M = (ntaps - 1) / 2;
222
  double fwT0 = 2 * M_PI * cutoff_freq / sampling_freq;
223
224
  for (int n = -M; n <= M; n++){
225
    if (n == 0)
226
      taps[n + M] = (1 - (fwT0 / M_PI)) * w[n + M];
227
    else {
228
      // a little algebra gets this into the more familiar sin(x)/x form
229
      taps[n + M] =  -sin (n * fwT0) / (n * M_PI) * w[n + M];
230
    }
231
  }
232
233
  // find the factor to normalize the gain, fmax.
234
  // For high-pass, gain @ fs/2 freq = 1.0
235
236
  double fmax = taps[0 + M];
237
  for (int n = 1; n <= M; n++)
238
    fmax += 2 * taps[n + M] * cos (n * M_PI);
239
240
  gain /= fmax; // normalize
241
242
  for (int i = 0; i < ntaps; i++)
243
    taps[i] *= gain;
244
245
  return taps;
246
}
247
248
//
249
//      === Band Pass ===
250
//
251
252
vector<float>
253
gr_firdes::band_pass_2 (double gain,
254
                      double sampling_freq,
255
                      double low_cutoff_freq,        // Hz center of transition band
256
                      double high_cutoff_freq,        // Hz center of transition band
257
                      double transition_width,        // Hz width of transition band
258
                      double attenuation_dB,   // attenuation dB
259
                      win_type window_type,
260
                      double beta)                // used only with Kaiser
261
{
262
  sanity_check_2f (sampling_freq,
263
                   low_cutoff_freq,
264
                   high_cutoff_freq, transition_width);
265
266
  int ntaps = compute_ntaps_windes (sampling_freq, transition_width,
267
                                    attenuation_dB);
268
269
  vector<float> taps(ntaps);
270
  vector<float> w = window (window_type, ntaps, beta);
271
272
  int M = (ntaps - 1) / 2;
273
  double fwT0 = 2 * M_PI * low_cutoff_freq / sampling_freq;
274
  double fwT1 = 2 * M_PI * high_cutoff_freq / sampling_freq;
275
276
  for (int n = -M; n <= M; n++){
277
    if (n == 0)
278
      taps[n + M] = (fwT1 - fwT0) / M_PI * w[n + M];
279
    else {
280
      taps[n + M] =  (sin (n * fwT1) - sin (n * fwT0)) / (n * M_PI) * w[n + M];
281
    }
282
  }
283
  
284
  // find the factor to normalize the gain, fmax.
285
  // For band-pass, gain @ center freq = 1.0
286
  
287
  double fmax = taps[0 + M];
288
  for (int n = 1; n <= M; n++)
289
    fmax += 2 * taps[n + M] * cos (n * (fwT0 + fwT1) * 0.5);
290
291
  gain /= fmax;        // normalize
292
293
  for (int i = 0; i < ntaps; i++)
294
    taps[i] *= gain;
295
296
  return taps;
297
}
298
299
300
vector<float>
301
gr_firdes::band_pass (double gain,
302
                      double sampling_freq,
303
                      double low_cutoff_freq,        // Hz center of transition band
304
                      double high_cutoff_freq,        // Hz center of transition band
305
                      double transition_width,        // Hz width of transition band
306
                      win_type window_type,
307
                      double beta)                // used only with Kaiser
308
{
309
  sanity_check_2f (sampling_freq,
310
                   low_cutoff_freq,
311
                   high_cutoff_freq, transition_width);
312
313
  int ntaps = compute_ntaps (sampling_freq, transition_width,
314
                             window_type, beta);
315
316
  // construct the truncated ideal impulse response times the window function
317
318
  vector<float> taps(ntaps);
319
  vector<float> w = window (window_type, ntaps, beta);
320
321
  int M = (ntaps - 1) / 2;
322
  double fwT0 = 2 * M_PI * low_cutoff_freq / sampling_freq;
323
  double fwT1 = 2 * M_PI * high_cutoff_freq / sampling_freq;
324
325
  for (int n = -M; n <= M; n++){
326
    if (n == 0)
327
      taps[n + M] = (fwT1 - fwT0) / M_PI * w[n + M];
328
    else {
329
      taps[n + M] =  (sin (n * fwT1) - sin (n * fwT0)) / (n * M_PI) * w[n + M];
330
    }
331
  }
332
  
333
  // find the factor to normalize the gain, fmax.
334
  // For band-pass, gain @ center freq = 1.0
335
  
336
  double fmax = taps[0 + M];
337
  for (int n = 1; n <= M; n++)
338
    fmax += 2 * taps[n + M] * cos (n * (fwT0 + fwT1) * 0.5);
339
340
  gain /= fmax;        // normalize
341
342
  for (int i = 0; i < ntaps; i++)
343
    taps[i] *= gain;
344
345
  return taps;
346
}
347
348
//
349
//        === Complex Band Pass ===
350
//
351
352
vector<gr_complex>
353
gr_firdes::complex_band_pass_2 (double gain,
354
                      double sampling_freq,
355
                      double low_cutoff_freq,        // Hz center of transition band
356
                      double high_cutoff_freq,        // Hz center of transition band
357
                      double transition_width,        // Hz width of transition band
358
                      double attenuation_dB,      // attenuation dB
359
                      win_type window_type,
360
                      double beta)                // used only with Kaiser
361
{
362
  sanity_check_2f_c (sampling_freq,
363
                   low_cutoff_freq,
364
                   high_cutoff_freq, transition_width);
365
366
  int ntaps = compute_ntaps_windes (sampling_freq, transition_width,
367
                                    attenuation_dB);
368
369
370
371
  vector<gr_complex> taps(ntaps);
372
  vector<float> lptaps(ntaps);
373
  vector<float> w = window (window_type, ntaps, beta);
374
375
  lptaps = low_pass_2(gain,sampling_freq,(high_cutoff_freq - low_cutoff_freq)/2,transition_width,attenuation_dB,window_type,beta);
376
377
  gr_complex *optr = &taps[0];
378
  float *iptr = &lptaps[0];
379
  float freq = M_PI * (high_cutoff_freq + low_cutoff_freq)/sampling_freq;
380
  float phase=0;
381
  if (lptaps.size() & 01) {
382
      phase = - freq * ( lptaps.size() >> 1 );
383
  } else phase = - freq/2.0 * ((1 + 2*lptaps.size()) >> 1);
384
  for(unsigned int i=0;i<lptaps.size();i++) {
385
      *optr++ = gr_complex(*iptr * cos(phase),*iptr * sin(phase));
386
      iptr++, phase += freq;
387
  }
388
  
389
  return taps;
390
}
391
392
393
vector<gr_complex>
394
gr_firdes::complex_band_pass (double gain,
395
                      double sampling_freq,
396
                      double low_cutoff_freq,        // Hz center of transition band
397
                      double high_cutoff_freq,        // Hz center of transition band
398
                      double transition_width,        // Hz width of transition band
399
                      win_type window_type,
400
                      double beta)                // used only with Kaiser
401
{
402
  sanity_check_2f_c (sampling_freq,
403
                   low_cutoff_freq,
404
                   high_cutoff_freq, transition_width);
405
406
  int ntaps = compute_ntaps (sampling_freq, transition_width,
407
                             window_type, beta);
408
409
  // construct the truncated ideal impulse response times the window function
410
411
  vector<gr_complex> taps(ntaps);
412
  vector<float> lptaps(ntaps);
413
  vector<float> w = window (window_type, ntaps, beta);
414
415
  lptaps = low_pass(gain,sampling_freq,(high_cutoff_freq - low_cutoff_freq)/2,transition_width,window_type,beta);
416
417
  gr_complex *optr = &taps[0];
418
  float *iptr = &lptaps[0];
419
  float freq = M_PI * (high_cutoff_freq + low_cutoff_freq)/sampling_freq;
420
  float phase=0;
421
  if (lptaps.size() & 01) {
422
      phase = - freq * ( lptaps.size() >> 1 );
423
  } else phase = - freq/2.0 * ((1 + 2*lptaps.size()) >> 1);
424
  for(unsigned int i=0;i<lptaps.size();i++) {
425
      *optr++ = gr_complex(*iptr * cos(phase),*iptr * sin(phase));
426
      iptr++, phase += freq;
427
  }
428
  
429
  return taps;
430
}
431
432
//
433
//        === Band Reject ===
434
//
435
436
vector<float>
437
gr_firdes::band_reject_2 (double gain,
438
                          double sampling_freq,
439
                        double low_cutoff_freq,         // Hz center of transition band
440
                        double high_cutoff_freq, // Hz center of transition band
441
                        double transition_width, // Hz width of transition band
442
                        double attenuation_dB,   // attenuation dB
443
                        win_type window_type,
444
                        double beta)                 // used only with Kaiser
445
{
446
  sanity_check_2f (sampling_freq,
447
                   low_cutoff_freq,
448
                   high_cutoff_freq, transition_width);
449
450
  int ntaps = compute_ntaps_windes (sampling_freq, transition_width,
451
                                    attenuation_dB);
452
453
  // construct the truncated ideal impulse response times the window function
454
455
  vector<float> taps(ntaps);
456
  vector<float> w = window (window_type, ntaps, beta);
457
458
  int M = (ntaps - 1) / 2;
459
  double fwT0 = 2 * M_PI * low_cutoff_freq / sampling_freq;
460
  double fwT1 = 2 * M_PI * high_cutoff_freq / sampling_freq;
461
462
  for (int n = -M; n <= M; n++){
463
    if (n == 0)
464
      taps[n + M] = 1.0 + ((fwT0 - fwT1) / M_PI * w[n + M]);
465
    else {
466
      taps[n + M] =  (sin (n * fwT0) - sin (n * fwT1)) / (n * M_PI) * w[n + M];
467
    }
468
  }
469
  
470
  // find the factor to normalize the gain, fmax.
471
  // For band-reject, gain @ zero freq = 1.0
472
  
473
  double fmax = taps[0 + M];
474
  for (int n = 1; n <= M; n++)
475
    fmax += 2 * taps[n + M];
476
477
  gain /= fmax;        // normalize
478
479
  for (int i = 0; i < ntaps; i++)
480
    taps[i] *= gain;
481
482
  return taps;
483
}
484
485
vector<float>
486
gr_firdes::band_reject (double gain,
487
                          double sampling_freq,
488
                        double low_cutoff_freq,         // Hz center of transition band
489
                        double high_cutoff_freq, // Hz center of transition band
490
                        double transition_width, // Hz width of transition band
491
                        win_type window_type,
492
                        double beta)                 // used only with Kaiser
493
{
494
  sanity_check_2f (sampling_freq,
495
                   low_cutoff_freq,
496
                   high_cutoff_freq, transition_width);
497
498
  int ntaps = compute_ntaps (sampling_freq, transition_width,
499
                             window_type, beta);
500
501
  // construct the truncated ideal impulse response times the window function
502
503
  vector<float> taps(ntaps);
504
  vector<float> w = window (window_type, ntaps, beta);
505
506
  int M = (ntaps - 1) / 2;
507
  double fwT0 = 2 * M_PI * low_cutoff_freq / sampling_freq;
508
  double fwT1 = 2 * M_PI * high_cutoff_freq / sampling_freq;
509
510
  for (int n = -M; n <= M; n++){
511
    if (n == 0)
512
      taps[n + M] = 1.0 + ((fwT0 - fwT1) / M_PI * w[n + M]);
513
    else {
514
      taps[n + M] =  (sin (n * fwT0) - sin (n * fwT1)) / (n * M_PI) * w[n + M];
515
    }
516
  }
517
  
518
  // find the factor to normalize the gain, fmax.
519
  // For band-reject, gain @ zero freq = 1.0
520
  
521
  double fmax = taps[0 + M];
522
  for (int n = 1; n <= M; n++)
523
    fmax += 2 * taps[n + M];
524
525
  gain /= fmax;        // normalize
526
527
  for (int i = 0; i < ntaps; i++)
528
    taps[i] *= gain;
529
530
  return taps;
531
}
532
533
//
534
// Hilbert Transform
535
//
536
537
vector<float>
538
gr_firdes::hilbert (unsigned int ntaps,
539
                    win_type windowtype, 
540
                    double beta)
541
{
542
  if(!(ntaps & 1))
543
    throw std::out_of_range("Hilbert:  Must have odd number of taps");
544
545
  vector<float> taps(ntaps);
546
  vector<float> w = window (windowtype, ntaps, beta);
547
  unsigned int h = (ntaps-1)/2;
548
  float gain=0;
549
  for (unsigned int i = 1; i <= h; i++)
550
    {
551
      if(i&1)
552
        {
553
          float x = 1/(float)i;
554
          taps[h+i] = x * w[h+i];
555
          taps[h-i] = -x * w[h-i];
556
          gain = taps[h+i] - gain;
557
        }
558
      else
559
        taps[h+i] = taps[h-i] = 0;
560
    }
561
  gain = 2 * fabs(gain);
562
  for ( unsigned int i = 0; i < ntaps; i++)
563
      taps[i] /= gain;
564
  return taps;
565
}
566
567
//
568
// Gaussian
569
//
570
571
vector<float>
572
gr_firdes::gaussian (double gain,
573
                     double spb,
574
                     double bt,
575
                     int ntaps)
576
{
577
578
  vector<float> taps(ntaps);
579
  double scale = 0;
580
  double dt = 1.0/spb;
581
  double s = 1.0/(sqrt(log(2.0)) / (2*M_PI*bt));
582
  double t0 = -0.5 * ntaps;
583
  double ts;
584
  for(int i=0;i<ntaps;i++)
585
    {
586
      t0++;
587
      ts = s*dt*t0;
588
      taps[i] = exp(-0.5*ts*ts);
589
      scale += taps[i];
590
    }
591
  for(int i=0;i<ntaps;i++)
592
    taps[i] = taps[i] / scale * gain;
593
  return taps;
594
}
595
596
597
//
598
// Root Raised Cosine
599
//
600
601
vector<float>
602
gr_firdes::root_raised_cosine (double gain,
603
                               double sampling_freq,
604
                               double symbol_rate,
605
                               double alpha,
606
                               int ntaps)
607
{
608
  ntaps |= 1;        // ensure that ntaps is odd
609
610
  double spb = sampling_freq/symbol_rate; // samples per bit/symbol
611
  vector<float> taps(ntaps);
612
  double scale = 0;
613
  for(int i=0;i<ntaps;i++)
614
    {
615
      double x1,x2,x3,num,den;
616
      double xindx = i - ntaps/2;
617
      x1 = M_PI * xindx/spb;
618
      x2 = 4 * alpha * xindx / spb;
619
      x3 = x2*x2 - 1;
620
      if( fabs(x3) >= 0.000001 )  // Avoid Rounding errors...
621
        {
622
          if( i != ntaps/2 )
623
            num = cos((1+alpha)*x1) + sin((1-alpha)*x1)/(4*alpha*xindx/spb);
624
          else
625
            num = cos((1+alpha)*x1) + (1-alpha) * M_PI / (4*alpha);
626
          den = x3 * M_PI;
627
        }
628
      else
629
        {
630
          if(alpha==1)
631
            {
632
              taps[i] = -1;
633
              continue;
634
            }
635
          x3 = (1-alpha)*x1;
636
          x2 = (1+alpha)*x1;
637
          num = (sin(x2)*(1+alpha)*M_PI
638
                 - cos(x3)*((1-alpha)*M_PI*spb)/(4*alpha*xindx)
639
                 + sin(x3)*spb*spb/(4*alpha*xindx*xindx));
640
          den = -32 * M_PI * alpha * alpha * xindx/spb;
641
        }
642
      taps[i] = 4 * alpha * num / den;
643
      scale += taps[i];
644
    }
645
646
  for(int i=0;i<ntaps;i++)
647
    taps[i] = taps[i] * gain / scale;
648
649
  return taps;
650
}
651
652
//
653
//        === Utilities ===
654
//
655
656
// delta_f / width_factor gives number of taps required.
657
static const float width_factor[5] = {   // indexed by win_type
658
  3.3,                        // WIN_HAMMING
659
  3.1,                        // WIN_HANN
660
  5.5,                      // WIN_BLACKMAN
661
  2.0,                  // WIN_RECTANGULAR
662
  //5.0                   // WIN_KAISER  (guesstimate compromise)
663
  //2.0                   // WIN_KAISER  (guesstimate compromise)
664
  10.0                        // WIN_KAISER
665
};
666
667
int
668
gr_firdes::compute_ntaps_windes(double sampling_freq,
669
                                 double transition_width, // this is frequency, not relative frequency
670
                                    double attenuation_dB)
671
{
672
  // Based on formula from Multirate Signal Processing for
673
  // Communications Systems, fredric j harris
674
  int ntaps = (int)(attenuation_dB*sampling_freq/(22.0*transition_width));
675
  if ((ntaps & 1) == 0)        // if even...
676
    ntaps++;                // ...make odd
677
  return ntaps;
678
}
679
680
int
681
gr_firdes::compute_ntaps (double sampling_freq,
682
                          double transition_width,
683
                          win_type window_type,
684
                          double beta)
685
{
686
  // normalized transition width
687
  double delta_f = transition_width / sampling_freq;
688
689
  // compute number of taps required for given transition width
690
  int ntaps = (int) (width_factor[window_type] / delta_f + 0.5);
691
  if ((ntaps & 1) == 0)        // if even...
692
    ntaps++;                // ...make odd
693
694
  return ntaps;
695
}
696
697
double gr_firdes::bessi0(double x)
698
{
699
        double ax,ans;
700
        double y;
701
702
        ax=fabs(x);
703
        if (ax < 3.75)
704
        {
705
                y=x/3.75;
706
                y*=y;
707
                ans=1.0+y*(3.5156229+y*(3.0899424+y*(1.2067492
708
                        +y*(0.2659732+y*(0.360768e-1+y*0.45813e-2)))));
709
        }
710
        else
711
        {
712
                y=3.75/ax;
713
                ans=(exp(ax)/sqrt(ax))*(0.39894228+y*(0.1328592e-1
714
                        +y*(0.225319e-2+y*(-0.157565e-2+y*(0.916281e-2
715
                        +y*(-0.2057706e-1+y*(0.2635537e-1+y*(-0.1647633e-1
716
                        +y*0.392377e-2))))))));
717
        }
718
        return ans;
719
}
720
vector<float>
721
gr_firdes::window (win_type type, int ntaps, double beta)
722
{
723
  vector<float> taps(ntaps);
724
  int        M = ntaps - 1;                // filter order
725
726
  switch (type){
727
  case WIN_RECTANGULAR:
728
    for (int n = 0; n < ntaps; n++)
729
      taps[n] = 1;
730
731
  case WIN_HAMMING:
732
    for (int n = 0; n < ntaps; n++)
733
      taps[n] = 0.54 - 0.46 * cos ((2 * M_PI * n) / M);
734
    break;
735
736
  case WIN_HANN:
737
    for (int n = 0; n < ntaps; n++)
738
      taps[n] = 0.5 - 0.5 * cos ((2 * M_PI * n) / M);
739
    break;
740
741
  case WIN_BLACKMAN:
742
    for (int n = 0; n < ntaps; n++)
743
      taps[n] = 0.42 - 0.50 * cos ((2*M_PI * n) / (M-1)) - 0.08 * cos ((4*M_PI * n) / (M-1));
744
    break;
745
746
  case WIN_BLACKMAN_hARRIS:
747
    for (int n = -ntaps/2; n < ntaps/2; n++)
748
      taps[n+ntaps/2] = 0.35875 + 0.48829*cos((2*M_PI * n) / (float)M) + 
749
        0.14128*cos((4*M_PI * n) / (float)M) + 0.01168*cos((6*M_PI * n) / (float)M);
750
    break;
751
752
#if 0
753
  case WIN_KAISER:
754
    for (int n = 0; n < ntaps; n++)
755
        taps[n] = bessi0(beta*sqrt(1.0 - (4.0*n/(M*M))))/bessi0(beta);
756
    break;
757
#else
758
759
  case WIN_KAISER:
760
    {
761
      double IBeta = 1.0/Izero(beta);
762
      double inm1 = 1.0/((double)(ntaps));
763
      double temp;
764
      //fprintf(stderr, "IBeta = %g; inm1 = %g\n", IBeta, inm1);
765
766
      for (int i=0; i<ntaps; i++) {
767
        temp = i * inm1;
768
        //fprintf(stderr, "temp = %g\n", temp);
769
        taps[i] = Izero(beta*sqrt(1.0-temp*temp)) * IBeta;
770
        //fprintf(stderr, "taps[%d] = %g\n", i, taps[i]);
771
      }
772
    }
773
    break;
774
775
#endif
776
  default:
777
    throw std::out_of_range ("gr_firdes:window: type out of range");
778
  }
779
780
  return taps;
781
}
782
783
void
784
gr_firdes::sanity_check_1f (double sampling_freq,
785
                            double fa,                        // cutoff freq
786
                            double transition_width)
787
{
788
  if (sampling_freq <= 0.0)
789
    throw std::out_of_range ("gr_firdes check failed: sampling_freq > 0");
790
791
  if (fa <= 0.0 || fa > sampling_freq / 2)
792
    throw std::out_of_range ("gr_firdes check failed: 0 < fa <= sampling_freq / 2");
793
  
794
  if (transition_width <= 0)
795
    throw std::out_of_range ("gr_dirdes check failed: transition_width > 0");
796
}
797
798
void
799
gr_firdes::sanity_check_2f (double sampling_freq,
800
                            double fa,                        // first cutoff freq
801
                            double fb,                        // second cutoff freq
802
                            double transition_width)
803
{
804
  if (sampling_freq <= 0.0)
805
    throw std::out_of_range ("gr_firdes check failed: sampling_freq > 0");
806
807
  if (fa <= 0.0 || fa > sampling_freq / 2)
808
    throw std::out_of_range ("gr_firdes check failed: 0 < fa <= sampling_freq / 2");
809
  
810
  if (fb <= 0.0 || fb > sampling_freq / 2)
811
    throw std::out_of_range ("gr_firdes check failed: 0 < fb <= sampling_freq / 2");
812
  
813
  if (fa > fb)
814
    throw std::out_of_range ("gr_firdes check failed: fa <= fb");
815
  
816
  if (transition_width <= 0)
817
    throw std::out_of_range ("gr_firdes check failed: transition_width > 0");
818
}
819
820
void
821
gr_firdes::sanity_check_2f_c (double sampling_freq,
822
                            double fa,                        // first cutoff freq
823
                            double fb,                        // second cutoff freq
824
                            double transition_width)
825
{
826
  if (sampling_freq <= 0.0)
827
    throw std::out_of_range ("gr_firdes check failed: sampling_freq > 0");
828
829
  if (fa < -sampling_freq / 2 || fa > sampling_freq / 2)
830
    throw std::out_of_range ("gr_firdes check failed: 0 < fa <= sampling_freq / 2");
831
  
832
  if (fb < -sampling_freq / 2  || fb > sampling_freq / 2)
833
    throw std::out_of_range ("gr_firdes check failed: 0 < fb <= sampling_freq / 2");
834
  
835
  if (fa > fb)
836
    throw std::out_of_range ("gr_firdes check failed: fa <= fb");
837
  
838
  if (transition_width <= 0)
839
    throw std::out_of_range ("gr_firdes check failed: transition_width > 0");
840
}