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