1 // ----------------------------------------------------------------------------
2 // pskeval.cxx  --  psk signal evaluator
3 //
4 // Copyright (C) 2008-2009
5 //		Dave Freese, W1HKJ
6 //
7 // This file is part of fldigi.  Adapted from code contained in gmfsk source code
8 // distribution.
9 //
10 // Fldigi is free software: you can redistribute it and/or modify
11 // it under the terms of the GNU General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // Fldigi is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 // GNU General Public License for more details.
19 //
20 // You should have received a copy of the GNU General Public License
21 // along with fldigi.  If not, see <http://www.gnu.org/licenses/>.
22 // ----------------------------------------------------------------------------
23 
24 #include <config.h>
25 
26 #include "fl_digi.h"
27 #include "pskeval.h"
28 #include "configuration.h"
29 #include "misc.h"
30 
31 using namespace std;
32 //=============================================================================
33 //========================== psk signal evaluation ============================
34 //=============================================================================
35 
pskeval()36 pskeval::pskeval() {
37 	bw = 31.25;
38 	clear();
39 }
40 
~pskeval()41 pskeval::~pskeval() {
42 }
43 
44 int countdown = 8;
45 int rows = 0;
46 
sigdensity()47 void pskeval::sigdensity() {
48 	int ihbw = (int)(0.6*bw);
49 	int ibw = 2 * ihbw;
50 
51 	double *vals = new double[ibw];
52 	double sig = 0.0;
53 	double val = 0.0;
54 
55 	int low = progdefaults.LowFreqCutoff;
56 	if (low < ihbw) low = ihbw;
57 	int high = progdefaults.HighFreqCutoff;
58 	if (high > WF_FFTLEN - ihbw) high = WF_FFTLEN - ihbw;
59 	int nbr = high - low;
60 
61 	sigmin = 1e6;
62 
63 	for (int i = 0; i < ibw; i++) {
64 		val = vals[i] = wf->Pwr(i + low - ihbw);
65 		sig += val;
66 	}
67 	for (int i = 0, j = 0; i < nbr; i++) {
68 		sigpwr[i + low] = decayavg(sigpwr[i + low], sig, 32);
69 		sig -= vals[j];
70 		val = vals[j] = wf->Pwr(i + ihbw + low);
71 		sig += val;
72 		if (++j == ibw) j = 0;
73 		if (sig < sigmin) sigmin = sig;
74 	}
75 
76 	if (sigmin < 1e-8) sigmin = 1e-8;
77 	delete [] vals;
78 }
79 
sigpeak(int & f,int f1,int f2)80 double pskeval::sigpeak(int &f, int f1, int f2)
81 {
82 	double peak = 0;
83 	f1 -= bw;
84 	if (f1 <= progdefaults.LowFreqCutoff) f1 = progdefaults.LowFreqCutoff;
85 	f2 += bw;
86 	if (f2 >= progdefaults.HighFreqCutoff) f2 = progdefaults.HighFreqCutoff;
87 
88 	int fa = f2, fb = f1;
89 
90 	for (int i = f1; i < f2; i++) if (sigpwr[i] > peak) peak = sigpwr[i];
91 	if (!peak) return 0;
92 	for (int i = f1; i < f2; i++)
93 		if (sigpwr[i] > peak*0.75) fb = i;
94 	for (int i = f2; i > f1; i--)
95 		if (sigpwr[i] > peak*0.75) fa = i;
96 	if (fa > fb) return 0;
97 	f = (fa + fb) / 2;
98 	return peak / sigmin / bw;
99 }
100 
peak(int & f0,int f1,int f2,double db)101 double pskeval::peak(int &f0, int f1, int f2, double db)
102 {
103 	double peak = 0;
104 
105 	int fa = f2, fb = f1;
106 	double level = pow(10, (10 + db) / 10.0);
107 
108 //step 1
109 	for (int i = f1; i < f2; i++) if (sigpwr[i] > peak) peak = sigpwr[i];
110 
111 	if (((peak-sigmin) / sigmin ) < level) {
112 		return 0;
113 	}
114 
115 	for (int i = f1; i < f2; i++)
116 		if (sigpwr[i] > peak*0.75) fb = i;
117 	for (int i = f2; i > f1; i--)
118 		if (sigpwr[i] > peak*0.75) fa = i;
119 	if (fa > fb) {
120 		return 0;
121 	}
122 	f0 = (fa + fb) / 2;
123 //step 2
124 	f1 = f0 - 1.5*bw;
125 	if (f1 < bw) f1 = bw;
126 	f2 = f0 + 1.5*bw;
127 	fb = f1; fa = f2;
128 	peak = 0;
129 	for (int i = f1; i < f2; i++) if (sigpwr[i] > peak) peak = sigpwr[i];
130 	for (int i = f1; i < f2; i++)
131 		if (sigpwr[i] > peak*0.75) fb = i;
132 	for (int i = f2; i > f1; i--)
133 		if (sigpwr[i] > peak*0.75) fa = i;
134 	if (fa > fb) {
135 		return 0;
136 	}
137 	f0 = (fa + fb) / 2;
138 	return (peak - sigmin) / sigmin ;
139 }
140 
clear()141 void pskeval::clear() {
142 	for (int i = 0; i < WF_FFTLEN; i++) sigpwr[i] = 0.0;
143 }
144