tomwalters@0: /* tomwalters@0: ramp.c generate an exponential sawtooth waveform tomwalters@0: ------ (in binary shorts or floats). tomwalters@0: tomwalters@0: Generate samples of a sawtooth waveform at a given sample rate. tomwalters@0: tomwalters@0: Decaying exponential: A.exp(-t) 0<=t<=T tomwalters@0: Growing exponential: A.exp(t) -T<=t<=0 tomwalters@0: or (shifting): A.exp(t-T) 0<=t<=T tomwalters@0: tomwalters@0: To arrange for a decay factor to correspond to the half life, so that tomwalters@0: the wave grows/decays to half the given amplitude in the given decay time, tomwalters@0: the argument of the exponential must be calibrated to result in 0.5. tomwalters@0: If exp(-x) = 0.5, then we have -x = ln(0.5) = -0.693147 tomwalters@0: so that: x = 0.693147 tomwalters@0: For a given decay factor, the damped exponential decays to half the given tomwalters@0: amplitude in this time. The ramped exponential is a time-reversed damped tomwalters@0: exponential. tomwalters@0: tomwalters@0: tomwalters@0: Examples: tomwalters@0: tomwalters@0: 1. Growing exponentials tomwalters@0: tomwalters@0: ramp polarity=ramp dec=1ms | x11plot tomwalters@0: tomwalters@0: 2. Decaying exponentials tomwalters@0: tomwalters@0: ramp polarity=damp dec=1ms | x11plot tomwalters@0: tomwalters@0: 3. Half a cycle of an 8ms decaying exponential. tomwalters@0: tomwalters@0: ramp polarity=damp dec=1ms dur=4ms | x11plot tomwalters@0: tomwalters@0: 4. Modulating a tone with a damped exponential. tomwalters@0: tomwalters@0: tone period=.5ms amp=500 type=float > foo1 tomwalters@0: ramp pol=damp dec=1ms amp=1 type=float > foo2 tomwalters@0: merge op=mult type=float foo1 foo2 | ftos | x11plot -n512 tomwalters@0: tomwalters@0: 5. Modulating a tone with a ramped exponential. tomwalters@0: tomwalters@0: tone period=.5ms amp=500 type=float > foo1 tomwalters@0: ramp pol=ramp dec=1ms amp=1 type=float > foo2 tomwalters@0: merge op=mult type=float foo1 foo2 | ftos | x11plot -n512 tomwalters@0: tomwalters@0: 6. Modulating a tone with a damped exponential, and half-wave rectifying to tomwalters@0: generate damped pulses. tomwalters@0: tomwalters@0: tone period=.5ms amp=500 type=float > foo1 tomwalters@0: ramp pol=damp dec=1ms amp=1 type=float > foo2 tomwalters@0: merge op=mult type=float foo1 foo2 | ftos | gate range=min-0 op=0 | x11plot -n512 tomwalters@0: tomwalters@0: 7. Modulating white noise with a ramped exponential. tomwalters@0: tomwalters@0: noise type=float > foo1 tomwalters@0: ramp pol=ramp dec=1ms amp=1 type=float > foo2 tomwalters@0: merge op=mult type=float foo1 foo2 | ftos | x11plot -n512 tomwalters@0: tomwalters@0: tomwalters@0: */ tomwalters@0: tomwalters@0: #include tomwalters@0: #include tomwalters@0: #include "options.h" tomwalters@0: #include "units.h" tomwalters@0: #include "strmatch.h" tomwalters@0: tomwalters@0: char applic[] = "generate an exponential sawtooth waveform. " ; tomwalters@0: char usage[] = "ramp [options]" ; tomwalters@0: tomwalters@0: static char *helpstr, *debugstr, *sampstr, *perstr, *astr, *decstr, *polstr, *dstr, *datastr ; tomwalters@0: tomwalters@0: static Options option[] = { tomwalters@0: { "help" , "off" , &helpstr , "help" , DEBUG }, tomwalters@0: { "debug" , "off" , &debugstr , "debugging switch" , DEBUG }, tomwalters@0: { "samplerate", "20kHz" , &sampstr , "samplerate " , VAL }, tomwalters@0: { "period" , "8ms" , &perstr , "period [s,ms,p] of ramp" , VAL }, tomwalters@0: { "amplitude" , "1024" , &astr , "amplitude of waveform" , VAL }, tomwalters@0: { "decay" , "2ms" , &decstr , "half-life of ramp" , VAL }, tomwalters@0: { "polarity" , "ramp" , &polstr , "ramp (growing) / damp (decaying)", VAL }, tomwalters@0: { "duration" , "500ms" , &dstr , "duration of waveform" , VAL }, tomwalters@0: { "type" , "short" , &datastr , "o/p datatype (short/float)", VAL }, tomwalters@0: ( char * ) 0 } ; tomwalters@0: tomwalters@0: tomwalters@0: #define DECAYFACTOR ( 0.693147 ) tomwalters@0: tomwalters@0: int samplerate ; tomwalters@0: float amplitude ; tomwalters@0: int duration ; tomwalters@0: int period ; tomwalters@0: int decay ; tomwalters@0: double decayrate ; tomwalters@0: tomwalters@0: main(argc, argv) tomwalters@0: int argc ; tomwalters@0: char *argv[] ; tomwalters@0: { tomwalters@0: int i, n, t ; tomwalters@0: short s ; tomwalters@0: float f ; tomwalters@0: tomwalters@0: getopts( option,argc,argv ) ; tomwalters@0: if ( !isoff( helpstr ) ) tomwalters@0: helpopts3( helpstr, argv[0], applic, usage, option ) ; tomwalters@0: tomwalters@0: samplerate = to_Hz( sampstr, 0 ) ; tomwalters@0: amplitude = atof( astr ) ; tomwalters@0: period = (int)to_p( perstr, samplerate ) ; tomwalters@0: decay = (int)to_p( decstr, samplerate ) ; tomwalters@0: duration = to_p( dstr, samplerate ) ; tomwalters@0: tomwalters@0: /* tomwalters@0: if ( decay >= period ) { tomwalters@0: fprintf(stderr,"ramp: half-life period [%dp] must be less than waveform period [%dp]\n", decay, period); tomwalters@0: exit( 1 ) ; tomwalters@0: } tomwalters@0: */ tomwalters@0: decayrate = DECAYFACTOR / (double)decay ; tomwalters@0: tomwalters@0: if ( iststr( polstr, "damped" ) ) { tomwalters@0: tomwalters@0: /* Decaying exponential */ tomwalters@0: tomwalters@0: if ( iststr( datastr, "short" ) ) tomwalters@0: for ( i=0 ; i