]> git.rkrishnan.org Git - dttsp.git/blob - jDttSP/spottone.c
Initial revision
[dttsp.git] / jDttSP / spottone.c
1 /* spottone.c */
2
3 #include <spottone.h>
4
5 //------------------------------------------------------------------------
6 // An ASR envelope on a complex phasor,
7 // with asynchronous trigger for R stage.
8 // A/R use sine shaping.
9 //------------------------------------------------------------------------
10
11 BOOLEAN
12 SpotTone(SpotToneGen st) {
13   int i, n = st->size;
14
15   ComplexOSC(st->osc.gen);
16
17   for (i = 0; i < n; i++) {
18
19     // in an envelope stage?
20
21     if (st->stage == SpotTone_RISE) {
22
23       // still going?
24       if (st->rise.have++ < st->rise.want) {
25         st->curr += st->rise.incr;
26         st->mul = st->scl * sin(st->curr * M_PI / 2.0);
27       } else {
28         // no, assert steady-state, force level
29         st->curr = 1.0;
30         st->mul = st->scl;
31         st->stage = SpotTone_STDY;
32         // won't come back into envelopes
33         // until FALL asserted from outside
34       }
35
36     } else if (st->stage == SpotTone_FALL) {
37
38       // still going?
39       if (st->fall.have++ < st->fall.want) {
40         st->curr -= st->fall.incr;
41         st->mul = st->scl * sin(st->curr * M_PI / 2.0);
42       } else {
43         // no, assert trailing, force level
44         st->curr = 0.0;
45         st->mul = 0.0;
46         st->stage = SpotTone_HOLD;
47         // won't come back into envelopes hereafter
48       }
49     }
50
51     // apply envelope
52     // (same base as osc.gen internal buf)
53     CXBdata(st->buf, i) = Cscl(CXBdata(st->buf, i), st->mul);
54   }
55
56   // indicate whether it's turned itself off
57   // sometime during this pass
58   
59   return st->stage != SpotTone_HOLD;
60 }
61
62 //------------------------------------------------------------------------
63 // turn spotting on with current settings
64
65 void
66 SpotToneOn(SpotToneGen st) {
67
68   // gain is in dB
69
70   st->scl = pow(10.0, st->gain / 20.0);
71   st->curr = st->mul = 0.0;
72   
73   // A/R times are in msec
74
75   st->rise.want = (int) (0.5 + st->sr * (st->rise.dur / 1e3));
76   st->rise.have = 0;
77   if (st->rise.want <= 1)
78     st->rise.incr = 1.0;
79   else
80     st->rise.incr = 1.0 / (st->rise.want - 1);
81   
82   st->fall.want = (int) (0.5 + st->sr * (st->fall.dur / 1e3));
83   st->fall.have = 0;
84   if (st->fall.want <= 1)
85     st->fall.incr = 1.0;
86   else
87     st->fall.incr = 1.0 / (st->fall.want - 1);
88
89   // freq is in Hz
90
91   OSCfreq(st->osc.gen) = 2.0 * M_PI * st->osc.freq / st->sr;
92   OSCphase(st->osc.gen) = 0.0;
93
94   st->stage = SpotTone_RISE;
95 }
96
97 //------------------------------------------------------------------------
98 // initiate turn-off
99
100 void
101 SpotToneOff(SpotToneGen st) { st->stage = SpotTone_FALL; }
102
103 //------------------------------------------------------------------------
104
105 void
106 setSpotToneGenVals(SpotToneGen st,
107                    REAL gain,
108                    REAL freq,
109                    REAL rise,
110                    REAL fall) {
111   st->gain = gain;
112   st->osc.freq = freq;
113   st->rise.dur = rise;
114   st->fall.dur = fall;
115 }
116
117 SpotToneGen
118 newSpotToneGen(REAL gain,       // dB
119                REAL freq,
120                REAL rise,       // ms
121                REAL fall,       // ms
122                int size,
123                REAL samplerate) {
124
125   SpotToneGen st = (SpotToneGen) safealloc(1,
126                                            sizeof(SpotToneGenDesc),
127                                            "SpotToneGenDesc");
128
129   setSpotToneGenVals(st, gain, freq, rise, fall);
130   st->size = size;
131   st->sr = samplerate;
132
133   st->osc.gen = newOSC(st->size,
134                        ComplexTone,
135                        st->osc.freq,
136                        0.0,
137                        st->sr,
138                        "SpotTone osc");
139
140   // overload oscillator buf
141   st->buf = newCXB(st->size, OSCCbase(st->osc.gen), "SpotToneGen buf");
142
143   return st;
144 }
145
146 void
147 delSpotToneGen(SpotToneGen st) {
148   if (st) {
149     delCXB(st->buf);
150     delOSC(st->osc.gen);
151     safefree((char *) st);
152   }
153 }