tomwalters@0
|
1 /*
|
tomwalters@0
|
2 SCCS VERSION 1.29 WITH 1.28 STRIPPED OUT.
|
tomwalters@0
|
3
|
tomwalters@0
|
4
|
tomwalters@0
|
5
|
tomwalters@0
|
6 Copyright (c) Applied Psychology Unit, Medical Research Council. 1988, 1989
|
tomwalters@0
|
7 ===========================================================================
|
tomwalters@0
|
8
|
tomwalters@0
|
9 Permission to use, copy, modify, and distribute this software without fee
|
tomwalters@0
|
10 is hereby granted for research purposes, provided that this copyright
|
tomwalters@0
|
11 notice appears in all copies and in all supporting documentation, and that
|
tomwalters@0
|
12 the software is not redistributed for any fee (except for a nominal shipping
|
tomwalters@0
|
13 charge). Anyone wanting to incorporate all or part of this software in a
|
tomwalters@0
|
14 commercial product must obtain a license from the Medical Research Council.
|
tomwalters@0
|
15
|
tomwalters@0
|
16 The MRC makes no representations about the suitability of this
|
tomwalters@0
|
17 software for any purpose. It is provided "as is" without express or implied
|
tomwalters@0
|
18 warranty.
|
tomwalters@0
|
19 */
|
tomwalters@0
|
20
|
tomwalters@0
|
21 /***************************************************************************
|
tomwalters@0
|
22 * image.c Version with trigger at right end of sai.
|
tomwalters@0
|
23 * =======
|
tomwalters@0
|
24 * Input data derived from a cochleagram is used to construct a stabilised
|
tomwalters@0
|
25 * auditory image (sai) of size `chans' * `framewidth' points.
|
tomwalters@0
|
26 *
|
tomwalters@0
|
27 * Organisation of data.
|
tomwalters@0
|
28 * Data is 2-dimensional: in time (rows) and frequency (columns).
|
tomwalters@0
|
29 *
|
tomwalters@0
|
30 * Input data is ordered by columns. The input array consists of blocks (columns)
|
tomwalters@0
|
31 * of `chans' points, each column being one time sample of `chans' channels.
|
tomwalters@0
|
32 * The zero'th point in each column is the lowest frequency channel.
|
tomwalters@0
|
33 *
|
tomwalters@0
|
34 * Output (sai) data is ordered by rows. The output array consists of blocks
|
tomwalters@0
|
35 * (rows) of `framewidth' points.
|
tomwalters@0
|
36 * The zero'th point in each row is the "oldest" time, as the time origin is
|
tomwalters@0
|
37 * on the right edge of the sai.
|
tomwalters@0
|
38 *
|
tomwalters@0
|
39 * Each sai is called a `frame', and its dimensions are `chans' rows by
|
tomwalters@0
|
40 * `framewidth' columns. In the code, the `framewidth' is often represented
|
tomwalters@0
|
41 * as imagewidth/chans, where imagewidth is the total amount of data in an
|
tomwalters@0
|
42 * sai frame, (ie. imagewidth=chans*framewidth).
|
tomwalters@0
|
43
|
tomwalters@0
|
44 * This module has been modified to have 5 levels of strobing.
|
tomwalters@0
|
45 A Jay Datta 6/03/95
|
tomwalters@0
|
46 ***************************************************************************/
|
tomwalters@0
|
47
|
tomwalters@0
|
48 #include <math.h>
|
tomwalters@0
|
49 #include <string.h>
|
tomwalters@0
|
50
|
tomwalters@0
|
51 #include "options.h"
|
tomwalters@0
|
52 #include "stitch.h"
|
tomwalters@0
|
53 #include "source.h"
|
tomwalters@0
|
54 #include "model.h"
|
tomwalters@0
|
55 #include "units.h"
|
tomwalters@0
|
56 #include "image.h"
|
tomwalters@0
|
57 #include "calc.h"
|
tomwalters@0
|
58
|
tomwalters@0
|
59 #define MAX_BUFFER (1l<<15)
|
tomwalters@0
|
60
|
tomwalters@0
|
61 #ifdef FLOAT
|
tomwalters@0
|
62 #define INPUT_SCALE 0.25
|
tomwalters@0
|
63 #define DECAY_SCALE 0.875
|
tomwalters@0
|
64 #else
|
tomwalters@0
|
65 #define INPUT_SHIFT 2
|
tomwalters@0
|
66 #define DECAY_ROUND 7
|
tomwalters@0
|
67 #endif
|
tomwalters@0
|
68 #define DECAY_SHIFT 3
|
tomwalters@0
|
69
|
tomwalters@0
|
70 #define MAXCHAN 1000
|
tomwalters@0
|
71
|
tomwalters@0
|
72 #ifndef lint
|
tomwalters@0
|
73 static char *sccs_id = "@(#)image.c 1.27 J. Holdsworth, M. Allerhand (MRC-APU) 6/6/91" ;
|
tomwalters@0
|
74 #endif
|
tomwalters@0
|
75
|
tomwalters@0
|
76 #ifdef DSP32
|
tomwalters@0
|
77 static int segsize = 16 ;
|
tomwalters@0
|
78 #else
|
tomwalters@0
|
79 static int segsize = 50 ;
|
tomwalters@0
|
80 #endif
|
tomwalters@0
|
81
|
tomwalters@0
|
82 typedef enum { False, True } Bool ;
|
tomwalters@0
|
83 typedef struct Node{int index; short val; struct Node *next;} node;
|
tomwalters@0
|
84
|
tomwalters@0
|
85 static void doColumn();
|
tomwalters@0
|
86 static Pointer sai_callback();
|
tomwalters@0
|
87 static Pointer summary_callback();
|
tomwalters@0
|
88 static void save_callback();
|
tomwalters@0
|
89 static void addIn();
|
tomwalters@0
|
90 static void decayImage();
|
tomwalters@0
|
91
|
tomwalters@0
|
92 void output_simple_strobe_info();
|
tomwalters@0
|
93 void doList_strobe_info();
|
tomwalters@0
|
94 void output_thresh_info();
|
tomwalters@0
|
95 void decay_strobe_threshold();
|
tomwalters@0
|
96 void print_trigger_debugging_info();
|
tomwalters@0
|
97
|
tomwalters@0
|
98 void initlist();
|
tomwalters@0
|
99 node *getnode();
|
tomwalters@0
|
100 node *insertl();
|
tomwalters@0
|
101 void inss();
|
tomwalters@0
|
102
|
tomwalters@0
|
103 FILE *trigger_file;
|
tomwalters@0
|
104 FILE *infotxt_file;
|
tomwalters@0
|
105 FILE *thresho_file;
|
tomwalters@0
|
106
|
tomwalters@0
|
107 int locmax_searchtime[MAXCHAN];
|
tomwalters@0
|
108 int locmax_searchstart[MAXCHAN];
|
tomwalters@0
|
109 int val[MAXCHAN];
|
tomwalters@0
|
110 int ltime[MAXCHAN];
|
tomwalters@0
|
111 int initial_strobe_candidate_time[MAXCHAN];
|
tomwalters@0
|
112 int ttime[MAXCHAN];
|
tomwalters@0
|
113
|
tomwalters@0
|
114 static node *start, *endl, *pp, *qq;
|
tomwalters@0
|
115 static char *exposwitch;
|
tomwalters@0
|
116
|
tomwalters@0
|
117 #ifdef FLOAT
|
tomwalters@0
|
118 float *S;
|
tomwalters@0
|
119 #else
|
tomwalters@0
|
120 short *S;
|
tomwalters@0
|
121 #endif
|
tomwalters@0
|
122
|
tomwalters@0
|
123
|
tomwalters@0
|
124 /***************************************************************************
|
tomwalters@0
|
125 * struct _sai_state:
|
tomwalters@0
|
126 * The source->info->state structure which is initialised by the
|
tomwalters@0
|
127 * routine Sai, and is then the state argument for the callback
|
tomwalters@0
|
128 * function: sai_callback.
|
tomwalters@0
|
129 ***************************************************************************/
|
tomwalters@0
|
130 struct _sai_state {
|
tomwalters@0
|
131 struct _pullable_source parent ;
|
tomwalters@0
|
132 Source source;
|
tomwalters@0
|
133 void (*trigger)(); /* trigger algorithm (originally doColumn) */
|
tomwalters@0
|
134 unsigned chans; /* number of filter channels */
|
tomwalters@0
|
135 unsigned framestep; /* sai display update period */
|
tomwalters@0
|
136 DataType *image; /* sai array (DataType = short) */
|
tomwalters@0
|
137 unsigned imagewidth; /* length of sai array (framewidth*chans) */
|
tomwalters@0
|
138 unsigned imagenwidth; /* portion of sai array for transient info */
|
tomwalters@0
|
139 unsigned decay_time; /* a factor of sai decay time constant */
|
tomwalters@0
|
140 unsigned decay_count;
|
tomwalters@0
|
141 ScalarType *framedecay; /* array of factors for cochleagram frame */
|
tomwalters@0
|
142 int *cps; /* array of 1/centre-freq (in samples) */
|
tomwalters@0
|
143 int *isPulse; /* array of bools, to see if data > thres */
|
tomwalters@0
|
144
|
tomwalters@0
|
145 int Stcrit; /* int restriction */
|
tomwalters@0
|
146 int SusThresh; /* Level 2 user settable thresh */
|
tomwalters@0
|
147 ScalarType triggerdecay; /* prop/point decay for strobe threshold */
|
tomwalters@0
|
148 int *trigtime; /* time of last trigger pulse */
|
tomwalters@0
|
149 int *trigheight; /* height of last trigger pulse */
|
tomwalters@0
|
150 int *isStrobe; /* array of booleans, set when pulse peak found */
|
tomwalters@0
|
151 float *thresh; /* array of thresholds, one per channel */
|
tomwalters@0
|
152 float *tlim; /* linear decay value */
|
tomwalters@0
|
153 int time; /* keep track of sai */
|
tomwalters@0
|
154 int *previnput; /* lock till new pulse found */
|
tomwalters@0
|
155 int *def_strobe_candidate_time;
|
tomwalters@0
|
156 int *def_strobe_height;
|
tomwalters@0
|
157 char *switch_info;
|
tomwalters@0
|
158 int tlim1;
|
tomwalters@0
|
159 int stlag; /* strobe nwid first attempt to decouple nwids */
|
tomwalters@0
|
160 };
|
tomwalters@0
|
161
|
tomwalters@0
|
162 /***************************************************************************
|
tomwalters@0
|
163 * Sai:
|
tomwalters@0
|
164 * Sai is called from SaiEntry (in module model.c).
|
tomwalters@0
|
165 * Routines in this module it uses are:
|
tomwalters@0
|
166 * doColumn, (which uses: addIn)
|
tomwalters@0
|
167 * sai_callback, (which uses: decayImage)
|
tomwalters@0
|
168 *
|
tomwalters@0
|
169 * SaiEntry (in model.c) is the entry-point function to the stabilised image
|
tomwalters@0
|
170 * processing module. Its purpose is to prepare the arguments for Sai by
|
tomwalters@0
|
171 * converting parameter-option strings to integers, and then to call Sai.
|
tomwalters@0
|
172 *
|
tomwalters@0
|
173 * Sai is called with the following arguments (in model.c):
|
tomwalters@0
|
174 * Sai( source, Frameheight(), segment, width,
|
tomwalters@0
|
175 * (int) Samples( decaystr )/Framestep(), (int) Freq( samplestr ),
|
tomwalters@0
|
176 * frequencies, Samples(ttstr)/Framestep(), Samples(cgmstr)/Framestep(),
|
tomwalters@0
|
177 * (int) Freq("250Hz"), (int) Freq("20Hz") ) ;
|
tomwalters@0
|
178 *
|
tomwalters@0
|
179 * The arguments are as follows:
|
tomwalters@0
|
180 * (The option name refers to the description given by "help". The values etc
|
tomwalters@0
|
181 * can be found in table.c as described in model.docs).
|
tomwalters@0
|
182 *
|
tomwalters@0
|
183 * Argument Option name Default Comment
|
tomwalters@0
|
184 * -------- ----------- ------- -------
|
tomwalters@0
|
185 * chans (see below) Number of filter channels
|
tomwalters@0
|
186 * framestep segment_sai 16ms SAI display update period
|
tomwalters@0
|
187 * framewidth duration_sai 32ms SAI duration (ms)
|
tomwalters@0
|
188 * decay decayrate_sai 32ms SAI decay time constant (SU/ms) 15ms NOW Default
|
tomwalters@0
|
189 * samplerate samplerate 20000. Input wave sample rate (Hz)
|
tomwalters@0
|
190 * cfs (see below) An array of filter centre frequencies
|
tomwalters@0
|
191 * cgmdecay napdecay_sai 16ms NAP (ie cochleagram) decay time constant
|
tomwalters@0
|
192 *
|
tomwalters@0
|
193 * Both "chans" and "cfs" are setup from the routine "updateFrequencies" in
|
tomwalters@0
|
194 * model.c, because both arguments are derived from three basic parameters:
|
tomwalters@0
|
195 *
|
tomwalters@0
|
196 * minstr mincf_afb 220Hz Minimum center frequency (Hz)
|
tomwalters@0
|
197 * maxstr maxcf_afb 4400Hz Maximum center frequency (Hz)
|
tomwalters@0
|
198 * denstr dencf_afb 4. Filter density (filters/critical band)
|
tomwalters@0
|
199 *
|
tomwalters@0
|
200 * The "chans" argument is calculated in the routine "NumberCenterFrequencies",
|
tomwalters@0
|
201 * and the result is copied into the "frameheightstr" by a call to the routine
|
tomwalters@0
|
202 * "setFrameheight".
|
tomwalters@0
|
203 * The "cfs" argument is calculated in the routine "GenerateCenterFrequencies".
|
tomwalters@0
|
204 * (Both CenterFrequency routines are in gamma_tone.c).
|
tomwalters@0
|
205 *
|
tomwalters@0
|
206 ***************************************************************************/
|
tomwalters@0
|
207
|
tomwalters@0
|
208 Source Sai(source, chans, framestep, pwidth, nwidth, decay, samplerate, cfs, ttdecay, cgmdecay, tlim1, tlim2, suslevel, susthresh, switchinfo, expoSwitch,stlag)
|
tomwalters@0
|
209 Source source ;
|
tomwalters@0
|
210 int chans, framestep, pwidth, nwidth, decay ;
|
tomwalters@0
|
211 int samplerate;
|
tomwalters@0
|
212 double *cfs ;
|
tomwalters@0
|
213 double ttdecay, cgmdecay ;
|
tomwalters@0
|
214 int tlim1, tlim2;
|
tomwalters@0
|
215 int suslevel;
|
tomwalters@0
|
216 char *susthresh;
|
tomwalters@0
|
217 char *switchinfo;
|
tomwalters@0
|
218 char *expoSwitch;
|
tomwalters@0
|
219 int stlag;
|
tomwalters@0
|
220 {
|
tomwalters@0
|
221
|
tomwalters@0
|
222 DeclareNew( struct _sai_state *, state ) ;
|
tomwalters@0
|
223 int i, chan, startup, segment, framewidth ;
|
tomwalters@0
|
224 double pts_per_ms, lin_napdec, lin_napfac ; /* roy 11-8-92 roy */
|
tomwalters@0
|
225 char *ThreshoFile, *InfotxtFile, *TriggerFile;
|
tomwalters@0
|
226
|
tomwalters@0
|
227 exposwitch=(char *)calloc(5, sizeof(char));
|
tomwalters@0
|
228 exposwitch=expoSwitch;
|
tomwalters@0
|
229
|
tomwalters@0
|
230 ThreshoFile = (char *)calloc(256, sizeof(char));
|
tomwalters@0
|
231 InfotxtFile = (char *)calloc(256, sizeof(char));
|
tomwalters@0
|
232 TriggerFile = (char *)calloc(256, sizeof(char));
|
tomwalters@0
|
233
|
tomwalters@0
|
234 state->switch_info = (char *)calloc(256,sizeof(char));
|
tomwalters@0
|
235 state->switch_info = switchinfo;
|
tomwalters@0
|
236
|
tomwalters@0
|
237 if (!strcmp(susthresh, "on"))
|
tomwalters@0
|
238 state->SusThresh=0;
|
tomwalters@0
|
239 else if (!strcmp(susthresh, "off"))
|
tomwalters@0
|
240 state->SusThresh=1;
|
tomwalters@0
|
241 else
|
tomwalters@0
|
242 state->SusThresh=atoi(susthresh);
|
tomwalters@0
|
243
|
tomwalters@0
|
244 if (!strcmp(state->switch_info, "off"))
|
tomwalters@0
|
245 ;
|
tomwalters@0
|
246 else if (!strcmp(state->switch_info, "on"))
|
tomwalters@0
|
247 infotxt_file=stdout;
|
tomwalters@0
|
248 else{
|
tomwalters@0
|
249 strcpy(InfotxtFile, switchinfo);
|
tomwalters@0
|
250 strcat(InfotxtFile, ".info");
|
tomwalters@0
|
251 infotxt_file=fopen(InfotxtFile, "w");
|
tomwalters@0
|
252
|
tomwalters@0
|
253 strcpy(TriggerFile, switchinfo);
|
tomwalters@0
|
254 strcat(TriggerFile, ".trigger");
|
tomwalters@0
|
255 trigger_file=fopen(TriggerFile, "w");
|
tomwalters@0
|
256
|
tomwalters@0
|
257 strcpy(ThreshoFile, switchinfo);
|
tomwalters@0
|
258 strcat(ThreshoFile, ".thresh");
|
tomwalters@0
|
259 thresho_file=fopen(ThreshoFile, "w");
|
tomwalters@0
|
260 }
|
tomwalters@0
|
261
|
tomwalters@0
|
262 initlist();
|
tomwalters@0
|
263 state->tlim1=0;
|
tomwalters@0
|
264
|
tomwalters@0
|
265 framewidth = pwidth+nwidth;
|
tomwalters@0
|
266
|
tomwalters@0
|
267 pts_per_ms = (double)samplerate/1000 ;
|
tomwalters@0
|
268
|
tomwalters@0
|
269 state->stlag=stlag; /* NEW line 95April */
|
tomwalters@0
|
270 /* Initialise members of the sai state structure */
|
tomwalters@0
|
271 state->source = NewRetainingSource( source, sizeof ( DataType ) * framewidth * chans ) ;
|
tomwalters@0
|
272 state->chans = chans ;
|
tomwalters@0
|
273 state->trigger = doColumn ;
|
tomwalters@0
|
274 state->framestep = framestep * chans ;
|
tomwalters@0
|
275 state->imagewidth = framewidth * chans ; /* size of sai buffer */
|
tomwalters@0
|
276 state->imagenwidth = nwidth * chans ; /* size of buffer for transient info */
|
tomwalters@0
|
277 state->decay_time = decay * -log( 1. - 1. / ( 1 << DECAY_SHIFT ) ) ;
|
tomwalters@0
|
278 state->decay_count = state->decay_time ;
|
tomwalters@0
|
279
|
tomwalters@0
|
280 state->Stcrit = suslevel;
|
tomwalters@0
|
281 if (stlag==0 && state->Stcrit==5) /* was nwid NEW */
|
tomwalters@0
|
282 state->Stcrit = suslevel-1;
|
tomwalters@0
|
283
|
tomwalters@0
|
284 /* state->SusThresh = susthresh; */
|
tomwalters@0
|
285
|
tomwalters@0
|
286 if (!strcmp(exposwitch, "on")) fprintf(stderr, "Exponential trigger decay SWITCH is ON\n");
|
tomwalters@0
|
287 /* if (!strcmp(exposwitch, "off")) printf("SWITCH is OFF\n"); */
|
tomwalters@0
|
288
|
tomwalters@0
|
289 if (!strcmp(exposwitch, "on"))
|
tomwalters@0
|
290 state->triggerdecay = (double) 1-((ttdecay / pts_per_ms ) /100.0) ;
|
tomwalters@0
|
291 else
|
tomwalters@0
|
292 state->triggerdecay = (double) (ttdecay /pts_per_ms) / 100.0 ;
|
tomwalters@0
|
293
|
tomwalters@0
|
294 if (!strcmp(switchinfo, "off"))
|
tomwalters@0
|
295 ;
|
tomwalters@0
|
296 else
|
tomwalters@0
|
297 fprintf(infotxt_file, "\ntriggerdecay = %15e\n", state->triggerdecay);
|
tomwalters@0
|
298
|
tomwalters@0
|
299 state->isStrobe = NewZeroedArray( int, state->chans, "image.c for Strobe" ) ;
|
tomwalters@0
|
300 state->isPulse = NewZeroedArray( int, state->chans, "image.c for trigger pulse" ) ;
|
tomwalters@0
|
301 state->trigtime = NewZeroedArray( int, state->chans, "image.c for trigger time" ) ;
|
tomwalters@0
|
302 state->trigheight = NewZeroedArray( int, state->chans, "image.c for trigger height" ) ;
|
tomwalters@0
|
303 state->thresh = NewZeroedArray( float, state->chans, "image.c for thresh" ) ;
|
tomwalters@0
|
304 state->tlim = NewZeroedArray( float, state->chans, "image.c for decay" ) ;
|
tomwalters@0
|
305 state->time = 0; /* Time initialized to Zero */
|
tomwalters@0
|
306 state->previnput = NewZeroedArray( int, state->chans, "image.c for pulse lock" ) ;
|
tomwalters@0
|
307
|
tomwalters@0
|
308 state->def_strobe_candidate_time = NewZeroedArray( int, state->chans, "image.c for prevtrig time" );
|
tomwalters@0
|
309 state->def_strobe_height = NewZeroedArray( int, state->chans, "image.c for prev trig" );
|
tomwalters@0
|
310
|
tomwalters@0
|
311 for (chan=0; chan < MAXCHAN; chan++)
|
tomwalters@0
|
312 locmax_searchtime[chan]=0;
|
tomwalters@0
|
313 for (chan=0; chan < MAXCHAN; chan++)
|
tomwalters@0
|
314 locmax_searchstart[chan]=0;
|
tomwalters@0
|
315 for (chan=0; chan < MAXCHAN; chan++)
|
tomwalters@0
|
316 val[chan]=0;
|
tomwalters@0
|
317 for (chan=0; chan < MAXCHAN; chan++)
|
tomwalters@0
|
318 initial_strobe_candidate_time[chan]=0;
|
tomwalters@0
|
319 for (chan=0; chan < MAXCHAN; chan++)
|
tomwalters@0
|
320 ltime[chan]=0;
|
tomwalters@0
|
321 for (chan=0; chan < MAXCHAN; chan++)
|
tomwalters@0
|
322 ttime[chan]=0;
|
tomwalters@0
|
323
|
tomwalters@0
|
324 #ifdef FLOAT
|
tomwalters@0
|
325 S=(float *)calloc(state->chans, sizeof(float));
|
tomwalters@0
|
326 #else
|
tomwalters@0
|
327 S=(short *)calloc(state->chans, sizeof(short));
|
tomwalters@0
|
328 #endif
|
tomwalters@0
|
329
|
tomwalters@0
|
330 /* Declare new arrays for members of state structure */
|
tomwalters@0
|
331
|
tomwalters@0
|
332 state->framedecay = NewArray( ScalarType, framewidth, "image.c for decay" ) ;
|
tomwalters@0
|
333 state->image = NewZeroedArray( DataType, state->imagewidth, "image.c for image" ) ;
|
tomwalters@0
|
334 state->cps = NewZeroedArray( int, state->chans, "image.c for channel centre periods" ) ;
|
tomwalters@0
|
335
|
tomwalters@0
|
336 /* Initialise cochleagram frame decay factors */
|
tomwalters@0
|
337 if (cgmdecay > 0)
|
tomwalters@0
|
338 {
|
tomwalters@0
|
339 /* 11111 roy 11-8-92 These mods change to a linear nap decay. 1111111 roy */
|
tomwalters@0
|
340 /* It requires pts_per_ms, lin_napdec and lin_napfac declared just after DeclareNew above */
|
tomwalters@0
|
341
|
tomwalters@0
|
342 lin_napdec = ((cgmdecay/100)/pts_per_ms)/pts_per_ms ; /* roy 19-8 roy */
|
tomwalters@0
|
343
|
tomwalters@0
|
344 /* cgmdecay is div by pts_per_ms to get back to napdecay in the original units */
|
tomwalters@0
|
345 /* When napdecay is interpreted as the % to decay per ms, and since we are */
|
tomwalters@0
|
346 /* operating in points, we need napdec/pts_per_ms, as the dec for each pt within the ms */
|
tomwalters@0
|
347 /* The decay vector is set to scale the NAP by 1.0 at strobe point. So, in the sai, */
|
tomwalters@0
|
348 /* it falls to the left AND RISES to the right of 0 ms. **** roy **** */
|
tomwalters@0
|
349
|
tomwalters@0
|
350 lin_napfac = 1.0 + nwidth*lin_napdec ;
|
tomwalters@0
|
351
|
tomwalters@0
|
352 for (i=0 ; i < framewidth ; i++)
|
tomwalters@0
|
353 {
|
tomwalters@0
|
354 if ( lin_napfac > 0 )
|
tomwalters@0
|
355 state->framedecay[i] = SCALAR( lin_napfac );
|
tomwalters@0
|
356 else
|
tomwalters@0
|
357 state->framedecay[i] = SCALAR( 0 );
|
tomwalters@0
|
358 lin_napfac -= lin_napdec ;
|
tomwalters@0
|
359 }
|
tomwalters@0
|
360 }
|
tomwalters@0
|
361 else /* disable decay factor on zero argument */
|
tomwalters@0
|
362 for (i=0 ; i < framewidth ; i++)
|
tomwalters@0
|
363 state->framedecay[i] = SCALAR( 1.0 ) ;
|
tomwalters@0
|
364
|
tomwalters@0
|
365 /* Initialise centre-period for each channel */
|
tomwalters@0
|
366 for (i=0 ; i < state->chans ; i++)
|
tomwalters@0
|
367 state->cps[i] = samplerate / cfs[i];
|
tomwalters@0
|
368
|
tomwalters@0
|
369 #if defined( PC ) || defined( THINK_C )
|
tomwalters@0
|
370 if( (long) ( MAX_BUFFER - (long) state->imagewidth * sizeof ( DataType ) ) < (long) ( state->chans * sizeof ( DataType ) ) )
|
tomwalters@0
|
371 stitch_error( "Sorry, image larger than maximum buffer size\n" ) ;
|
tomwalters@0
|
372 #endif
|
tomwalters@0
|
373
|
tomwalters@0
|
374 /* for (i=0; i<state->imagewidth;i++)
|
tomwalters@0
|
375 fprintf(stderr, "Image Buffer is %f, count = %d\n", *(state->image+i), (i+1)); */
|
tomwalters@0
|
376
|
tomwalters@0
|
377
|
tomwalters@0
|
378
|
tomwalters@0
|
379 return ( SetPullableSource( state, sai_callback, "image.c stabilised image" ) ) ;
|
tomwalters@0
|
380 }
|
tomwalters@0
|
381
|
tomwalters@0
|
382 /****************************************************************************
|
tomwalters@0
|
383 * sai_callback
|
tomwalters@0
|
384 * The callback function at source->info->callback in the source
|
tomwalters@0
|
385 * returned by Sai.
|
tomwalters@0
|
386 * A "frame" is a window over the cochleagram, of size chans * points.
|
tomwalters@0
|
387 * A "segment" is a stretch of the cochleagram which is segsize (ie 50) time
|
tomwalters@0
|
388 * samples long, ie segsize columns of the cochleagram.
|
tomwalters@0
|
389 *
|
tomwalters@0
|
390 * This callback routine is executed once for each sai frame which is plotted.
|
tomwalters@0
|
391 * "*bytes" is the number of bytes in the sai, ie:
|
tomwalters@0
|
392 * *bytes = state->imagewidth * sizeof(DataType)
|
tomwalters@0
|
393 ****************************************************************************/
|
tomwalters@0
|
394 static Pointer sai_callback( state, bytes )
|
tomwalters@0
|
395 struct _sai_state *state ;
|
tomwalters@0
|
396 ByteCount *bytes ;
|
tomwalters@0
|
397 {
|
tomwalters@0
|
398 register long col, point ;
|
tomwalters@0
|
399 register long points = state->framestep; /* total num points under frame */
|
tomwalters@0
|
400 #if defined( PC )
|
tomwalters@0
|
401 int segment = ( MAX_BUFFER - state->imagewidth * sizeof ( DataType ) ) / state->chans / sizeof ( DataType ) * state->chans ;
|
tomwalters@0
|
402 #else
|
tomwalters@0
|
403 int segment = segsize * state->chans ;
|
tomwalters@0
|
404 #endif
|
tomwalters@0
|
405 register DataType *input ; /* cochleagram (input) data array */
|
tomwalters@0
|
406 static int first=1;
|
tomwalters@0
|
407 static int test=0;
|
tomwalters@0
|
408 int chan;
|
tomwalters@0
|
409 int i;
|
tomwalters@0
|
410 /* #if defined( PC )
|
tomwalters@0
|
411 test=1;
|
tomwalters@0
|
412 #else
|
tomwalters@0
|
413 if (state->SusThresh == 0)
|
tomwalters@0
|
414 segment= 30 * state->chans ;
|
tomwalters@0
|
415 #endif */
|
tomwalters@0
|
416
|
tomwalters@0
|
417 /* test++; */
|
tomwalters@0
|
418
|
tomwalters@0
|
419
|
tomwalters@0
|
420 /* If size argument is zero, then by convention free space and return null */
|
tomwalters@0
|
421 if( *bytes == 0 ) {
|
tomwalters@0
|
422 Pull( state->source, 0 ) ;
|
tomwalters@0
|
423 Delete( state->image ) ;
|
tomwalters@0
|
424 return ( DeletePullableSource( state ) ) ;
|
tomwalters@0
|
425 }
|
tomwalters@0
|
426
|
tomwalters@0
|
427 /* Initially pull enough data to buffer transient info ahead of the trigger */
|
tomwalters@0
|
428 /* Note, the pull operation is not valid when the size arg is zero. */
|
tomwalters@0
|
429 /* The result would be a segmentation fault on the next pull, below. */
|
tomwalters@0
|
430
|
tomwalters@0
|
431 if (state->Stcrit==0 || state->Stcrit==1 || state->Stcrit==2 || state->Stcrit==3)
|
tomwalters@0
|
432 if (first) {
|
tomwalters@0
|
433 if (state->imagenwidth > 0)
|
tomwalters@0
|
434 input = PullItems(state->source, state->imagenwidth, DataType);
|
tomwalters@0
|
435 first = 0;
|
tomwalters@0
|
436 }
|
tomwalters@0
|
437
|
tomwalters@0
|
438
|
tomwalters@0
|
439 /* Search frame in segment blocks for trigger-points */
|
tomwalters@0
|
440 for( point=0 ; point < points ; point += segment ) {
|
tomwalters@0
|
441 if( segment > points - point ) /* Finish at end of frame */
|
tomwalters@0
|
442 segment = points - point ;
|
tomwalters@0
|
443 /* Get one segment of the input data */
|
tomwalters@0
|
444 /* Pull 50 columns of data from the source, in buffer *input. */
|
tomwalters@0
|
445 /* Keep one sai of data, from last pull, in buffer behind *input */
|
tomwalters@0
|
446 input = PullItems(state->source, segment, DataType);
|
tomwalters@0
|
447
|
tomwalters@0
|
448 for( col=0 ; col < segment ; col += state->chans ) {
|
tomwalters@0
|
449 /* Retard the "current" data point by transient buffer width */
|
tomwalters@0
|
450 /* (This retards the trigger by the transient time, about 5ms) */
|
tomwalters@0
|
451 if (state->Stcrit==0 || state->Stcrit==1 || state->Stcrit==2 || state->Stcrit==3)
|
tomwalters@0
|
452 state->trigger(input-state->imagenwidth, state) ;
|
tomwalters@0
|
453 else{
|
tomwalters@0
|
454 state->trigger( input, state) ; /* -state->imagenwidth, state ) ; */
|
tomwalters@0
|
455 /*fprintf(stderr, " %d ", points) ; */ }
|
tomwalters@0
|
456 input += state->chans ; /* next column */
|
tomwalters@0
|
457 /* decay image periodically, once every `decay_time' columns */
|
tomwalters@0
|
458 /* Lines moved down */
|
tomwalters@0
|
459 if( --state->decay_count <= 0 ) {
|
tomwalters@0
|
460 decayImage( state ) ;
|
tomwalters@0
|
461 state->decay_count = state->decay_time ;
|
tomwalters@0
|
462 }
|
tomwalters@0
|
463 } /* for each col */
|
tomwalters@0
|
464 } /* for each seg */
|
tomwalters@0
|
465
|
tomwalters@0
|
466 /* whatever the number of bytes requested, the image is always this size */
|
tomwalters@0
|
467 *bytes = state->imagewidth * sizeof ( *state->image ) ;
|
tomwalters@0
|
468
|
tomwalters@0
|
469 /* if (state->Stcrit==1 && state->SusThresh==0){
|
tomwalters@0
|
470 if (test%5==0)
|
tomwalters@0
|
471 decayImage( state );
|
tomwalters@0
|
472 test++;}
|
tomwalters@0
|
473 else if (state->Stcrit==1 && state->SusThresh>0){ changed 2 to 3
|
tomwalters@0
|
474 if (test%10==0)
|
tomwalters@0
|
475 decayImage( state );
|
tomwalters@0
|
476 test++;}
|
tomwalters@0
|
477 else{ */
|
tomwalters@0
|
478
|
tomwalters@0
|
479 return ( (Pointer) state->image ) ;
|
tomwalters@0
|
480 }
|
tomwalters@0
|
481
|
tomwalters@0
|
482 /****************************************************************************
|
tomwalters@0
|
483 * decayImage
|
tomwalters@0
|
484 * Periodically attenuate image to give computationally efficient image decay.
|
tomwalters@0
|
485 * Attenuate all points in the sai by a constant factor.
|
tomwalters@0
|
486 ****************************************************************************/
|
tomwalters@0
|
487 static void decayImage( state )
|
tomwalters@0
|
488 struct _sai_state *state ;
|
tomwalters@0
|
489 {
|
tomwalters@0
|
490 register DataType *image_ptr, *image_end ;
|
tomwalters@0
|
491 #ifdef FLOAT
|
tomwalters@0
|
492 register FLOAT image_decay = DECAY_SCALE ;
|
tomwalters@0
|
493 #endif
|
tomwalters@0
|
494
|
tomwalters@0
|
495 image_end = state->image + state->imagewidth ; /* end of sai array */
|
tomwalters@0
|
496 #ifdef FLOAT
|
tomwalters@0
|
497 for( image_ptr=state->image ; image_ptr < image_end ; )
|
tomwalters@0
|
498 *image_ptr++ *= image_decay ;
|
tomwalters@0
|
499 #else
|
tomwalters@0
|
500 for( image_ptr=state->image ; image_ptr < image_end ; image_ptr++ )
|
tomwalters@0
|
501 *image_ptr -= *image_ptr + DECAY_ROUND >> DECAY_SHIFT ;
|
tomwalters@0
|
502 #endif
|
tomwalters@0
|
503 return ;
|
tomwalters@0
|
504 }
|
tomwalters@0
|
505
|
tomwalters@0
|
506 /****************************************************************************
|
tomwalters@0
|
507 * doColumn
|
tomwalters@0
|
508 * Trigger algorithm for Sai.
|
tomwalters@0
|
509 * Installed as source->info->state->trigger.
|
tomwalters@0
|
510 *
|
tomwalters@0
|
511 ****************************************************************************/
|
tomwalters@0
|
512 static void doColumn( input, state )
|
tomwalters@0
|
513 DataType *input ;
|
tomwalters@0
|
514 struct _sai_state *state ;
|
tomwalters@0
|
515 {
|
tomwalters@0
|
516
|
tomwalters@0
|
517 register int chan ;
|
tomwalters@0
|
518 float strobelag;
|
tomwalters@0
|
519 int s_lag;
|
tomwalters@0
|
520
|
tomwalters@0
|
521
|
tomwalters@0
|
522 short *STI;
|
tomwalters@0
|
523 static int check=0;
|
tomwalters@0
|
524 int storev;
|
tomwalters@0
|
525 char buf[2];
|
tomwalters@0
|
526 short stipts=-2000;
|
tomwalters@0
|
527 short zeroval=0;
|
tomwalters@0
|
528
|
tomwalters@0
|
529 STI=(short *)calloc(state->chans, sizeof(short));
|
tomwalters@0
|
530
|
tomwalters@0
|
531 strobelag = (double) (state->time)-(state->stlag);
|
tomwalters@0
|
532
|
tomwalters@0
|
533 s_lag=(state->time)-(state->stlag);
|
tomwalters@0
|
534
|
tomwalters@0
|
535 /* For each channel up column, add a row of data to sai if the */
|
tomwalters@0
|
536 /* current point is non-zero. Add the row from the current point */
|
tomwalters@0
|
537 /* plus state->imagenwidth, to display the transient (nwidth) info. */
|
tomwalters@0
|
538
|
tomwalters@0
|
539
|
tomwalters@0
|
540 /* 000000000000000000000000 stcrit 0000000000000000000000000000000000 */
|
tomwalters@0
|
541 /* Add on every point : Low Pass Filter */
|
tomwalters@0
|
542
|
tomwalters@0
|
543 if (state->Stcrit==0)
|
tomwalters@0
|
544 {
|
tomwalters@0
|
545 for( chan=0 ; chan < state->chans ; chan++ )
|
tomwalters@0
|
546 {
|
tomwalters@0
|
547 addIn(input+(state->imagenwidth), chan, state);
|
tomwalters@0
|
548 output_simple_strobe_info(state, stipts);
|
tomwalters@0
|
549 }
|
tomwalters@0
|
550 } /* if (state->Stcrit==0) */
|
tomwalters@0
|
551
|
tomwalters@0
|
552
|
tomwalters@0
|
553 /* 111111111111111111111111 stcrit 1111111111111111111111111111111111 */
|
tomwalters@0
|
554 /* Add on every point greater than "stthresh_ai" (default 0) */
|
tomwalters@0
|
555
|
tomwalters@0
|
556 if (state->Stcrit==1)
|
tomwalters@0
|
557 {
|
tomwalters@0
|
558 for( chan=0 ; chan < state->chans ; chan++ )
|
tomwalters@0
|
559 {
|
tomwalters@0
|
560 if (input[chan] > state->SusThresh )
|
tomwalters@0
|
561 {
|
tomwalters@0
|
562 addIn(input+(state->imagenwidth), chan, state);
|
tomwalters@0
|
563 output_simple_strobe_info(state, stipts);
|
tomwalters@0
|
564 }
|
tomwalters@0
|
565 else if (input[chan] <=state->SusThresh)
|
tomwalters@0
|
566 output_simple_strobe_info(state, zeroval);
|
tomwalters@0
|
567 }
|
tomwalters@0
|
568 } /* if (state->Stcrit==1) */
|
tomwalters@0
|
569
|
tomwalters@0
|
570
|
tomwalters@0
|
571 /* 222222222222222222222222 stcrit 2222222222222222222222222222222222 */
|
tomwalters@0
|
572 /* Add on every Nap pulse peak */
|
tomwalters@0
|
573
|
tomwalters@0
|
574 if (state->Stcrit==2)
|
tomwalters@0
|
575 {
|
tomwalters@0
|
576 for( chan=0 ; chan < state->chans ; chan++ )
|
tomwalters@0
|
577 {
|
tomwalters@0
|
578 if (state->isStrobe[chan]) /* Check to see if it is time to addIn */
|
tomwalters@0
|
579 {
|
tomwalters@0
|
580 addIn(input+((state->imagenwidth)-2*(state->chans)), chan, state);
|
tomwalters@0
|
581 state->isStrobe[chan]=0; /* Reset strobe flag */
|
tomwalters@0
|
582 doList_strobe_info(state, chan);
|
tomwalters@0
|
583 }
|
tomwalters@0
|
584
|
tomwalters@0
|
585 /* Find a pulse peak routine */
|
tomwalters@0
|
586
|
tomwalters@0
|
587 if (!state->isPulse[chan]) /* Not in pulse, looking for pulse */
|
tomwalters@0
|
588 {
|
tomwalters@0
|
589 state->thresh[chan]=input[chan];
|
tomwalters@0
|
590 if (input[chan] > 0 /*state->thresh[chan] */ ) /* Start of a Nap pulse */
|
tomwalters@0
|
591 state->isPulse[chan] =1; /* set in pulse flag */
|
tomwalters@0
|
592 }
|
tomwalters@0
|
593 else /* In pulse, looking for peak */
|
tomwalters@0
|
594 {
|
tomwalters@0
|
595 if (input[chan] < state->thresh[chan]) /* peak found */
|
tomwalters@0
|
596 {
|
tomwalters@0
|
597 state->isPulse[chan]=0;
|
tomwalters@0
|
598 state->isStrobe[chan]=1; /* set strobe pending flag */
|
tomwalters@0
|
599 }
|
tomwalters@0
|
600 else
|
tomwalters@0
|
601 state->thresh[chan]=input[chan];
|
tomwalters@0
|
602 }
|
tomwalters@0
|
603 output_thresh_info(state, chan);
|
tomwalters@0
|
604 }
|
tomwalters@0
|
605 } /* if (state->stcrit==2) */
|
tomwalters@0
|
606
|
tomwalters@0
|
607
|
tomwalters@0
|
608
|
tomwalters@0
|
609 /* 333333333333333333333333 stcrit 3333333333333333333333333333333333 */
|
tomwalters@0
|
610 /* Add on pulse peaks that exceed strobe threshold (temporal shadow ) */
|
tomwalters@0
|
611 /* Primitive Local Max algorithm */
|
tomwalters@0
|
612
|
tomwalters@0
|
613 if (state->Stcrit==3)
|
tomwalters@0
|
614 {
|
tomwalters@0
|
615 for( chan=0 ; chan < state->chans ; chan++ )
|
tomwalters@0
|
616 {
|
tomwalters@0
|
617 if (state->isStrobe[chan]) /* Check to see if it is time to addIn */
|
tomwalters@0
|
618 {
|
tomwalters@0
|
619 addIn(input+((state->imagenwidth)-2*(state->chans)), chan, state);
|
tomwalters@0
|
620 state->isStrobe[chan] = 0; /* Reset strobe flag */
|
tomwalters@0
|
621 doList_strobe_info(state, chan);
|
tomwalters@0
|
622 }
|
tomwalters@0
|
623
|
tomwalters@0
|
624 /* Find a pulse peak routine */
|
tomwalters@0
|
625
|
tomwalters@0
|
626 if (!state->isPulse[chan]) /* Not in Pulse, looking for Pulse */
|
tomwalters@0
|
627 {
|
tomwalters@0
|
628 if (input[chan] > state->thresh[chan] && input[chan] > state->previnput[chan])
|
tomwalters@0
|
629 { /* Previnput check ensures threshold decay
|
tomwalters@0
|
630 does not cut into pulse */
|
tomwalters@0
|
631
|
tomwalters@0
|
632 state->isPulse[chan] = 1; /* set flag: in pulse */
|
tomwalters@0
|
633 state->thresh[chan] = input[chan]; /* start search for peak */
|
tomwalters@0
|
634 }
|
tomwalters@0
|
635 else {
|
tomwalters@0
|
636 decay_strobe_threshold(state, chan);
|
tomwalters@0
|
637 if (input[chan]==0) /* in the zeroes between nap pulses */
|
tomwalters@0
|
638 state->previnput[chan] = 0; /* Set it to Zero previnput */
|
tomwalters@0
|
639 }
|
tomwalters@0
|
640 }
|
tomwalters@0
|
641
|
tomwalters@0
|
642 if (state->isPulse[chan]) /* Else in ongoing pulse looking for peak */
|
tomwalters@0
|
643 {
|
tomwalters@0
|
644 if (input[chan] <= state->thresh[chan] && input[chan] <= state->previnput[chan])
|
tomwalters@0
|
645 /* pulse peak found */
|
tomwalters@0
|
646 {
|
tomwalters@0
|
647 state->isPulse[chan] = 0; /* clear flag: not in pulse */
|
tomwalters@0
|
648 state->isStrobe[chan] = 1; /* set Strobe pending flag */
|
tomwalters@0
|
649 if (!strcmp(exposwitch, "off"))
|
tomwalters@0
|
650 state->tlim[chan]=state->triggerdecay * state->thresh[chan];
|
tomwalters@0
|
651 state->trigtime[chan]=(state->time)-1;
|
tomwalters@0
|
652 /* state->previnput[chan]=input[cha */
|
tomwalters@0
|
653 }
|
tomwalters@0
|
654 else /* still in pulse, so continue search for peak */
|
tomwalters@0
|
655 state->thresh[chan] = input[chan];
|
tomwalters@0
|
656
|
tomwalters@0
|
657 } /* if in Pulse */
|
tomwalters@0
|
658 state->previnput[chan]=input[chan];
|
tomwalters@0
|
659 output_thresh_info(state, chan);
|
tomwalters@0
|
660 } /* for all chans... */
|
tomwalters@0
|
661 } /* if (state->Stcrit==3) */
|
tomwalters@0
|
662
|
tomwalters@0
|
663
|
tomwalters@0
|
664
|
tomwalters@0
|
665 /* 444444444444444444444444 stcrit 4444444444444444444444444444444444 */
|
tomwalters@0
|
666 /* Add on pulse peaks that exceed strobe threshold and which are not succeeded by
|
tomwalters@0
|
667 a larger pulse in nwid ms. (Better Local Max mechanism) */
|
tomwalters@0
|
668
|
tomwalters@0
|
669 if (state->Stcrit==4)
|
tomwalters@0
|
670 {
|
tomwalters@0
|
671 for( chan=0 ; chan < state->chans ; chan++ )
|
tomwalters@0
|
672 {
|
tomwalters@0
|
673 if (state->isStrobe[chan]) /* Check to see if it is time to addIn */
|
tomwalters@0
|
674 {
|
tomwalters@0
|
675 if ( strobelag-1 >= state->trigtime[chan])
|
tomwalters@0
|
676 /* initiates strobe after nwid ms */
|
tomwalters@0
|
677 {
|
tomwalters@0
|
678 addIn(input-(state->chans), chan, state);
|
tomwalters@0
|
679 doList_strobe_info(state, chan);
|
tomwalters@0
|
680 state->isStrobe[chan] = 0; /* Reset strobe flag */
|
tomwalters@0
|
681 state->trigheight[chan] = 0; /* Reset local max value */
|
tomwalters@0
|
682
|
tomwalters@0
|
683 }
|
tomwalters@0
|
684 }
|
tomwalters@0
|
685
|
tomwalters@0
|
686 /* Find a pulse peak routine */
|
tomwalters@0
|
687
|
tomwalters@0
|
688 if (!state->isPulse[chan]) /* Not in Pulse, looking for pulse */
|
tomwalters@0
|
689 {
|
tomwalters@0
|
690 if (input[chan] > state->thresh[chan] && input[chan] > state->previnput[chan])
|
tomwalters@0
|
691 { /* Previnput check ensures threshold
|
tomwalters@0
|
692 decay does not cut into pulse */
|
tomwalters@0
|
693
|
tomwalters@0
|
694 state->isPulse[chan] = 1; /* set flag: in pulse */
|
tomwalters@0
|
695 state->thresh[chan] = input[chan]; /* start search for peak */
|
tomwalters@0
|
696 /* state->previnput[chan]= 1; in pulse till the next zero value */
|
tomwalters@0
|
697 }
|
tomwalters@0
|
698 else
|
tomwalters@0
|
699 {
|
tomwalters@0
|
700 decay_strobe_threshold(state, chan);
|
tomwalters@0
|
701 if (input[chan]==0) /* in the zeroes between nap pulses */
|
tomwalters@0
|
702 state->previnput[chan] = 0; /* Free previnput */
|
tomwalters@0
|
703 }
|
tomwalters@0
|
704 }
|
tomwalters@0
|
705
|
tomwalters@0
|
706 if (state->isPulse[chan]) /* Else in ongoing pulse, looking for peak */
|
tomwalters@0
|
707 {
|
tomwalters@0
|
708 if (input[chan] <= state->thresh[chan] && input[chan] <= state->previnput[chan])
|
tomwalters@0
|
709 /* pulse peak found */
|
tomwalters@0
|
710 {
|
tomwalters@0
|
711 state->isPulse[chan] = 0; /* clear flag: not in pulse */
|
tomwalters@0
|
712 state->isStrobe[chan] = 1; /* set Strobe pending flag */
|
tomwalters@0
|
713
|
tomwalters@0
|
714 if ( state->thresh[chan] > state->trigheight[chan] )
|
tomwalters@0
|
715 /* Check for LOCAL MAX */
|
tomwalters@0
|
716 {
|
tomwalters@0
|
717 state->trigheight[chan] = state->thresh[chan];
|
tomwalters@0
|
718 state->trigtime[chan] = (state->time)-1; /* Set strobe time */
|
tomwalters@0
|
719 if (!strcmp(exposwitch, "off"))
|
tomwalters@0
|
720 state->tlim[chan]=state->triggerdecay * state->trigheight[chan];
|
tomwalters@0
|
721 }
|
tomwalters@0
|
722 }
|
tomwalters@0
|
723 else /* still in pulse, so continue search for peak */
|
tomwalters@0
|
724 state->thresh[chan] = input[chan];
|
tomwalters@0
|
725 } /* if in Pulse */
|
tomwalters@0
|
726 state->previnput[chan]=input[chan];
|
tomwalters@0
|
727 output_thresh_info(state, chan);
|
tomwalters@0
|
728 } /* for all chans... */
|
tomwalters@0
|
729 } /* if (state->Stcrit==4) */
|
tomwalters@0
|
730
|
tomwalters@0
|
731
|
tomwalters@0
|
732
|
tomwalters@0
|
733 /* 555555555555555555555555 stcrit 5555555555555555555555555555555555 */
|
tomwalters@0
|
734 /* Add on pulse peaks that exceed storbe threshold and which are not succeeded by
|
tomwalters@0
|
735 a larger pulse in nwid ms, provided total lag is < 2*nwid ms
|
tomwalters@0
|
736 Local Max mechanism with a timeout */
|
tomwalters@0
|
737
|
tomwalters@0
|
738 if (state->Stcrit==5)
|
tomwalters@0
|
739 {
|
tomwalters@0
|
740 for (chan = 0; chan < state->chans; chan++)
|
tomwalters@0
|
741 {
|
tomwalters@0
|
742 if(state->isStrobe[chan]) /* Check to see if it is time to addIn */
|
tomwalters@0
|
743 { /* check for waiting till the first local max found */
|
tomwalters@0
|
744 if (strobelag-1 >= state->def_strobe_candidate_time[chan])
|
tomwalters@0
|
745 /* initiate strobe after nwid ms */
|
tomwalters@0
|
746 {
|
tomwalters@0
|
747 /* print_trigger_debugging_info(state, chan, s_lag, 1); */
|
tomwalters@0
|
748 addIn(input-state->chans, chan, state);
|
tomwalters@0
|
749 doList_strobe_info(state, chan);
|
tomwalters@0
|
750
|
tomwalters@0
|
751 state->def_strobe_candidate_time[chan] = 0; /* Reset strobe time */
|
tomwalters@0
|
752 state->def_strobe_height[chan] = 0; /* Reset local max value */
|
tomwalters@0
|
753 state->trigheight[chan]=0;
|
tomwalters@0
|
754 state->isStrobe[chan]=0; /* Reset strobe flag */
|
tomwalters@0
|
755
|
tomwalters@0
|
756 }
|
tomwalters@0
|
757 }
|
tomwalters@0
|
758
|
tomwalters@0
|
759 /* Find a pulse peak routine */
|
tomwalters@0
|
760
|
tomwalters@0
|
761 if (!state->isPulse[chan]) /* Not in pulse, looking for pulse */
|
tomwalters@0
|
762 {
|
tomwalters@0
|
763 if (input[chan] > state->thresh[chan] && input[chan] > state->previnput[chan])
|
tomwalters@0
|
764 { /* Previnput check ensures threshold
|
tomwalters@0
|
765 decay does not cut into pulse */
|
tomwalters@0
|
766
|
tomwalters@0
|
767 state->isPulse[chan] = 1; /* set flag: in pulse */
|
tomwalters@0
|
768 state->thresh[chan] = input[chan]; /* start search for peak */
|
tomwalters@0
|
769 /* state->previnput[chan] = 1; in pulse till the next zero value */
|
tomwalters@0
|
770 }
|
tomwalters@0
|
771 else
|
tomwalters@0
|
772 {
|
tomwalters@0
|
773 decay_strobe_threshold(state, chan);
|
tomwalters@0
|
774 if (input[chan]==0) /* in the zeroes between nap pulses */
|
tomwalters@0
|
775 state->previnput[chan]=0; /* Free previnput */
|
tomwalters@0
|
776 }
|
tomwalters@0
|
777
|
tomwalters@0
|
778 }
|
tomwalters@0
|
779
|
tomwalters@0
|
780 if (state->isPulse[chan]) /* Else in ongoing pulse, looking for peak */
|
tomwalters@0
|
781 {
|
tomwalters@0
|
782 if (input[chan] <= state->thresh[chan] && input[chan] <= state->previnput[chan])
|
tomwalters@0
|
783 /* Pulse Peak Found */
|
tomwalters@0
|
784 {
|
tomwalters@0
|
785 state->isPulse[chan]=0; /* clear flag: not in pulse */
|
tomwalters@0
|
786
|
tomwalters@0
|
787 if (locmax_searchstart[chan]==0 )
|
tomwalters@0
|
788 /* && state->time>=((ttime[chan]-initial_strobe_candidate_time[chan])+ltime[chan])) AJD 1-2-96 */
|
tomwalters@0
|
789 { /* start local max time (for timeout)
|
tomwalters@0
|
790 and shift search window */
|
tomwalters@0
|
791 locmax_searchtime[chan]=1; /* local max time started */
|
tomwalters@0
|
792 locmax_searchstart[chan]=1; /* local max flag set */
|
tomwalters@0
|
793 print_trigger_debugging_info(state, chan, s_lag, 2);
|
tomwalters@0
|
794 initial_strobe_candidate_time[chan]=(state->time)-1; /* local max start time noted */
|
tomwalters@0
|
795
|
tomwalters@0
|
796 }
|
tomwalters@0
|
797
|
tomwalters@0
|
798 /* if (locmax_searchstart[chan]==1) */ /* 8rd March, 1995 AJayDatta */
|
tomwalters@0
|
799 if (state->thresh[chan] > state->trigheight[chan])
|
tomwalters@0
|
800 /* Check for LOCAL MAX */
|
tomwalters@0
|
801 {
|
tomwalters@0
|
802 state->trigheight[chan]=state->thresh[chan];
|
tomwalters@0
|
803 state->trigtime[chan]=(state->time)-1; /* Set strobe time */
|
tomwalters@0
|
804 if (!strcmp(exposwitch, "off"))
|
tomwalters@0
|
805 state->tlim[chan]=state->triggerdecay * state->trigheight[chan];
|
tomwalters@0
|
806 if (locmax_searchstart[chan]==1)
|
tomwalters@0
|
807 print_trigger_debugging_info(state, chan, s_lag, 3);
|
tomwalters@0
|
808 } /* if greater than thresh */
|
tomwalters@0
|
809
|
tomwalters@0
|
810
|
tomwalters@0
|
811 /* Reached end of time-out period (While in the peak finding stage !)
|
tomwalters@0
|
812 End of the timeout period can occur at two stages of the algorithm,
|
tomwalters@0
|
813 at a Nap pulse peak or at any point of the pulse train. */
|
tomwalters@0
|
814
|
tomwalters@0
|
815 if (locmax_searchtime[chan]==(state->stlag)) /* imagenwidth/state->chans)) */
|
tomwalters@0
|
816 {
|
tomwalters@0
|
817 print_trigger_debugging_info(state, chan, s_lag, 4);
|
tomwalters@0
|
818
|
tomwalters@0
|
819 state->def_strobe_candidate_time[chan]=state->trigtime[chan];
|
tomwalters@0
|
820 state->def_strobe_height[chan]=state->trigheight[chan];
|
tomwalters@0
|
821 locmax_searchtime[chan]=0;
|
tomwalters@0
|
822 locmax_searchstart[chan]=0;
|
tomwalters@0
|
823 state->trigheight[chan]=0;
|
tomwalters@0
|
824 state->trigtime[chan]=0;
|
tomwalters@0
|
825 state->isStrobe[chan]=1; /* set Strobe pending flag */
|
tomwalters@0
|
826 ltime[chan]=state->time; /* End of search time */
|
tomwalters@0
|
827 ttime[chan]=state->def_strobe_candidate_time[chan]; /* Local Max time */
|
tomwalters@0
|
828 }
|
tomwalters@0
|
829 /* reset search period to zero */
|
tomwalters@0
|
830 /* as y ms search period ends, update the info for strobe and
|
tomwalters@0
|
831 clear current_ values for the next y ms */
|
tomwalters@0
|
832 } /* Pulse Peak Loop */
|
tomwalters@0
|
833 else
|
tomwalters@0
|
834 state->thresh[chan]=input[chan];
|
tomwalters@0
|
835 } /* if (state->isPulse..) */
|
tomwalters@0
|
836
|
tomwalters@0
|
837 if (locmax_searchtime[chan] == (state->stlag)) /* imagenwidth/state->chans)) */
|
tomwalters@0
|
838 /* && state->def_strobe_candidate_time[chan]==0) */
|
tomwalters@0
|
839 { /* start local max time (for timeout) */
|
tomwalters@0
|
840 print_trigger_debugging_info(state, chan, s_lag, 5);
|
tomwalters@0
|
841
|
tomwalters@0
|
842 state->def_strobe_candidate_time[chan]=state->trigtime[chan];
|
tomwalters@0
|
843 state->def_strobe_height[chan]=state->trigheight[chan];
|
tomwalters@0
|
844 locmax_searchtime[chan]=0;
|
tomwalters@0
|
845 locmax_searchstart[chan]=0;
|
tomwalters@0
|
846 state->trigheight[chan]=0;
|
tomwalters@0
|
847 state->trigtime[chan]=0;
|
tomwalters@0
|
848 state->isStrobe[chan]=1; /* set Strobe pending flag */
|
tomwalters@0
|
849 ltime[chan]=state->time;
|
tomwalters@0
|
850 ttime[chan]=state->def_strobe_candidate_time[chan];
|
tomwalters@0
|
851 }
|
tomwalters@0
|
852 /* reset search period to zero */
|
tomwalters@0
|
853 /* as y ms search period ends, update the info for strobe and
|
tomwalters@0
|
854 clear current_ values for the next y ms */
|
tomwalters@0
|
855
|
tomwalters@0
|
856
|
tomwalters@0
|
857 if (locmax_searchstart[chan]==1)
|
tomwalters@0
|
858 (locmax_searchtime[chan])++;
|
tomwalters@0
|
859 state->previnput[chan]=input[chan];
|
tomwalters@0
|
860 output_thresh_info(state, chan);
|
tomwalters@0
|
861
|
tomwalters@0
|
862 } /* for all chans */
|
tomwalters@0
|
863 } /* if (state->Stcrit== 5) */
|
tomwalters@0
|
864
|
tomwalters@0
|
865
|
tomwalters@0
|
866 qq=insertl(state->time); /* insert time to list */
|
tomwalters@0
|
867 (state->time)++;
|
tomwalters@0
|
868 return;
|
tomwalters@0
|
869
|
tomwalters@0
|
870 } /* doColumn */
|
tomwalters@0
|
871
|
tomwalters@0
|
872
|
tomwalters@0
|
873 /****************************************************************************
|
tomwalters@0
|
874 * addIn
|
tomwalters@0
|
875 * add row cochleagram into stabilised image
|
tomwalters@0
|
876 ****************************************************************************/
|
tomwalters@0
|
877 static void addIn( input, chan, state )
|
tomwalters@0
|
878 DataType *input ;
|
tomwalters@0
|
879 int chan ;
|
tomwalters@0
|
880 struct _sai_state *state ;
|
tomwalters@0
|
881 {
|
tomwalters@0
|
882 register DataType *channel_ptr, *image_ptr, *end;
|
tomwalters@0
|
883 #ifdef FLOAT
|
tomwalters@0
|
884 register FLOAT input_scale = INPUT_SCALE ;
|
tomwalters@0
|
885 #endif
|
tomwalters@0
|
886 register ScalarType *decayfactor = state->framedecay;
|
tomwalters@0
|
887
|
tomwalters@0
|
888 /* Initialize channel_ptr to the input data to be added in. */
|
tomwalters@0
|
889 /* `input' points to a particular column in the cochleagram, */
|
tomwalters@0
|
890 /* and `chan' indexes a particular channel in this column. */
|
tomwalters@0
|
891 channel_ptr = input + chan ;
|
tomwalters@0
|
892 end = channel_ptr - state->imagewidth ;
|
tomwalters@0
|
893
|
tomwalters@0
|
894 /* Initialize image_ptr to end of sai row corresponding to `chan'.*/
|
tomwalters@0
|
895 /* `state->image' points to the start of the sai, */
|
tomwalters@0
|
896 /* so increment pointer by chan*framewidth to get to row `chan'. */
|
tomwalters@0
|
897 /* To get to end of row, increment by ((chan+1)*framewidth)-1. */
|
tomwalters@0
|
898 /* But framewidth = state->imagewidth / state->chans, and hence: */
|
tomwalters@0
|
899 /* Added fix; as new spiral.c accepts nwid AJD 17-3-95 */
|
tomwalters@0
|
900 if (state->Stcrit==4 && state->stlag==0)
|
tomwalters@0
|
901 image_ptr = (state->image + state->imagewidth / state->chans * (chan+1));
|
tomwalters@0
|
902 /* 13-3-95 removed -1; ajd */
|
tomwalters@0
|
903 else
|
tomwalters@0
|
904 image_ptr = (state->image + state->imagewidth / state->chans * (chan+1))-1;
|
tomwalters@0
|
905
|
tomwalters@0
|
906 /* Decrement channel_ptr by columns, from the initial column, */
|
tomwalters@0
|
907 /* until one complete sai row has been added into, which is when */
|
tomwalters@0
|
908 /* channel_ptr has decreased by a whole imagewidth. */
|
tomwalters@0
|
909 while( channel_ptr > end ) {
|
tomwalters@0
|
910 #ifdef FLOAT
|
tomwalters@0
|
911 *image_ptr += ( ( *channel_ptr * input_scale ) * (*decayfactor++) ) ;
|
tomwalters@0
|
912 #else
|
tomwalters@0
|
913 *image_ptr += DESCALE( ( *channel_ptr >> INPUT_SHIFT ) * (*decayfactor++) ) ;
|
tomwalters@0
|
914 #endif
|
tomwalters@0
|
915 /* if (state->chans <= 40) */
|
tomwalters@0
|
916 if (*image_ptr > 32767.0)
|
tomwalters@0
|
917 *image_ptr = 32767.0; /* 32767 */
|
tomwalters@0
|
918
|
tomwalters@0
|
919 image_ptr--;
|
tomwalters@0
|
920
|
tomwalters@0
|
921 channel_ptr -= state->chans ; /* next (ie previous) input time point */
|
tomwalters@0
|
922 }
|
tomwalters@0
|
923
|
tomwalters@0
|
924 return ;
|
tomwalters@0
|
925 }
|
tomwalters@0
|
926
|
tomwalters@0
|
927
|
tomwalters@0
|
928 /***************************************************************************
|
tomwalters@0
|
929 * Summary is not called in this module.
|
tomwalters@0
|
930 * (see SummaryEntry in model.c, which is the entry point for gensas).
|
tomwalters@0
|
931 * Summary computes a row summary spectrogram and is called during the
|
tomwalters@0
|
932 * program "gensas".
|
tomwalters@0
|
933
|
tomwalters@0
|
934 * Routines in this module it uses are:
|
tomwalters@0
|
935 * summary_callback
|
tomwalters@0
|
936 ****************************************************************************/
|
tomwalters@0
|
937
|
tomwalters@0
|
938 struct _summary_state {
|
tomwalters@0
|
939 struct _fillable_source parent ;
|
tomwalters@0
|
940 Source source;
|
tomwalters@0
|
941 int framewidth; /* number of time-points or cols in an sai */
|
tomwalters@0
|
942 int frameheight; /* number of channels or rows in an sai */
|
tomwalters@0
|
943 double scale;
|
tomwalters@0
|
944 int *llim; /* integration limits (lower & upper) for sai summary data */
|
tomwalters@0
|
945 int *ulim;
|
tomwalters@0
|
946 };
|
tomwalters@0
|
947
|
tomwalters@0
|
948
|
tomwalters@0
|
949 Source Summary( source, frameheight, scale, cfs, samplerate, llimstr, ulimstr)
|
tomwalters@0
|
950 Source source ;
|
tomwalters@0
|
951 int frameheight ;
|
tomwalters@0
|
952 double scale ;
|
tomwalters@0
|
953 double *cfs, samplerate ; /* array of channel centre frequencies */
|
tomwalters@0
|
954 char *llimstr, *ulimstr; /* lower and upper limit strings */
|
tomwalters@0
|
955 {
|
tomwalters@0
|
956 int i, framewidth, max_ulim=0, min_llim=99999999;
|
tomwalters@0
|
957
|
tomwalters@0
|
958 DeclareNew( struct _summary_state *, state ) ;
|
tomwalters@0
|
959
|
tomwalters@0
|
960 /* Allocate new arrays for integration limits */
|
tomwalters@0
|
961 state->llim = NewArray(int, frameheight, "image.c for lower limit array" );
|
tomwalters@0
|
962 state->ulim = NewArray(int, frameheight, "image.c for upper limit array" );
|
tomwalters@0
|
963
|
tomwalters@0
|
964 for (i=0 ; i<frameheight ; i++) {
|
tomwalters@0
|
965
|
tomwalters@0
|
966 /* Convert strings to sample points, allowing for cycles units */
|
tomwalters@0
|
967 state->llim[i] = Cycles( llimstr, cfs[i], Samplerate() );
|
tomwalters@0
|
968 state->ulim[i] = Cycles( ulimstr, cfs[i], Samplerate() );
|
tomwalters@0
|
969
|
tomwalters@0
|
970 /* Check that llim < ulim, and quit if not so */
|
tomwalters@0
|
971 if (state->llim[i] >= state->ulim[i])
|
tomwalters@0
|
972 stitch_error("Warning: gensas integration limits badly ordered\n");
|
tomwalters@0
|
973
|
tomwalters@0
|
974 /* Find limits on required framewidth */
|
tomwalters@0
|
975 if (state->ulim[i] > max_ulim)
|
tomwalters@0
|
976 max_ulim = state->ulim[i];
|
tomwalters@0
|
977 if (state->llim[i] < min_llim)
|
tomwalters@0
|
978 min_llim = state->llim[i];
|
tomwalters@0
|
979 }
|
tomwalters@0
|
980
|
tomwalters@0
|
981 if (min_llim > 0) min_llim = 0;
|
tomwalters@0
|
982 framewidth = max_ulim - min_llim;
|
tomwalters@0
|
983
|
tomwalters@0
|
984 /* Adjust the integration limits for an sai with triggering on the */
|
tomwalters@0
|
985 /* right. (The parameters llim <= ulim, but the resulting sai indices */
|
tomwalters@0
|
986 /* state->llim[i] > state->ulim[i]). */
|
tomwalters@0
|
987 /* This is done by subtracting from (framewidth-1), where framewidth is */
|
tomwalters@0
|
988 /* the maximum required number of points, (ie ulim in points). */
|
tomwalters@0
|
989
|
tomwalters@0
|
990 for (i=0 ; i<frameheight ; i++) {
|
tomwalters@0
|
991 state->llim[i] = framewidth - state->llim[i] ;
|
tomwalters@0
|
992 state->ulim[i] = framewidth - state->ulim[i] ;
|
tomwalters@0
|
993 }
|
tomwalters@0
|
994
|
tomwalters@0
|
995 framewidth++; /* extra point as array starts from zeroth location */
|
tomwalters@0
|
996
|
tomwalters@0
|
997 /* a blockings requests up into requests of the size specifed */
|
tomwalters@0
|
998 state->source = NewBlockingSource( source, sizeof ( DataType ) * framewidth * frameheight ) ;
|
tomwalters@0
|
999 state->framewidth = framewidth ;
|
tomwalters@0
|
1000 state->frameheight = frameheight ;
|
tomwalters@0
|
1001 state->scale = scale ;
|
tomwalters@0
|
1002
|
tomwalters@0
|
1003 return ( SetFillableSource( state, summary_callback, "image.c summarising sai" ) ) ;
|
tomwalters@0
|
1004 }
|
tomwalters@0
|
1005
|
tomwalters@0
|
1006 /*********************** Routines supporting Summary ***********************/
|
tomwalters@0
|
1007
|
tomwalters@0
|
1008 static Pointer summary_callback( state, bytes, buffer )
|
tomwalters@0
|
1009 struct _summary_state *state ;
|
tomwalters@0
|
1010 ByteCount *bytes ;
|
tomwalters@0
|
1011 DataType *buffer ;
|
tomwalters@0
|
1012 {
|
tomwalters@0
|
1013 register int last = *bytes == 0 ;
|
tomwalters@0
|
1014 register int i, j, ulim, llim, point, points=ToPoints(DataType,*bytes) ;
|
tomwalters@0
|
1015 register DataType *sairow;
|
tomwalters@0
|
1016 #ifdef FLOAT
|
tomwalters@0
|
1017 register DataType sum ;
|
tomwalters@0
|
1018 #else
|
tomwalters@0
|
1019 register long sum ;
|
tomwalters@0
|
1020 #endif
|
tomwalters@0
|
1021
|
tomwalters@0
|
1022 /* Pull an sai frame */
|
tomwalters@0
|
1023
|
tomwalters@0
|
1024 for( point=0 ; point < points ; )
|
tomwalters@0
|
1025 /* For each channel (row) in the sai, sum the row between the given limits */
|
tomwalters@0
|
1026 for(i=0 ; i<state->frameheight ; i++) {
|
tomwalters@0
|
1027
|
tomwalters@0
|
1028 sairow = PullItems(state->source,state->framewidth,DataType);
|
tomwalters@0
|
1029
|
tomwalters@0
|
1030 ulim = state->ulim[i];
|
tomwalters@0
|
1031 llim = state->llim[i];
|
tomwalters@0
|
1032 sum = 0;
|
tomwalters@0
|
1033 for (j=ulim ; j<=llim ; j++)
|
tomwalters@0
|
1034 sum += sairow[j];
|
tomwalters@0
|
1035
|
tomwalters@0
|
1036 /* store the row-sum, scaled and normalized for the range of the sum */
|
tomwalters@0
|
1037 buffer[point++] = sum*state->scale / (llim-ulim);
|
tomwalters@0
|
1038 }
|
tomwalters@0
|
1039
|
tomwalters@0
|
1040 if( !last )
|
tomwalters@0
|
1041 return ( (Pointer) buffer ) ;
|
tomwalters@0
|
1042 else {
|
tomwalters@0
|
1043 Delete( state->llim ) ;
|
tomwalters@0
|
1044 Delete( state->ulim ) ;
|
tomwalters@0
|
1045
|
tomwalters@0
|
1046 return ( DeleteFillableSource( state ) ) ;
|
tomwalters@0
|
1047 }
|
tomwalters@0
|
1048 }
|
tomwalters@0
|
1049
|
tomwalters@0
|
1050 /********************************************************************************/
|
tomwalters@0
|
1051 /* */
|
tomwalters@0
|
1052 /* initlist initialises the linked list pointer before the other list functions */
|
tomwalters@0
|
1053 /* call the list. */
|
tomwalters@0
|
1054 /* */
|
tomwalters@0
|
1055 /********************************************************************************/
|
tomwalters@0
|
1056 void initlist()
|
tomwalters@0
|
1057 {
|
tomwalters@0
|
1058 static int status=0;
|
tomwalters@0
|
1059 if (status==0)
|
tomwalters@0
|
1060 start = endl = pp = qq = (node *)malloc(sizeof(node));
|
tomwalters@0
|
1061 status=1;
|
tomwalters@0
|
1062 }
|
tomwalters@0
|
1063
|
tomwalters@0
|
1064 /********************************************************************************/
|
tomwalters@0
|
1065 /* */
|
tomwalters@0
|
1066 /* Function getnode allocates storage for a link list node and returns a */
|
tomwalters@0
|
1067 /* pointer to that node */
|
tomwalters@0
|
1068 /* */
|
tomwalters@0
|
1069 /********************************************************************************/
|
tomwalters@0
|
1070 node *getnode()
|
tomwalters@0
|
1071 {
|
tomwalters@0
|
1072 node *q;
|
tomwalters@0
|
1073 q=(node *)malloc(sizeof(node));
|
tomwalters@0
|
1074 if (q==NULL) exit(66);
|
tomwalters@0
|
1075 return q;
|
tomwalters@0
|
1076 }
|
tomwalters@0
|
1077
|
tomwalters@0
|
1078 /********************************************************************************/
|
tomwalters@0
|
1079 /* */
|
tomwalters@0
|
1080 /* The function insertl inserts the value x at the end of the linked list and */
|
tomwalters@0
|
1081 /* moves the end point by another node */
|
tomwalters@0
|
1082 /* */
|
tomwalters@0
|
1083 /********************************************************************************/
|
tomwalters@0
|
1084 node *insertl(x)
|
tomwalters@0
|
1085 int x;
|
tomwalters@0
|
1086 {
|
tomwalters@0
|
1087 node *q=endl;
|
tomwalters@0
|
1088 endl=getnode();
|
tomwalters@0
|
1089 q->next=endl;
|
tomwalters@0
|
1090 q->index=x;
|
tomwalters@0
|
1091 q->val=0;
|
tomwalters@0
|
1092 /* fprintf(testfile, "insertl: index is %d, val is %d\n", q->index, q->val); */
|
tomwalters@0
|
1093 return q;
|
tomwalters@0
|
1094 }
|
tomwalters@0
|
1095
|
tomwalters@0
|
1096 /********************************************************************************/
|
tomwalters@0
|
1097 /* */
|
tomwalters@0
|
1098 /* The function inss searches the list from the start, stops 3 nodes before the */
|
tomwalters@0
|
1099 /* value x, assigns the value -2000 to the three nodes till the (x+1)th node. */
|
tomwalters@0
|
1100 /* */
|
tomwalters@0
|
1101 /********************************************************************************/
|
tomwalters@0
|
1102 void inss(x)
|
tomwalters@0
|
1103 int x;
|
tomwalters@0
|
1104 {
|
tomwalters@0
|
1105 node *q=start;
|
tomwalters@0
|
1106 int y=x-3;
|
tomwalters@0
|
1107 int z=x;
|
tomwalters@0
|
1108 while (q!=endl)
|
tomwalters@0
|
1109 {
|
tomwalters@0
|
1110 if (q->index == y)
|
tomwalters@0
|
1111 do
|
tomwalters@0
|
1112 {
|
tomwalters@0
|
1113 q->val=-2000;
|
tomwalters@0
|
1114 q=q->next;
|
tomwalters@0
|
1115 /* fprintf(stderr, "Inss(x) index=%d\n",q->index); */
|
tomwalters@0
|
1116 } while (q->index < z);
|
tomwalters@0
|
1117 q=q->next;
|
tomwalters@0
|
1118 }
|
tomwalters@0
|
1119 }
|
tomwalters@0
|
1120
|
tomwalters@0
|
1121
|
tomwalters@0
|
1122 /********************************************************************************/
|
tomwalters@0
|
1123 /* */
|
tomwalters@0
|
1124 /* output_simple_strobe_info routine creates a file pointed by trigger file */
|
tomwalters@0
|
1125 /* which writes the points in the Nap pulse which initiates strobing */
|
tomwalters@0
|
1126 /* */
|
tomwalters@0
|
1127 /********************************************************************************/
|
tomwalters@0
|
1128 void output_simple_strobe_info(state, value)
|
tomwalters@0
|
1129 struct _sai_state *state;
|
tomwalters@0
|
1130 short value;
|
tomwalters@0
|
1131 {
|
tomwalters@0
|
1132
|
tomwalters@0
|
1133 if (!(!strcmp(state->switch_info, "off") || !strcmp(state->switch_info, "on")))
|
tomwalters@0
|
1134 fwrite(&(value), sizeof(short), 1 , trigger_file);
|
tomwalters@0
|
1135 }
|
tomwalters@0
|
1136
|
tomwalters@0
|
1137 /********************************************************************************/
|
tomwalters@0
|
1138 /* */
|
tomwalters@0
|
1139 /* doList_strobe_info creates a file (pointed by "trigger_file") which writes */
|
tomwalters@0
|
1140 /* in binary shorts the points in the Nap pulse which initiates a strobe */
|
tomwalters@0
|
1141 /* It uses a linked list data structure to keep track of the actual time which */
|
tomwalters@0
|
1142 /* causes a strobe, rather than the time when the strobing event occurs. */
|
tomwalters@0
|
1143 /* At stcrit 4 or 5, strobing occurs nwid ms after a nap pulse peak has been */
|
tomwalters@0
|
1144 /* located. */
|
tomwalters@0
|
1145 /* */
|
tomwalters@0
|
1146 /********************************************************************************/
|
tomwalters@0
|
1147 void doList_strobe_info(state, chan)
|
tomwalters@0
|
1148 struct _sai_state *state;
|
tomwalters@0
|
1149 int chan;
|
tomwalters@0
|
1150 {
|
tomwalters@0
|
1151 int storev;
|
tomwalters@0
|
1152
|
tomwalters@0
|
1153 if (state->Stcrit==2)
|
tomwalters@0
|
1154 storev=(state->time)-2;
|
tomwalters@0
|
1155 else if (state->Stcrit==5)
|
tomwalters@0
|
1156 storev=state->def_strobe_candidate_time[chan];
|
tomwalters@0
|
1157 /* fprintf(stderr, "Storev value of doList is = %d\n", storev);} */
|
tomwalters@0
|
1158 else
|
tomwalters@0
|
1159 storev=state->trigtime[chan];
|
tomwalters@0
|
1160
|
tomwalters@0
|
1161 inss(storev);
|
tomwalters@0
|
1162
|
tomwalters@0
|
1163 while (pp->index<=storev) /* (pp!=qq) */
|
tomwalters@0
|
1164 {
|
tomwalters@0
|
1165 if (!(!strcmp(state->switch_info, "off") || !strcmp(state->switch_info, "on")))
|
tomwalters@0
|
1166 fwrite(&(pp->val), sizeof(short), 1, trigger_file);
|
tomwalters@0
|
1167 /* fprintf(testfile, "doList: index is %d, val is %d\n", pp->index, pp->val); */
|
tomwalters@0
|
1168 pp=pp->next;
|
tomwalters@0
|
1169 }
|
tomwalters@0
|
1170 /* pp=qq; */
|
tomwalters@0
|
1171 }
|
tomwalters@0
|
1172
|
tomwalters@0
|
1173 /********************************************************************************/
|
tomwalters@0
|
1174 /* */
|
tomwalters@0
|
1175 /* output_thresh_info writes threshold values (in binary shorts or floats) to */
|
tomwalters@0
|
1176 /* the file opened by the file pointer "thresho_file" */
|
tomwalters@0
|
1177 /* */
|
tomwalters@0
|
1178 /********************************************************************************/
|
tomwalters@0
|
1179 void output_thresh_info(state, chan)
|
tomwalters@0
|
1180 struct _sai_state *state;
|
tomwalters@0
|
1181 int chan;
|
tomwalters@0
|
1182 {
|
tomwalters@0
|
1183 S[chan]=state->thresh[chan];
|
tomwalters@0
|
1184
|
tomwalters@0
|
1185 if (!(!strcmp(state->switch_info, "off") || !strcmp(state->switch_info, "on")))
|
tomwalters@0
|
1186 #ifdef FLOAT
|
tomwalters@0
|
1187 fwrite((S+chan), sizeof(float), 1, thresho_file);
|
tomwalters@0
|
1188 #else
|
tomwalters@0
|
1189 fwrite((S+chan), sizeof(short), 1, thresho_file);
|
tomwalters@0
|
1190 #endif
|
tomwalters@0
|
1191
|
tomwalters@0
|
1192 }
|
tomwalters@0
|
1193
|
tomwalters@0
|
1194 /********************************************************************************/
|
tomwalters@0
|
1195 /* */
|
tomwalters@0
|
1196 /* decay_strobe_threshold decays the strobe threshold at every clock */
|
tomwalters@0
|
1197 /* tick either linearly or exponentially */
|
tomwalters@0
|
1198 /* */
|
tomwalters@0
|
1199 /********************************************************************************/
|
tomwalters@0
|
1200 void decay_strobe_threshold(state, chan)
|
tomwalters@0
|
1201 struct _sai_state *state;
|
tomwalters@0
|
1202 int chan;
|
tomwalters@0
|
1203 {
|
tomwalters@0
|
1204
|
tomwalters@0
|
1205 if (!strcmp(exposwitch, "on"))
|
tomwalters@0
|
1206 state->thresh[chan] *= state->triggerdecay;
|
tomwalters@0
|
1207 else
|
tomwalters@0
|
1208 {
|
tomwalters@0
|
1209 state->thresh[chan] -= state->tlim[chan];
|
tomwalters@0
|
1210 if (state->thresh[chan] < 0)
|
tomwalters@0
|
1211 state->thresh[chan]=0;
|
tomwalters@0
|
1212 }
|
tomwalters@0
|
1213 }
|
tomwalters@0
|
1214
|
tomwalters@0
|
1215 /********************************************************************************/
|
tomwalters@0
|
1216 /* */
|
tomwalters@0
|
1217 /* This routine prints debugging information of the local max search */
|
tomwalters@0
|
1218 /* with timeout (i.e. stcrit_ai=5) */
|
tomwalters@0
|
1219 /* */
|
tomwalters@0
|
1220 /********************************************************************************/
|
tomwalters@0
|
1221 void print_trigger_debugging_info(state, chan, strobe_lag, stage)
|
tomwalters@0
|
1222 struct _sai_state *state;
|
tomwalters@0
|
1223 int chan;
|
tomwalters@0
|
1224 int strobe_lag;
|
tomwalters@0
|
1225 int stage;
|
tomwalters@0
|
1226 {
|
tomwalters@0
|
1227 if (stage==1)
|
tomwalters@0
|
1228 {
|
tomwalters@0
|
1229 if (strobe_lag > state->def_strobe_candidate_time[chan])
|
tomwalters@0
|
1230 val[chan]=strobe_lag-state->def_strobe_candidate_time[chan];
|
tomwalters@0
|
1231 if (strobe_lag == state->def_strobe_candidate_time[chan])
|
tomwalters@0
|
1232 val[chan]=0;
|
tomwalters@0
|
1233
|
tomwalters@0
|
1234 if (!strcmp(state->switch_info,"off"));
|
tomwalters@0
|
1235 else
|
tomwalters@0
|
1236 fprintf(infotxt_file, "Chan %d: :: Actual time of trigger: s_lag=%d, trigtime=%d\n", chan, strobe_lag, state->def_strobe_candidate_time[chan]);
|
tomwalters@0
|
1237 }
|
tomwalters@0
|
1238
|
tomwalters@0
|
1239 /* fprintf(infotxt_file, "Chan %d: Actual time of trigger: s_lag=%d, trigtime=%d, shift=%d\n", chan, strobe_lag, state->def_strobe_candidate_time[chan], val[chan]*state->chans); */
|
tomwalters@0
|
1240
|
tomwalters@0
|
1241
|
tomwalters@0
|
1242 if (stage==2)
|
tomwalters@0
|
1243 {
|
tomwalters@0
|
1244 if (!strcmp(state->switch_info,"off"));
|
tomwalters@0
|
1245 else
|
tomwalters@0
|
1246 fprintf(infotxt_file, "Chan %d: Loc Max Start Time = %d, trigcurrent %d, Threshold=%f, shift=%d\n", chan, state->time, state->trigheight[chan], state->thresh[chan], (ttime[chan]-initial_strobe_candidate_time[chan]));
|
tomwalters@0
|
1247 }
|
tomwalters@0
|
1248
|
tomwalters@0
|
1249 if (stage==3)
|
tomwalters@0
|
1250 {
|
tomwalters@0
|
1251 if (!strcmp(state->switch_info,"off"));
|
tomwalters@0
|
1252 else
|
tomwalters@0
|
1253 fprintf(infotxt_file, "Chan %d: Loc Max is %d Time is %d\n", chan, state->trigheight[chan], state->trigtime[chan] );
|
tomwalters@0
|
1254 }
|
tomwalters@0
|
1255
|
tomwalters@0
|
1256 if (stage==4)
|
tomwalters@0
|
1257 {
|
tomwalters@0
|
1258 if (!strcmp(state->switch_info,"off"));
|
tomwalters@0
|
1259 else
|
tomwalters@0
|
1260 fprintf(infotxt_file, "Chan %d: At the End of Search (At peak), trigtime = %d time = %d height = %d\n", chan, state->trigtime[chan], state->time, state->trigheight[chan]);
|
tomwalters@0
|
1261 }
|
tomwalters@0
|
1262 if (stage==5)
|
tomwalters@0
|
1263 {
|
tomwalters@0
|
1264 if (!strcmp(state->switch_info,"off"));
|
tomwalters@0
|
1265 else
|
tomwalters@0
|
1266 fprintf(infotxt_file, "Chan %d: At the End of Search, trigtime = %d time = %d height = %d\n", chan, state->trigtime[chan], state->time, state->trigheight[chan]);
|
tomwalters@0
|
1267 }
|
tomwalters@0
|
1268
|
tomwalters@0
|
1269
|
tomwalters@0
|
1270 }
|
tomwalters@0
|
1271
|