tomwalters@0
|
1 /*
|
tomwalters@0
|
2 ramp.c generate an exponential sawtooth waveform
|
tomwalters@0
|
3 ------ (in binary shorts or floats).
|
tomwalters@0
|
4
|
tomwalters@0
|
5 Generate samples of a sawtooth waveform at a given sample rate.
|
tomwalters@0
|
6
|
tomwalters@0
|
7 Decaying exponential: A.exp(-t) 0<=t<=T
|
tomwalters@0
|
8 Growing exponential: A.exp(t) -T<=t<=0
|
tomwalters@0
|
9 or (shifting): A.exp(t-T) 0<=t<=T
|
tomwalters@0
|
10
|
tomwalters@0
|
11 To arrange for a decay factor to correspond to the half life, so that
|
tomwalters@0
|
12 the wave grows/decays to half the given amplitude in the given decay time,
|
tomwalters@0
|
13 the argument of the exponential must be calibrated to result in 0.5.
|
tomwalters@0
|
14 If exp(-x) = 0.5, then we have -x = ln(0.5) = -0.693147
|
tomwalters@0
|
15 so that: x = 0.693147
|
tomwalters@0
|
16 For a given decay factor, the damped exponential decays to half the given
|
tomwalters@0
|
17 amplitude in this time. The ramped exponential is a time-reversed damped
|
tomwalters@0
|
18 exponential.
|
tomwalters@0
|
19
|
tomwalters@0
|
20
|
tomwalters@0
|
21 Examples:
|
tomwalters@0
|
22
|
tomwalters@0
|
23 1. Growing exponentials
|
tomwalters@0
|
24
|
tomwalters@0
|
25 ramp polarity=ramp dec=1ms | x11plot
|
tomwalters@0
|
26
|
tomwalters@0
|
27 2. Decaying exponentials
|
tomwalters@0
|
28
|
tomwalters@0
|
29 ramp polarity=damp dec=1ms | x11plot
|
tomwalters@0
|
30
|
tomwalters@0
|
31 3. Half a cycle of an 8ms decaying exponential.
|
tomwalters@0
|
32
|
tomwalters@0
|
33 ramp polarity=damp dec=1ms dur=4ms | x11plot
|
tomwalters@0
|
34
|
tomwalters@0
|
35 4. Modulating a tone with a damped exponential.
|
tomwalters@0
|
36
|
tomwalters@0
|
37 tone period=.5ms amp=500 type=float > foo1
|
tomwalters@0
|
38 ramp pol=damp dec=1ms amp=1 type=float > foo2
|
tomwalters@0
|
39 merge op=mult type=float foo1 foo2 | ftos | x11plot -n512
|
tomwalters@0
|
40
|
tomwalters@0
|
41 5. Modulating a tone with a ramped exponential.
|
tomwalters@0
|
42
|
tomwalters@0
|
43 tone period=.5ms amp=500 type=float > foo1
|
tomwalters@0
|
44 ramp pol=ramp dec=1ms amp=1 type=float > foo2
|
tomwalters@0
|
45 merge op=mult type=float foo1 foo2 | ftos | x11plot -n512
|
tomwalters@0
|
46
|
tomwalters@0
|
47 6. Modulating a tone with a damped exponential, and half-wave rectifying to
|
tomwalters@0
|
48 generate damped pulses.
|
tomwalters@0
|
49
|
tomwalters@0
|
50 tone period=.5ms amp=500 type=float > foo1
|
tomwalters@0
|
51 ramp pol=damp dec=1ms amp=1 type=float > foo2
|
tomwalters@0
|
52 merge op=mult type=float foo1 foo2 | ftos | gate range=min-0 op=0 | x11plot -n512
|
tomwalters@0
|
53
|
tomwalters@0
|
54 7. Modulating white noise with a ramped exponential.
|
tomwalters@0
|
55
|
tomwalters@0
|
56 noise type=float > foo1
|
tomwalters@0
|
57 ramp pol=ramp dec=1ms amp=1 type=float > foo2
|
tomwalters@0
|
58 merge op=mult type=float foo1 foo2 | ftos | x11plot -n512
|
tomwalters@0
|
59
|
tomwalters@0
|
60
|
tomwalters@0
|
61 */
|
tomwalters@0
|
62
|
tomwalters@0
|
63 #include <stdio.h>
|
tomwalters@0
|
64 #include <math.h>
|
tomwalters@0
|
65 #include "options.h"
|
tomwalters@0
|
66 #include "units.h"
|
tomwalters@0
|
67 #include "strmatch.h"
|
tomwalters@0
|
68
|
tomwalters@0
|
69 char applic[] = "generate an exponential sawtooth waveform. " ;
|
tomwalters@0
|
70 char usage[] = "ramp [options]" ;
|
tomwalters@0
|
71
|
tomwalters@0
|
72 static char *helpstr, *debugstr, *sampstr, *perstr, *astr, *decstr, *polstr, *dstr, *datastr ;
|
tomwalters@0
|
73
|
tomwalters@0
|
74 static Options option[] = {
|
tomwalters@0
|
75 { "help" , "off" , &helpstr , "help" , DEBUG },
|
tomwalters@0
|
76 { "debug" , "off" , &debugstr , "debugging switch" , DEBUG },
|
tomwalters@0
|
77 { "samplerate", "20kHz" , &sampstr , "samplerate " , VAL },
|
tomwalters@0
|
78 { "period" , "8ms" , &perstr , "period [s,ms,p] of ramp" , VAL },
|
tomwalters@0
|
79 { "amplitude" , "1024" , &astr , "amplitude of waveform" , VAL },
|
tomwalters@0
|
80 { "decay" , "2ms" , &decstr , "half-life of ramp" , VAL },
|
tomwalters@0
|
81 { "polarity" , "ramp" , &polstr , "ramp (growing) / damp (decaying)", VAL },
|
tomwalters@0
|
82 { "duration" , "500ms" , &dstr , "duration of waveform" , VAL },
|
tomwalters@0
|
83 { "type" , "short" , &datastr , "o/p datatype (short/float)", VAL },
|
tomwalters@0
|
84 ( char * ) 0 } ;
|
tomwalters@0
|
85
|
tomwalters@0
|
86
|
tomwalters@0
|
87 #define DECAYFACTOR ( 0.693147 )
|
tomwalters@0
|
88
|
tomwalters@0
|
89 int samplerate ;
|
tomwalters@0
|
90 float amplitude ;
|
tomwalters@0
|
91 int duration ;
|
tomwalters@0
|
92 int period ;
|
tomwalters@0
|
93 int decay ;
|
tomwalters@0
|
94 double decayrate ;
|
tomwalters@0
|
95
|
tomwalters@0
|
96 main(argc, argv)
|
tomwalters@0
|
97 int argc ;
|
tomwalters@0
|
98 char *argv[] ;
|
tomwalters@0
|
99 {
|
tomwalters@0
|
100 int i, n, t ;
|
tomwalters@0
|
101 short s ;
|
tomwalters@0
|
102 float f ;
|
tomwalters@0
|
103
|
tomwalters@0
|
104 getopts( option,argc,argv ) ;
|
tomwalters@0
|
105 if ( !isoff( helpstr ) )
|
tomwalters@0
|
106 helpopts3( helpstr, argv[0], applic, usage, option ) ;
|
tomwalters@0
|
107
|
tomwalters@0
|
108 samplerate = to_Hz( sampstr, 0 ) ;
|
tomwalters@0
|
109 amplitude = atof( astr ) ;
|
tomwalters@0
|
110 period = (int)to_p( perstr, samplerate ) ;
|
tomwalters@0
|
111 decay = (int)to_p( decstr, samplerate ) ;
|
tomwalters@0
|
112 duration = to_p( dstr, samplerate ) ;
|
tomwalters@0
|
113
|
tomwalters@0
|
114 /*
|
tomwalters@0
|
115 if ( decay >= period ) {
|
tomwalters@0
|
116 fprintf(stderr,"ramp: half-life period [%dp] must be less than waveform period [%dp]\n", decay, period);
|
tomwalters@0
|
117 exit( 1 ) ;
|
tomwalters@0
|
118 }
|
tomwalters@0
|
119 */
|
tomwalters@0
|
120 decayrate = DECAYFACTOR / (double)decay ;
|
tomwalters@0
|
121
|
tomwalters@0
|
122 if ( iststr( polstr, "damped" ) ) {
|
tomwalters@0
|
123
|
tomwalters@0
|
124 /* Decaying exponential */
|
tomwalters@0
|
125
|
tomwalters@0
|
126 if ( iststr( datastr, "short" ) )
|
tomwalters@0
|
127 for ( i=0 ; i<duration ; )
|
tomwalters@0
|
128 for ( t=0 ; t<period && i<duration ; t++, i++ ) {
|
tomwalters@0
|
129 s = amplitude * exp( - (double)( t * decayrate ) ) ;
|
tomwalters@0
|
130 fwrite( &s, sizeof(short), 1, stdout ) ;
|
tomwalters@0
|
131 }
|
tomwalters@0
|
132 else if ( iststr( datastr, "float" ) )
|
tomwalters@0
|
133 for ( i=0 ; i<duration ; )
|
tomwalters@0
|
134 for ( t=0 ; t<period && i<duration ; t++, i++ ) {
|
tomwalters@0
|
135 f = amplitude * exp( - (double)( t * decayrate ) ) ;
|
tomwalters@0
|
136 fwrite( &f, sizeof(float), 1, stdout ) ;
|
tomwalters@0
|
137 }
|
tomwalters@0
|
138 else
|
tomwalters@0
|
139 fprintf(stderr,"unknown datatype [%s]\n", datastr) ;
|
tomwalters@0
|
140 }
|
tomwalters@0
|
141 else if ( iststr( polstr, "ramped" ) ) {
|
tomwalters@0
|
142
|
tomwalters@0
|
143 /* Growing exponential */
|
tomwalters@0
|
144
|
tomwalters@0
|
145 if ( iststr( datastr, "short" ) )
|
tomwalters@0
|
146 for ( i=0 ; i<duration ; )
|
tomwalters@0
|
147 for ( t=(-period) ; t<=0 && i<duration ; t++, i++ ) {
|
tomwalters@0
|
148 s = amplitude * exp( (double)( t * decayrate ) ) ;
|
tomwalters@0
|
149 fwrite( &s, sizeof(short), 1, stdout ) ;
|
tomwalters@0
|
150 }
|
tomwalters@0
|
151 else if ( iststr( datastr, "float" ) )
|
tomwalters@0
|
152 for ( i=0 ; i<duration ; )
|
tomwalters@0
|
153 for ( t=(-period) ; t<=0 && i<duration ; t++, i++ ) {
|
tomwalters@0
|
154 f = amplitude * exp( (double)( t * decayrate ) ) ;
|
tomwalters@0
|
155 fwrite( &f, sizeof(float), 1, stdout ) ;
|
tomwalters@0
|
156 }
|
tomwalters@0
|
157 else
|
tomwalters@0
|
158 fprintf(stderr,"unknown datatype [%s]\n", datastr) ;
|
tomwalters@0
|
159 }
|
tomwalters@0
|
160 else
|
tomwalters@0
|
161 fprintf( stderr, "unknown polarity [%s]\n", polstr ) ;
|
tomwalters@0
|
162 }
|