1 /*
2 * Copyright (c) 2007 - 2015 Joseph Gaeddert
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 * THE SOFTWARE.
21 */
22
23 #include <assert.h>
24 #include "autotest/autotest.h"
25 #include "liquid.h"
26
27 // Helper function to keep code base small
firpfbch2_crcf_runtest(unsigned int _M,unsigned int _m,float _As)28 void firpfbch2_crcf_runtest(unsigned int _M,
29 unsigned int _m,
30 float _As)
31 {
32 float tol = 1e-3f;
33 unsigned int i;
34
35 // derived values
36 unsigned int num_symbols = 8*_m; // number of symbols
37 unsigned int num_samples = _M * num_symbols;
38
39 // allocate arrays
40 float complex x[num_samples];
41 float complex y[num_samples];
42
43 // generate pseudo-random sequence
44 unsigned int s = 1; // seed
45 unsigned int p = 524287; // large prime number
46 unsigned int g = 1031; // another large prime number
47 for (i=0; i<num_samples; i++) {
48 s = (s * p) % g;
49 x[i] = (float)s / (float)g - 0.5f;
50 //x[i] = (i==0) ? 1.0f : 0.0f; // impulse response
51 }
52
53 // create filterbank objects from prototype
54 firpfbch2_crcf qa = firpfbch2_crcf_create_kaiser(LIQUID_ANALYZER, _M, _m, _As);
55 firpfbch2_crcf qs = firpfbch2_crcf_create_kaiser(LIQUID_SYNTHESIZER, _M, _m, _As);
56
57 // run channelizer
58 float complex Y[_M];
59 for (i=0; i<num_samples; i+=_M/2) {
60 // run analysis filterbank
61 firpfbch2_crcf_execute(qa, &x[i], Y);
62
63 // run synthesis filterbank
64 firpfbch2_crcf_execute(qs, Y, &y[i]);
65 }
66
67 // destroy filterbank objects
68 firpfbch2_crcf_destroy(qa); // analysis filterbank
69 firpfbch2_crcf_destroy(qs); // synthesis filterbank
70
71 // validate output
72 unsigned int delay = 2*_M*_m - _M/2 + 1;
73 float rmse = 0.0f;
74 for (i=0; i<num_samples; i++) {
75 //printf("%3u : %12.8f + %12.8fj\n", i, crealf(y[i]), cimagf(y[i]));
76 if (i < delay) {
77 CONTEND_DELTA( crealf(y[i]), 0.0f, tol );
78 CONTEND_DELTA( cimagf(y[i]), 0.0f, tol );
79 } else {
80 CONTEND_DELTA( crealf(y[i]), crealf(x[i-delay]), tol );
81 CONTEND_DELTA( cimagf(y[i]), cimagf(x[i-delay]), tol );
82 }
83
84 // compute rmse
85 float complex err = y[i] - (i < delay ? 0.0f : x[i-delay]);
86 rmse += crealf(err * conjf(err));
87 }
88
89 rmse = sqrtf(rmse / (float)num_samples);
90 if (liquid_autotest_verbose)
91 printf("firpfbch2: M=%3u, m=%2u, As=%8.2f dB, rmse=%12.4e\n", _M, _m, _As, rmse);
92 }
93
94 // analysis
autotest_firpfbch2_crcf_n8()95 void autotest_firpfbch2_crcf_n8() { firpfbch2_crcf_runtest( 8, 5, 60.0f); }
autotest_firpfbch2_crcf_n16()96 void autotest_firpfbch2_crcf_n16() { firpfbch2_crcf_runtest( 16, 5, 60.0f); }
autotest_firpfbch2_crcf_n32()97 void autotest_firpfbch2_crcf_n32() { firpfbch2_crcf_runtest( 32, 5, 60.0f); }
autotest_firpfbch2_crcf_n64()98 void autotest_firpfbch2_crcf_n64() { firpfbch2_crcf_runtest( 64, 5, 60.0f); }
99
100