1 // ----------------------------------------------------------------------------
2 // tune.cxx -- create a single sinewave output with controlled start/end shape
3 //
4 // Copyright (C) 2006-2007
5 // Dave Freese, W1HKJ
6 //
7 // This file is part of fldigi.
8 //
9 // Fldigi is free software: you can redistribute it and/or modify
10 // it under the terms of the GNU General Public License as published by
11 // the Free Software Foundation, either version 3 of the License, or
12 // (at your option) any later version.
13 //
14 // Fldigi is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 // GNU General Public License for more details.
18 //
19 // You should have received a copy of the GNU General Public License
20 // along with fldigi. If not, see <http://www.gnu.org/licenses/>.
21 // ----------------------------------------------------------------------------
22
23 #include <math.h>
24 #include "sound.h"
25 #include "confdialog.h"
26
27 #include "test_signal.h"
28
29 namespace xmttune {
30
31 // use same wave shaping for tune key down / key up as for the CW tx_process
32 // produces a 4 msec leading / trailing edge
33 #define KNUM 32
34 // keydown wave shape
35
36 double kdshape[KNUM] = {
37 0.00240750255310301, 0.00960708477768751,
38 0.02152941088003600, 0.03805966253618680,
39 0.05903864465505320, 0.08426431851158830,
40 0.11349374748686800, 0.14644543667658500,
41 0.18280204383628200, 0.22221343555548300,
42 0.26430005922814900, 0.30865659834558700,
43 0.35485587590940700, 0.40245296837259500,
44 0.45098949048925500, 0.49999800980765500,
45 0.54900654829266300, 0.59754312772456200,
46 0.64514031509964400, 0.69133972425796200,
47 0.73569643038517400, 0.77778325487450100,
48 0.81719487928327800, 0.85355174876454100,
49 0.88650372738152000, 0.91573347010241700,
50 0.94095947900139100, 0.96193881423287900,
51 0.97846943367117300, 0.99039213868324900,
52 0.99759210729604500, 0.99999999999295900
53 };
54
55 // keyup wave shape
56 double kushape[KNUM] = {
57 0.99999999999295900, 0.99759210729604500,
58 0.99039213868324900, 0.97846943367117300,
59 0.96193881423287900, 0.94095947900139100,
60 0.91573347010241700, 0.88650372738152000,
61 0.85355174876454100, 0.81719487928327800,
62 0.77778325487450100, 0.73569643038517400,
63 0.69133972425796200, 0.64514031509964400,
64 0.59754312772456200, 0.54900654829266300,
65 0.49999800980765500, 0.45098949048925500,
66 0.40245296837259500, 0.35485587590940700,
67 0.30865659834558700, 0.26430005922814900,
68 0.22221343555548300, 0.18280204383628200,
69 0.14644543667658500, 0.11349374748686800,
70 0.08426431851158830, 0.05903864465505320,
71 0.03805966253618680, 0.02152941088003600,
72 0.00960708477768751, 0.00240750255310301
73 };
74
75 #define BUFLEN 512
76 double phaseacc = 0.0;
77 double phaseincr = 0.0;
78 double pttacc = 0.0;
79 double outbuf[BUFLEN];
80 double pttbuf[BUFLEN];
81
82 //===========================================================================
83
nco()84 inline double nco()
85 {
86 phaseacc += phaseincr;
87 if (phaseacc > TWOPI) phaseacc -= TWOPI;
88 return cos(phaseacc);
89 }
90
pttnco()91 inline double pttnco()
92 {
93 pttacc += TWOPI * 1000 / active_modem->get_samplerate();
94 if (pttacc > TWOPI) pttacc -= TWOPI;
95 return sin(pttacc);
96 }
97
98
99 //=====================================================================
100
101
102 //=====================================================================
103
keydown(double freq,SoundBase * scard)104 void keydown(double freq, SoundBase *scard)
105 {
106 int i;
107 phaseincr = 2.0 * M_PI * freq / active_modem->get_samplerate();
108 for (i = 0; i < KNUM; i++){
109 outbuf[i] = nco() * kdshape[i];
110 pttbuf[i] = pttnco();
111 }
112 for (; i < BUFLEN; i++) {
113 outbuf[i] = nco();
114 pttbuf[i] = pttnco();
115 }
116 if ((active_modem == cw_modem) && progdefaults.QSK) {
117 active_modem->ModulateStereo(
118 outbuf, pttbuf,
119 BUFLEN, false);
120 } else {
121 active_modem->ModulateXmtr(outbuf, BUFLEN);
122 }
123 }
124
125 //=====================================================================
126
keyup(double freq,SoundBase * scard)127 void keyup(double freq, SoundBase *scard)
128 {
129 int i;
130 phaseincr = 2.0 * M_PI * freq / active_modem->get_samplerate();
131 for (i = 0; i < KNUM; i++) {
132 outbuf[i] = nco() * kushape[i];
133 pttbuf[i] = pttnco();
134 }
135 for (; i < BUFLEN; i++) {
136 outbuf[i] = 0.0;
137 pttbuf[i] = pttnco();
138 }
139 if ((active_modem == cw_modem) && progdefaults.QSK) {
140 active_modem->ModulateStereo(
141 outbuf, pttbuf,
142 BUFLEN, false);
143 } else {
144 active_modem->ModulateXmtr(outbuf, BUFLEN);
145 }
146 }
147
148 //=====================================================================
149
tune(double freq,SoundBase * scard)150 void tune(double freq, SoundBase *scard)
151 {
152 int i;
153
154 if (test_signal_window && test_signal_window->visible() && btnOffsetOn->value())
155 freq += ctrl_freq_offset->value();
156
157 phaseincr = 2.0 * M_PI * freq / active_modem->get_samplerate();
158
159 for (i = 0; i < BUFLEN; i++) {
160 outbuf[i] = nco();
161 pttbuf[i] = pttnco();
162 }
163 if ((active_modem == cw_modem) && progdefaults.QSK) {
164 active_modem->ModulateStereo(
165 outbuf, pttbuf,
166 BUFLEN, false);
167 } else {
168 active_modem->ModulateXmtr(outbuf, BUFLEN);
169 }
170 }
171
172 }; // namespace tune
173