4 This file is part of a program that implements a Software-Defined Radio.
6 Copyright (C) 2004 by Frank Brickle, AB2KT and Bob McGwier, N4HY
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 The authors can be reached by email at
30 The DTTS Microwave Society
37 //------------------------------------------------------------------------
38 // An ASR envelope on a complex phasor,
39 // with asynchronous trigger for R stage.
40 // A/R use sine shaping.
41 //------------------------------------------------------------------------
44 SpotTone(SpotToneGen st) {
47 ComplexOSC(st->osc.gen);
49 for (i = 0; i < n; i++) {
51 // in an envelope stage?
53 if (st->stage == SpotTone_RISE) {
56 if (st->rise.have++ < st->rise.want) {
57 st->curr += st->rise.incr;
58 st->mul = st->scl * sin(st->curr * M_PI / 2.0);
60 // no, assert steady-state, force level
63 st->stage = SpotTone_STDY;
64 // won't come back into envelopes
65 // until FALL asserted from outside
68 } else if (st->stage == SpotTone_FALL) {
71 if (st->fall.have++ < st->fall.want) {
72 st->curr -= st->fall.incr;
73 st->mul = st->scl * sin(st->curr * M_PI / 2.0);
75 // no, assert trailing, force level
78 st->stage = SpotTone_HOLD;
79 // won't come back into envelopes hereafter
84 // (same base as osc.gen internal buf)
85 CXBdata(st->buf, i) = Cscl(CXBdata(st->buf, i), st->mul);
88 // indicate whether it's turned itself off
89 // sometime during this pass
91 return st->stage != SpotTone_HOLD;
94 //------------------------------------------------------------------------
95 // turn spotting on with current settings
98 SpotToneOn(SpotToneGen st) {
102 st->scl = pow(10.0, st->gain / 20.0);
103 st->curr = st->mul = 0.0;
105 // A/R times are in msec
107 st->rise.want = (int) (0.5 + st->sr * (st->rise.dur / 1e3));
109 if (st->rise.want <= 1)
112 st->rise.incr = 1.0 / (st->rise.want - 1);
114 st->fall.want = (int) (0.5 + st->sr * (st->fall.dur / 1e3));
116 if (st->fall.want <= 1)
119 st->fall.incr = 1.0 / (st->fall.want - 1);
123 OSCfreq(st->osc.gen) = 2.0 * M_PI * st->osc.freq / st->sr;
124 OSCphase(st->osc.gen) = 0.0;
126 st->stage = SpotTone_RISE;
129 //------------------------------------------------------------------------
133 SpotToneOff(SpotToneGen st) { st->stage = SpotTone_FALL; }
135 //------------------------------------------------------------------------
138 setSpotToneGenVals(SpotToneGen st,
150 newSpotToneGen(REAL gain, // dB
157 SpotToneGen st = (SpotToneGen) safealloc(1,
158 sizeof(SpotToneGenDesc),
161 setSpotToneGenVals(st, gain, freq, rise, fall);
165 st->osc.gen = newOSC(st->size,
172 // overload oscillator buf
173 st->buf = newCXB(st->size, OSCCbase(st->osc.gen), "SpotToneGen buf");
179 delSpotToneGen(SpotToneGen st) {
183 safefree((char *) st);