]> git.rkrishnan.org Git - dttsp.git/blob - jDttSP/cwtones.c
Bug fixes to jsdr, keyer
[dttsp.git] / jDttSP / cwtones.c
1 /* cwtones.c */
2 /*
3 This file is part of a program that implements a Software-Defined Radio.
4
5 Copyright (C) 2005 by Frank Brickle, AB2KT and Bob McGwier, N4HY
6
7 This program 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 2 of the License, or
10 (at your option) any later version.
11
12 This program 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 this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20
21 The authors can be reached by email at
22
23 ab2kt@arrl.net
24 or
25 rwmcgwier@comcast.net
26
27 or by paper mail at
28
29 The DTTS Microwave Society
30 6 Kathleen Place
31 Bridgewater, NJ 08807
32 */
33
34 #include <cwtones.h>
35
36 //------------------------------------------------------------------------
37 // An ASR envelope on a complex phasor,
38 // with asynchronous trigger for R stage.
39 // A/R use sine shaping.
40 //------------------------------------------------------------------------
41
42 BOOLEAN
43 CWTone(CWToneGen cwt) {
44   int i, n = cwt->size;
45
46   ComplexOSC(cwt->osc.gen);
47
48   for (i = 0; i < n; i++) {
49
50     // in an envelope stage?
51
52     if (cwt->stage == CWTone_RISE) {
53
54       // still going?
55       if (cwt->rise.have++ < cwt->rise.want) {
56         cwt->curr += cwt->rise.incr;
57         cwt->mul = cwt->scl * sin(cwt->curr * M_PI / 2.0);
58       } else {
59         // no, assert steady-state, force level
60         cwt->curr = 1.0;
61         cwt->mul = cwt->scl;
62         cwt->stage = CWTone_STDY;
63         // won't come back into envelopes
64         // until FALL asserted from outside
65       }
66
67     } else if (cwt->stage == CWTone_FALL) {
68
69       // still going?
70       if (cwt->fall.have++ < cwt->fall.want) {
71         cwt->curr -= cwt->fall.incr;
72         cwt->mul = cwt->scl * sin(cwt->curr * M_PI / 2.0);
73       } else {
74         // no, assert trailing, force level
75         cwt->curr = 0.0;
76         cwt->mul = 0.0;
77         cwt->stage = CWTone_HOLD;
78         // won't come back into envelopes hereafter
79       }
80     }
81
82     // apply envelope
83     // (same base as osc.gen internal buf)
84     CXBdata(cwt->buf, i) = Cscl(CXBdata(cwt->buf, i), cwt->mul);
85   }
86
87   // indicate whether it's turned itself off
88   // sometime during this pass
89   
90   return cwt->stage != CWTone_HOLD;
91 }
92
93 //------------------------------------------------------------------------
94 // turn tone on with current settings
95
96 void
97 CWToneOn(CWToneGen cwt) {
98
99   // gain is in dB
100
101   cwt->scl = pow(10.0, cwt->gain / 20.0);
102   cwt->curr = cwt->mul = 0.0;
103   
104   // A/R times are in msec
105
106   cwt->rise.want = (int) (0.5 + cwt->sr * (cwt->rise.dur / 1e3));
107   cwt->rise.have = 0;
108   if (cwt->rise.want <= 1)
109     cwt->rise.incr = 1.0;
110   else
111     cwt->rise.incr = 1.0 / (cwt->rise.want - 1);
112   
113   cwt->fall.want = (int) (0.5 + cwt->sr * (cwt->fall.dur / 1e3));
114   cwt->fall.have = 0;
115   if (cwt->fall.want <= 1)
116     cwt->fall.incr = 1.0;
117   else
118     cwt->fall.incr = 1.0 / (cwt->fall.want - 1);
119
120   // freq is in Hz
121
122   OSCfreq(cwt->osc.gen) = 2.0 * M_PI * cwt->osc.freq / cwt->sr;
123   OSCphase(cwt->osc.gen) = 0.0;
124
125   cwt->stage = CWTone_RISE;
126 }
127
128 //------------------------------------------------------------------------
129 // initiate turn-off
130
131 void
132 CWToneOff(CWToneGen cwt) { cwt->stage = CWTone_FALL; }
133
134 //------------------------------------------------------------------------
135
136 void
137 setCWToneGenVals(CWToneGen cwt,
138                  REAL gain,
139                  REAL freq,
140                  REAL rise,
141                  REAL fall) {
142   cwt->gain = gain;
143   cwt->osc.freq = freq;
144   cwt->rise.dur = rise;
145   cwt->fall.dur = fall;
146 }
147
148 CWToneGen
149 newCWToneGen(REAL gain, // dB
150              REAL freq,
151              REAL rise, // ms
152              REAL fall, // ms
153              int size,
154              REAL samplerate) {
155
156   CWToneGen cwt = (CWToneGen) safealloc(1, sizeof(CWToneGenDesc),
157                                        "CWToneGenDesc");
158
159   setCWToneGenVals(cwt, gain, freq, rise, fall);
160   cwt->size = size;
161   cwt->sr = samplerate;
162
163   cwt->osc.gen = newOSC(cwt->size,
164                         ComplexTone,
165                         cwt->osc.freq,
166                         0.0,
167                         cwt->sr,
168                         "CWTone osc");
169
170   // overload oscillator buf
171   cwt->buf = newCXB(cwt->size, OSCCbase(cwt->osc.gen), "CWToneGen buf");
172
173   return cwt;
174 }
175
176 void
177 delCWToneGen(CWToneGen cwt) {
178   if (cwt) {
179     delCXB(cwt->buf);
180     delOSC(cwt->osc.gen);
181     safefree((char *) cwt);
182   }
183 }