tomwalters@0
|
1 /*
|
tomwalters@0
|
2 acgram.c Autocorrelogram program by Michael Allerhand.
|
tomwalters@0
|
3 ----------
|
tomwalters@0
|
4
|
tomwalters@0
|
5 Short-time autocorrelation function applied to each row of input frames.
|
tomwalters@0
|
6 Output frames consist of row-wise autocorrelation coefficients.
|
tomwalters@0
|
7 The routine acf() uses an fft to compute the array of lagged products
|
tomwalters@0
|
8 which is the autocovariance function. An optional normalization (dividing
|
tomwalters@0
|
9 each coefficient by the zeroth coefficient) produces the autocorrelation
|
tomwalters@0
|
10 function, (and this is then scaled up to the range [0-5000]).
|
tomwalters@0
|
11
|
tomwalters@0
|
12 Input/output:
|
tomwalters@0
|
13 Read a header and frame in NAP format.
|
tomwalters@0
|
14 Write a header, (constructed from the original input header), and a
|
tomwalters@0
|
15 succession of frames in SAI format.
|
tomwalters@0
|
16
|
tomwalters@0
|
17 The input file is interpreted as one large frame in NAP format to be
|
tomwalters@0
|
18 divided into input frames, each to be processed and output in SAI format.
|
tomwalters@0
|
19
|
tomwalters@0
|
20 The options "start" and "length" specify the input file.
|
tomwalters@0
|
21 The special option value length=max specifies all the input file from
|
tomwalters@0
|
22 the given start to its end.
|
tomwalters@0
|
23
|
tomwalters@0
|
24 The options "width" and "frstep" specify the input frames.
|
tomwalters@0
|
25 The width option is the framewidth of each input frame) and the frstep
|
tomwalters@0
|
26 option is the frameshift between input frames in the input file.
|
tomwalters@0
|
27 The special option value width=max specifies the input framewidth as equal
|
tomwalters@0
|
28 to the given input file length, (and if this is also "max", then the
|
tomwalters@0
|
29 input framewidth is the remainder of the input file).
|
tomwalters@0
|
30
|
tomwalters@0
|
31 Most options in the input header are copied to the output header.
|
tomwalters@0
|
32 This enables options which are needed for the eventual display
|
tomwalters@0
|
33 to pass straight through. Some options are set so that they can override
|
tomwalters@0
|
34 the input header. For example, the display option is set on to enable
|
tomwalters@0
|
35 display even when input has display=off. The animate option can be set on
|
tomwalters@0
|
36 even when the input has animate=off.
|
tomwalters@0
|
37 Parts of the header are changed for the new sai format:
|
tomwalters@0
|
38 (frames, frameshift, framewidth, frameheight, framebytes).
|
tomwalters@0
|
39
|
tomwalters@0
|
40 Padding:
|
tomwalters@0
|
41 The output framewidth is the given maximum acf lag, which is also the
|
tomwalters@0
|
42 number of acf coefficients computed from each row of each input frame.
|
tomwalters@0
|
43 The rows of each input frame are padded with zeroes so that the input
|
tomwalters@0
|
44 framewidth is at least twice the required output framewidth (max acf lag),
|
tomwalters@0
|
45 and also a power of 2. This is because the fft method is "radix-2", and
|
tomwalters@0
|
46 because the output acf is symmetrical so that just half the points are
|
tomwalters@0
|
47 unique. It is advisable to pad input frames for the additional reason that
|
tomwalters@0
|
48 padding counters end-effects (which can be significant with the fft method
|
tomwalters@0
|
49 for computing acf).
|
tomwalters@0
|
50
|
tomwalters@0
|
51 Therefore each row of each input frame is padded with zeroes to the next
|
tomwalters@0
|
52 power of 2 larger than either the original input framewidth or twice the
|
tomwalters@0
|
53 max acf lag (whichever is the larger).
|
tomwalters@0
|
54 If necessary, extra padding can be enforced using the padding option to
|
tomwalters@0
|
55 add extra zeroes, padding to a larger power of 2.
|
tomwalters@0
|
56 The amount of extra padding is "exponential" since if the basic padded
|
tomwalters@0
|
57 framesize is N, and the padding option is n, then extra padding is to:
|
tomwalters@0
|
58 N * 2**n.
|
tomwalters@0
|
59 (n=0 by default, so that N is not changed. When n=1 then N is doubled, and
|
tomwalters@0
|
60 when n=2 then N is quadrupled, etc.).
|
tomwalters@0
|
61
|
tomwalters@0
|
62
|
tomwalters@0
|
63 Examples:
|
tomwalters@0
|
64
|
tomwalters@0
|
65 1. Autocorrelogram of a NAP, animated and normalized, with max lag 16ms:
|
tomwalters@0
|
66
|
tomwalters@0
|
67 gennap len=128ms output=stdout display=off file | acgram lag=16ms norm=on anim=on > file.sai
|
tomwalters@0
|
68 gensai useprev=on headr=5 top=1000 file -(for landscape plot)
|
tomwalters@0
|
69 genspl useprev=on headr=5 top=1000 pensize=2 file -(for spiral plot)
|
tomwalters@0
|
70
|
tomwalters@0
|
71 2. Autocorrelogram of an SAI:
|
tomwalters@0
|
72 (Note that gensai removes file.sai, so you must use some other name, eg foo.sai).
|
tomwalters@0
|
73
|
tomwalters@0
|
74 gensai len=64 pwidth=64 nwidth=0 output=stdout display=off file | \
|
tomwalters@0
|
75 saitonap frame=3 | acgram lag=32ms frame=1 > foo.sai
|
tomwalters@0
|
76 gensai useprev=on top=1000 headr=5 mag=2 foo
|
tomwalters@0
|
77
|
tomwalters@0
|
78 3. Autocorrelogram of a NAP, followed by a cross-channel summary:
|
tomwalters@0
|
79
|
tomwalters@0
|
80 gennap len=128ms output=stdout display=off file | acgram lag=16ms scale=0.001 > file.sai
|
tomwalters@0
|
81 edframe frame=1 file.sai | integframe var=freq > file.sum
|
tomwalters@0
|
82
|
tomwalters@0
|
83 */
|
tomwalters@0
|
84
|
tomwalters@0
|
85
|
tomwalters@0
|
86 #include <stdio.h>
|
tomwalters@0
|
87 #include <math.h>
|
tomwalters@0
|
88 #include "header.h"
|
tomwalters@0
|
89 #include "options.h"
|
tomwalters@0
|
90 #include "units.h"
|
tomwalters@0
|
91 #include "strmatch.h"
|
tomwalters@0
|
92 #include "sigproc.h"
|
tomwalters@0
|
93
|
tomwalters@0
|
94 char applic[] = "Autocorrelogram auditory image." ;
|
tomwalters@0
|
95
|
tomwalters@0
|
96 static char *helpstr , *debugstr, *dispstr , *anistr , *startstr ;
|
tomwalters@0
|
97 static char *lengthstr, *widthstr, *shiftstr, *headerstr, *framestr ;
|
tomwalters@0
|
98 static char *normstr , *wstr , *scalestr, *lagstr , *padstr ;
|
tomwalters@0
|
99 static char *negstr , *vstr ;
|
tomwalters@0
|
100
|
tomwalters@0
|
101 static Options option[] = {
|
tomwalters@0
|
102 { "help" , "off" , &helpstr , "help" , DEBUG },
|
tomwalters@0
|
103 { "debug" , "off" , &debugstr , "debugging switch" , DEBUG },
|
tomwalters@0
|
104 { "display" , "on" , &dispstr , "Display output image." , SETFLAG },
|
tomwalters@0
|
105 { "animate" , "off" , &anistr , "Animate cartoon." , SETFLAG },
|
tomwalters@0
|
106 { "frames" , "1-max" , &framestr , "Select frames inclusively" , VAL },
|
tomwalters@0
|
107 { "Header" , "on" , &headerstr , "Header (for gensai useprevious=on)." , VAL },
|
tomwalters@0
|
108 { "start" , "0" , &startstr , "Start point in i/p file." , VAL },
|
tomwalters@0
|
109 { "length" , "max" , &lengthstr , "Length of i/p file to process." , VAL },
|
tomwalters@0
|
110 { "frstep" , "16ms" , &shiftstr , "Step between input frames." , VAL },
|
tomwalters@0
|
111 { "width" , "32ms" , &widthstr , "Width of input frames." , VAL },
|
tomwalters@0
|
112 { "lag" , "32ms" , &lagstr , "Maximum acf lag (output frame width)." , VAL },
|
tomwalters@0
|
113 { "padding" , "0" , &padstr , "Exponential frame padding" , SVAL },
|
tomwalters@0
|
114 { "window" , "on" , &wstr , "Hamming window" , SETFLAG },
|
tomwalters@0
|
115 { "normalize" , "off" , &normstr , "Normalization" , SETFLAG },
|
tomwalters@0
|
116 { "scale" , "1." , &scalestr , "Scale factor for output" , VAL },
|
tomwalters@0
|
117 { "negative" , "off" , &negstr , "write negative half of acf (zeroth lag on right)", SVAL },
|
tomwalters@0
|
118 { "verbose" , "off" , &vstr , "print at each frame" , SVAL },
|
tomwalters@0
|
119 ( char * ) 0 } ;
|
tomwalters@0
|
120
|
tomwalters@0
|
121
|
tomwalters@0
|
122 int samplerate ;
|
tomwalters@0
|
123
|
tomwalters@0
|
124 int frameheight, framewidth ;
|
tomwalters@0
|
125 int frames, framebytes ;
|
tomwalters@0
|
126 int frameshift ;
|
tomwalters@0
|
127
|
tomwalters@0
|
128 int Newframeheight, Newframewidth ;
|
tomwalters@0
|
129 int Newframes, Newframebytes ;
|
tomwalters@0
|
130 int Newframeshift ;
|
tomwalters@0
|
131
|
tomwalters@0
|
132 int start, length ; /* Size of input file (num cols) */
|
tomwalters@0
|
133 int frameslength ; /* Length (num cols) of input file to process */
|
tomwalters@0
|
134
|
tomwalters@0
|
135 int zeroes ;
|
tomwalters@0
|
136 int window ; /* Flag for Hamming window */
|
tomwalters@0
|
137 float scale ; /* Scale factor for output */
|
tomwalters@0
|
138 int normalize ; /* Flag to normalize acf */
|
tomwalters@0
|
139 int negative ;
|
tomwalters@0
|
140 int Verbose ;
|
tomwalters@0
|
141
|
tomwalters@0
|
142 short *file ; /* Input file (NAP format) */
|
tomwalters@0
|
143 float *W ; /* Hamming window for fft */
|
tomwalters@0
|
144 float *buf ; /* fft working space */
|
tomwalters@0
|
145
|
tomwalters@0
|
146
|
tomwalters@0
|
147 main(argc, argv)
|
tomwalters@0
|
148 int argc ;
|
tomwalters@0
|
149 char *argv[] ;
|
tomwalters@0
|
150 {
|
tomwalters@0
|
151 FILE *fp ;
|
tomwalters@0
|
152 char *header, *SaiHeader();
|
tomwalters@0
|
153 char *versionstr, c ;
|
tomwalters@0
|
154 int startbytes, framebyteshift ;
|
tomwalters@0
|
155 short *frame, *endframe ;
|
tomwalters@0
|
156 int i, a, b ;
|
tomwalters@0
|
157 float acgram(), f, newscale = 1. ;
|
tomwalters@0
|
158
|
tomwalters@0
|
159 fp = openopts( option,argc,argv ) ;
|
tomwalters@0
|
160 if ( !isoff( helpstr ) )
|
tomwalters@0
|
161 helpopts( helpstr, argv[0], applic, option ) ;
|
tomwalters@0
|
162
|
tomwalters@0
|
163 window = ison( wstr ) ;
|
tomwalters@0
|
164 normalize = ison( normstr ) ;
|
tomwalters@0
|
165 negative = ison( negstr ) ;
|
tomwalters@0
|
166 Verbose = ison( vstr ) ;
|
tomwalters@0
|
167
|
tomwalters@0
|
168
|
tomwalters@0
|
169 /**** parse bounds on number of frames ****/
|
tomwalters@0
|
170
|
tomwalters@0
|
171 if ( selector( framestr, &a, &b ) == 0 ) {
|
tomwalters@0
|
172 fprintf(stderr,"acgram: bad frame selector [%s]\n", framestr ) ;
|
tomwalters@0
|
173 exit( 1 ) ;
|
tomwalters@0
|
174 }
|
tomwalters@0
|
175
|
tomwalters@0
|
176
|
tomwalters@0
|
177 /**** Input frame dimensions (from header and options) ****/
|
tomwalters@0
|
178
|
tomwalters@0
|
179 if ((header = ReadHeader(fp)) == (char *) 0 ) {
|
tomwalters@0
|
180 fprintf(stderr,"acgram: header not found\n");
|
tomwalters@0
|
181 exit(1);
|
tomwalters@0
|
182 }
|
tomwalters@0
|
183
|
tomwalters@0
|
184 if ( (versionstr = HeaderString( header, "Version" )) == (char *)0 ) {
|
tomwalters@0
|
185 fprintf(stderr,"acgram: model version-number not found in header\n");
|
tomwalters@0
|
186 exit(1);
|
tomwalters@0
|
187 }
|
tomwalters@0
|
188
|
tomwalters@0
|
189 samplerate = HeaderSamplerate( header );
|
tomwalters@0
|
190
|
tomwalters@0
|
191 /* In NAP format, the size of the 2-D image is given by: */
|
tomwalters@0
|
192 /* frameheight = number of rows (filterbank channels) */
|
tomwalters@0
|
193 /* frames = number of columns (sample points) */
|
tomwalters@0
|
194
|
tomwalters@0
|
195 frameheight = HeaderInt( header, "frameheight" );
|
tomwalters@0
|
196 frames = HeaderInt( header, "frames" );
|
tomwalters@0
|
197
|
tomwalters@0
|
198 if ( ( frameshift = to_p( shiftstr, samplerate ) ) <= 0 ) {
|
tomwalters@0
|
199 fprintf(stderr,"acgram: non-positive frstep [%d]\n", frameshift);
|
tomwalters@0
|
200 exit(1);
|
tomwalters@0
|
201 }
|
tomwalters@0
|
202
|
tomwalters@0
|
203 /* calculate start of first frame (in cols) */
|
tomwalters@0
|
204
|
tomwalters@0
|
205 if ( ( start = to_p( startstr, samplerate ) + ( a-1 ) * frameshift ) >= frames ) {
|
tomwalters@0
|
206 fprintf(stderr,"acgram: input file too small (%dms) for given framing parameters\n", frames * 1000 / samplerate );
|
tomwalters@0
|
207 exit(1);
|
tomwalters@0
|
208 }
|
tomwalters@0
|
209
|
tomwalters@0
|
210 /* get length of input file (in cols) and framewidth of input frames */
|
tomwalters@0
|
211
|
tomwalters@0
|
212 if ( ismax( lengthstr ) ) length = frames - start ;
|
tomwalters@0
|
213 else length = to_p( lengthstr, samplerate ) - start ;
|
tomwalters@0
|
214
|
tomwalters@0
|
215 if ( ismax( widthstr ) ) framewidth = length ;
|
tomwalters@0
|
216 else framewidth = to_p( widthstr, samplerate ) ;
|
tomwalters@0
|
217
|
tomwalters@0
|
218 if ( length < framewidth ) {
|
tomwalters@0
|
219 fprintf(stderr,"acgram: input file too small (%dms) for given framing parameters\n", frames * 1000 / samplerate );
|
tomwalters@0
|
220 exit(1);
|
tomwalters@0
|
221 }
|
tomwalters@0
|
222
|
tomwalters@0
|
223 /* calculate length (num cols) to process, and the number of frames */
|
tomwalters@0
|
224
|
tomwalters@0
|
225 if ( b==0 ) {
|
tomwalters@0
|
226 frameslength = length ;
|
tomwalters@0
|
227 Newframes = 1 + ( length - framewidth ) / frameshift ;
|
tomwalters@0
|
228 }
|
tomwalters@0
|
229 else {
|
tomwalters@0
|
230 frameslength = framewidth + ( b-a ) * frameshift ;
|
tomwalters@0
|
231 Newframes = b - ( a-1 ) ;
|
tomwalters@0
|
232 }
|
tomwalters@0
|
233
|
tomwalters@0
|
234 if ( start + frameslength > frames ) {
|
tomwalters@0
|
235 fprintf(stderr,"acgram: input file too small (%dms) for requested start and length \n", frames * 1000 / samplerate );
|
tomwalters@0
|
236 exit(1);
|
tomwalters@0
|
237 }
|
tomwalters@0
|
238
|
tomwalters@0
|
239 framebytes = frameheight * frameslength * sizeof(short) ;
|
tomwalters@0
|
240 startbytes = frameheight * start * sizeof(short) ;
|
tomwalters@0
|
241
|
tomwalters@0
|
242
|
tomwalters@0
|
243 /**** Output frame dimensions ****/
|
tomwalters@0
|
244
|
tomwalters@0
|
245 Newframeheight = frameheight ;
|
tomwalters@0
|
246 Newframewidth = to_p( lagstr, samplerate ); /* Max acf lag */
|
tomwalters@0
|
247 Newframeshift = frameshift ;
|
tomwalters@0
|
248 Newframebytes = Newframeheight * Newframewidth * sizeof(short) ;
|
tomwalters@0
|
249
|
tomwalters@0
|
250
|
tomwalters@0
|
251 /**** Padding and output scale factor ****/
|
tomwalters@0
|
252
|
tomwalters@0
|
253 if ( ( Newframewidth << 1 ) < framewidth )
|
tomwalters@0
|
254 zeroes = ( getpower( framewidth ) << atoi( padstr ) ) - framewidth ;
|
tomwalters@0
|
255 else if ( Newframewidth <= framewidth )
|
tomwalters@0
|
256 zeroes = ( getpower( Newframewidth << 1 ) << atoi( padstr ) ) - framewidth ;
|
tomwalters@0
|
257 else {
|
tomwalters@0
|
258 fprintf(stderr,"acgram: required max lag [%dms] greater than framewidth [%dms]\n", Newframewidth*1000/samplerate, framewidth*1000/samplerate);
|
tomwalters@0
|
259 exit( 1 ) ;
|
tomwalters@0
|
260 }
|
tomwalters@0
|
261
|
tomwalters@0
|
262 if ( normalize == 0 ) /* no normalize, so divide by length to get average of products */
|
tomwalters@0
|
263 scale = 1./(double)(framewidth + zeroes) * atof( scalestr ) ;
|
tomwalters@0
|
264 else
|
tomwalters@0
|
265 scale = atof( scalestr ) ;
|
tomwalters@0
|
266
|
tomwalters@0
|
267
|
tomwalters@0
|
268 /**** Debug ****/
|
tomwalters@0
|
269
|
tomwalters@0
|
270 if ( ison( debugstr ) ) {
|
tomwalters@0
|
271 fprintf(stderr, "Input: frames=%d frameheight=%d frameshift=%d\n", frames, frameheight, frameshift ) ;
|
tomwalters@0
|
272 fprintf(stderr, "Sizes: start=%d length=%d framewidth=%d frameslength=%d\n", start, length, framewidth, frameslength ) ;
|
tomwalters@0
|
273 fprintf(stderr, "Output: zeroes=%d Newframewidth=%d Newframes=%d \n", zeroes, Newframewidth, Newframes ) ;
|
tomwalters@0
|
274 exit( 1 ) ;
|
tomwalters@0
|
275 }
|
tomwalters@0
|
276
|
tomwalters@0
|
277
|
tomwalters@0
|
278 /**** Allocate space (input file, window coeffs, and fft working space) ****/
|
tomwalters@0
|
279
|
tomwalters@0
|
280 if ( ( file = (short *)malloc( framebytes ) ) == NULL ) {
|
tomwalters@0
|
281 fprintf(stderr,"acgram: malloc out of space\n");
|
tomwalters@0
|
282 exit(1);
|
tomwalters@0
|
283 }
|
tomwalters@0
|
284
|
tomwalters@0
|
285 if ( window )
|
tomwalters@0
|
286 W = hamming( framewidth ) ;
|
tomwalters@0
|
287
|
tomwalters@0
|
288 buf = (float *)malloc( ( framewidth + zeroes ) * sizeof(float) );
|
tomwalters@0
|
289
|
tomwalters@0
|
290
|
tomwalters@0
|
291 /**** Write new sai header ****/
|
tomwalters@0
|
292
|
tomwalters@0
|
293 if ( ison( headerstr ) )
|
tomwalters@0
|
294 WriteHeader( SaiHeader(header), stdout );
|
tomwalters@0
|
295
|
tomwalters@0
|
296
|
tomwalters@0
|
297 /**** Seek to start of input file in blocks of framebytes ****/
|
tomwalters@0
|
298
|
tomwalters@0
|
299 for (i=framebytes ; i < startbytes ; i += framebytes)
|
tomwalters@0
|
300 if ( fread( file, framebytes, 1, fp ) == NULL ) {
|
tomwalters@0
|
301 fprintf(stderr,"acgram: missing data after header\n");
|
tomwalters@0
|
302 exit(1);
|
tomwalters@0
|
303 }
|
tomwalters@0
|
304 if ( (startbytes -= (i - framebytes)) > 0 )
|
tomwalters@0
|
305 if ( fread( file, startbytes, 1, fp ) == NULL ) {
|
tomwalters@0
|
306 fprintf(stderr,"acgram: missing data after header\n");
|
tomwalters@0
|
307 exit(1);
|
tomwalters@0
|
308 }
|
tomwalters@0
|
309
|
tomwalters@0
|
310
|
tomwalters@0
|
311 /**** Read framebytes of i/p file ****/
|
tomwalters@0
|
312
|
tomwalters@0
|
313 if ( fread( file, framebytes, 1, fp ) == NULL ) {
|
tomwalters@0
|
314 fprintf(stderr,"acgram: missing data after header\n");
|
tomwalters@0
|
315 exit(1);
|
tomwalters@0
|
316 }
|
tomwalters@0
|
317
|
tomwalters@0
|
318
|
tomwalters@0
|
319 /**** Process frames ****/
|
tomwalters@0
|
320
|
tomwalters@0
|
321 framebyteshift = frameshift * frameheight ;
|
tomwalters@0
|
322 endframe = file + Newframes * framebyteshift ;
|
tomwalters@0
|
323
|
tomwalters@0
|
324 for ( frame = file, i=1 ; frame < endframe ; frame += framebyteshift, i++ ) {
|
tomwalters@0
|
325 if ( Verbose )
|
tomwalters@0
|
326 fprintf(stderr,"acgram: %d / %d [%dms]\n", i, Newframes, start*1000/samplerate );
|
tomwalters@0
|
327 if ( ( f = acgram( frame ) ) < newscale )
|
tomwalters@0
|
328 newscale = f ;
|
tomwalters@0
|
329 start += frameshift ;
|
tomwalters@0
|
330 }
|
tomwalters@0
|
331
|
tomwalters@0
|
332 fclose(fp);
|
tomwalters@0
|
333
|
tomwalters@0
|
334 if ( newscale < 1. ) {
|
tomwalters@0
|
335 fprintf( stderr, "Warning: 16-bit overflow during acgram. " ) ;
|
tomwalters@0
|
336 if ( normalize == 0 )
|
tomwalters@0
|
337 fprintf( stderr, "Try scale<%f\n", newscale * (float)(framewidth + zeroes) ) ;
|
tomwalters@0
|
338 else
|
tomwalters@0
|
339 fprintf( stderr, "Try scale<%f\n", newscale ) ;
|
tomwalters@0
|
340 }
|
tomwalters@0
|
341
|
tomwalters@0
|
342 if ( Verbose )
|
tomwalters@0
|
343 fprintf(stderr,"acgram: done\n" ) ;
|
tomwalters@0
|
344 }
|
tomwalters@0
|
345
|
tomwalters@0
|
346
|
tomwalters@0
|
347 /************************** Autocorrelation function ***********************/
|
tomwalters@0
|
348
|
tomwalters@0
|
349 /* Call acf for each row in the SAI frame */
|
tomwalters@0
|
350
|
tomwalters@0
|
351 float acgram( frame )
|
tomwalters@0
|
352 short *frame ;
|
tomwalters@0
|
353 {
|
tomwalters@0
|
354 register int i, j, row, col ;
|
tomwalters@0
|
355 float writebuf(), f, newscale = 1. ;
|
tomwalters@0
|
356
|
tomwalters@0
|
357 for ( row=0 ; row < frameheight ; row++ ) {
|
tomwalters@0
|
358
|
tomwalters@0
|
359 if ( window )
|
tomwalters@0
|
360 for ( col=0 , i=row ; col < framewidth ; col++, i+=frameheight )
|
tomwalters@0
|
361 buf[col] = frame[i] * W[col] ;
|
tomwalters@0
|
362 else
|
tomwalters@0
|
363 for ( col=0 , i=row ; col < framewidth ; col++, i+=frameheight )
|
tomwalters@0
|
364 buf[col] = frame[i] ;
|
tomwalters@0
|
365
|
tomwalters@0
|
366 for ( j=0 ; j<zeroes ; j++ ) /* padding */
|
tomwalters@0
|
367 buf[col++] = 0 ;
|
tomwalters@0
|
368
|
tomwalters@0
|
369 acf( buf, framewidth+zeroes ) ;
|
tomwalters@0
|
370
|
tomwalters@0
|
371 if ( normalize == 0 )
|
tomwalters@0
|
372 f = writebuf( buf, Newframewidth, scale ) ;
|
tomwalters@0
|
373 else
|
tomwalters@0
|
374 f = writebuf( buf, Newframewidth, scale/buf[0] ) ;
|
tomwalters@0
|
375
|
tomwalters@0
|
376 if ( f < newscale )
|
tomwalters@0
|
377 newscale = f ;
|
tomwalters@0
|
378 }
|
tomwalters@0
|
379
|
tomwalters@0
|
380 return ( newscale ) ;
|
tomwalters@0
|
381 }
|
tomwalters@0
|
382
|
tomwalters@0
|
383
|
tomwalters@0
|
384 /********************** Write o/p ****************************************/
|
tomwalters@0
|
385
|
tomwalters@0
|
386 float writebuf( buf, n, scale ) /* write buffer as scaled shorts */
|
tomwalters@0
|
387 float *buf ;
|
tomwalters@0
|
388 int n ;
|
tomwalters@0
|
389 float scale ;
|
tomwalters@0
|
390 {
|
tomwalters@0
|
391 register int i ;
|
tomwalters@0
|
392 short p ;
|
tomwalters@0
|
393 float newscale ;
|
tomwalters@0
|
394
|
tomwalters@0
|
395 if ( !negative ) { /* usual acf (ie. positive half, with zeroth lag on left) */
|
tomwalters@0
|
396 for (i=0 ; i < n ; i++) {
|
tomwalters@0
|
397
|
tomwalters@0
|
398 newscale = check_overflow( buf[i], scale, 1 ) ;
|
tomwalters@0
|
399
|
tomwalters@0
|
400 p = (short)( buf[i] * scale ) ;
|
tomwalters@0
|
401 fwrite( &p, sizeof(short), 1, stdout ) ;
|
tomwalters@0
|
402 }
|
tomwalters@0
|
403 }
|
tomwalters@0
|
404
|
tomwalters@0
|
405 else { /* write negative half of acf (zeroth lag on right) */
|
tomwalters@0
|
406 for ( i = n-1 ; i >= 0 ; --i ) {
|
tomwalters@0
|
407
|
tomwalters@0
|
408 newscale = check_overflow( buf[i], scale, 1 ) ;
|
tomwalters@0
|
409
|
tomwalters@0
|
410 p = (short)( buf[i] * scale ) ;
|
tomwalters@0
|
411 fwrite( &p, sizeof(short), 1, stdout ) ;
|
tomwalters@0
|
412 }
|
tomwalters@0
|
413 }
|
tomwalters@0
|
414 return ( newscale ) ;
|
tomwalters@0
|
415 }
|
tomwalters@0
|
416
|
tomwalters@0
|
417
|
tomwalters@0
|
418
|
tomwalters@0
|
419 /************************ Output header ************************************/
|
tomwalters@0
|
420 /*
|
tomwalters@0
|
421 First create a new header with
|
tomwalters@0
|
422 nwidth_aid
|
tomwalters@0
|
423 pwidth_aid
|
tomwalters@0
|
424 frstep_aid
|
tomwalters@0
|
425 Then copy the original nap header into the sai header, changing in order:
|
tomwalters@0
|
426 frames
|
tomwalters@0
|
427 frameshift
|
tomwalters@0
|
428 framewidth
|
tomwalters@0
|
429 frameheight
|
tomwalters@0
|
430 framebytes
|
tomwalters@0
|
431 animate
|
tomwalters@0
|
432 display
|
tomwalters@0
|
433 Then change applic name [gennap] to [gensai] in the Version string.
|
tomwalters@0
|
434 Finally, update the new header_bytes, and return the new header.
|
tomwalters@0
|
435 */
|
tomwalters@0
|
436
|
tomwalters@0
|
437 char *SaiHeader( napheader )
|
tomwalters@0
|
438 char *napheader ;
|
tomwalters@0
|
439 {
|
tomwalters@0
|
440 char *saiheader;
|
tomwalters@0
|
441 char *p0, *p1, *p2, *s, str[64];
|
tomwalters@0
|
442
|
tomwalters@0
|
443 saiheader = (char *)malloc( strlen(napheader) + 128 ) ;
|
tomwalters@0
|
444
|
tomwalters@0
|
445 p0 = saiheader ;
|
tomwalters@0
|
446 p1 = napheader ;
|
tomwalters@0
|
447
|
tomwalters@0
|
448
|
tomwalters@0
|
449 /** copy initial header bytes **/
|
tomwalters@0
|
450
|
tomwalters@0
|
451 p2 = HeaderString( napheader , "header_bytes" ) ;
|
tomwalters@0
|
452 while( p1 < p2 )
|
tomwalters@0
|
453 *p0++ = *p1++ ;
|
tomwalters@0
|
454 while (*p1 != '\n')
|
tomwalters@0
|
455 *p0++ = *p1++ ;
|
tomwalters@0
|
456 *p0++ = *p1++ ;
|
tomwalters@0
|
457
|
tomwalters@0
|
458
|
tomwalters@0
|
459 /** insert nwidth_aid at top of new header **/
|
tomwalters@0
|
460
|
tomwalters@0
|
461 sprintf(str,"nwidth_aid=0\n");
|
tomwalters@0
|
462 for (s = str ; *s != '\n' ; )
|
tomwalters@0
|
463 *p0++ = *s++;
|
tomwalters@0
|
464 *p0++ = *s;
|
tomwalters@0
|
465
|
tomwalters@0
|
466
|
tomwalters@0
|
467 /** insert pwidth_aid into new header **/
|
tomwalters@0
|
468
|
tomwalters@0
|
469 sprintf(str,"pwidth_aid=%dms\n", (int)(1000*((float)Newframewidth/samplerate)) );
|
tomwalters@0
|
470 for (s = str ; *s != '\n' ; )
|
tomwalters@0
|
471 *p0++ = *s++;
|
tomwalters@0
|
472 *p0++ = *s;
|
tomwalters@0
|
473
|
tomwalters@0
|
474
|
tomwalters@0
|
475 /** insert frstep_aid into new header **/
|
tomwalters@0
|
476
|
tomwalters@0
|
477 sprintf(str,"frstep_aid=%dms\n", (int)(1000*((float)frameshift/samplerate)) );
|
tomwalters@0
|
478 for (s = str ; *s != '\n' ; )
|
tomwalters@0
|
479 *p0++ = *s++;
|
tomwalters@0
|
480 *p0++ = *s;
|
tomwalters@0
|
481
|
tomwalters@0
|
482
|
tomwalters@0
|
483 /** copy up to frames **/
|
tomwalters@0
|
484
|
tomwalters@0
|
485 p2 = HeaderString( napheader , "frames" ) ;
|
tomwalters@0
|
486 while( p1 < p2 )
|
tomwalters@0
|
487 *p0++ = *p1++ ;
|
tomwalters@0
|
488
|
tomwalters@0
|
489 sprintf(str,"%d\n", Newframes);
|
tomwalters@0
|
490 for (s = str ; *s != '\n' ; )
|
tomwalters@0
|
491 *p0++ = *s++;
|
tomwalters@0
|
492 *p0++ = *s;
|
tomwalters@0
|
493 while (*p1 != '\n')
|
tomwalters@0
|
494 *p1++;
|
tomwalters@0
|
495 *p1++;
|
tomwalters@0
|
496
|
tomwalters@0
|
497
|
tomwalters@0
|
498 /** copy up to frameshift **/
|
tomwalters@0
|
499
|
tomwalters@0
|
500 p2 = HeaderString( napheader , "frameshift" ) ;
|
tomwalters@0
|
501 while ( p1 < p2 )
|
tomwalters@0
|
502 *p0++ = *p1++ ;
|
tomwalters@0
|
503
|
tomwalters@0
|
504 sprintf(str,"%d\n", Newframeshift);
|
tomwalters@0
|
505 for (s = str ; *s != '\n' ; )
|
tomwalters@0
|
506 *p0++ = *s++;
|
tomwalters@0
|
507 *p0++ = *s;
|
tomwalters@0
|
508 while (*p1 != '\n')
|
tomwalters@0
|
509 *p1++;
|
tomwalters@0
|
510 *p1++;
|
tomwalters@0
|
511
|
tomwalters@0
|
512
|
tomwalters@0
|
513 /** copy up to framewidth **/
|
tomwalters@0
|
514
|
tomwalters@0
|
515 p2 = HeaderString( napheader , "framewidth" ) ;
|
tomwalters@0
|
516 while ( p1 < p2 )
|
tomwalters@0
|
517 *p0++ = *p1++ ;
|
tomwalters@0
|
518
|
tomwalters@0
|
519 sprintf(str,"%d\n", Newframewidth);
|
tomwalters@0
|
520 for (s = str ; *s != '\n' ; )
|
tomwalters@0
|
521 *p0++ = *s++;
|
tomwalters@0
|
522 *p0++ = *s;
|
tomwalters@0
|
523 while (*p1 != '\n')
|
tomwalters@0
|
524 *p1++;
|
tomwalters@0
|
525 *p1++;
|
tomwalters@0
|
526
|
tomwalters@0
|
527
|
tomwalters@0
|
528 /** copy up to frameheight **/
|
tomwalters@0
|
529
|
tomwalters@0
|
530 p2 = HeaderString( napheader , "frameheight" ) ;
|
tomwalters@0
|
531 while ( p1 < p2 )
|
tomwalters@0
|
532 *p0++ = *p1++ ;
|
tomwalters@0
|
533
|
tomwalters@0
|
534 sprintf(str,"%d\n", Newframeheight);
|
tomwalters@0
|
535 for (s = str ; *s != '\n' ; )
|
tomwalters@0
|
536 *p0++ = *s++;
|
tomwalters@0
|
537 *p0++ = *s;
|
tomwalters@0
|
538 while (*p1 != '\n')
|
tomwalters@0
|
539 *p1++;
|
tomwalters@0
|
540 *p1++;
|
tomwalters@0
|
541
|
tomwalters@0
|
542
|
tomwalters@0
|
543 /** copy up to framebytes **/
|
tomwalters@0
|
544
|
tomwalters@0
|
545 p2 = HeaderString( napheader , "framebytes" ) ;
|
tomwalters@0
|
546 while ( p1 < p2 )
|
tomwalters@0
|
547 *p0++ = *p1++ ;
|
tomwalters@0
|
548
|
tomwalters@0
|
549 sprintf(str,"%d\n", Newframebytes);
|
tomwalters@0
|
550 for (s = str ; *s != '\n' ; )
|
tomwalters@0
|
551 *p0++ = *s++;
|
tomwalters@0
|
552 *p0++ = *s;
|
tomwalters@0
|
553 while (*p1 != '\n')
|
tomwalters@0
|
554 *p1++;
|
tomwalters@0
|
555 *p1++;
|
tomwalters@0
|
556
|
tomwalters@0
|
557
|
tomwalters@0
|
558 /** copy up to animate_ctn **/
|
tomwalters@0
|
559
|
tomwalters@0
|
560 p2 = HeaderString( napheader , "animate_ctn" ) ;
|
tomwalters@0
|
561 while ( p1 < p2 )
|
tomwalters@0
|
562 *p0++ = *p1++ ;
|
tomwalters@0
|
563
|
tomwalters@0
|
564 sprintf(str,"%s\n", anistr );
|
tomwalters@0
|
565 for (s = str ; *s != '\n' ; )
|
tomwalters@0
|
566 *p0++ = *s++;
|
tomwalters@0
|
567 *p0++ = *s;
|
tomwalters@0
|
568 while (*p1 != '\n')
|
tomwalters@0
|
569 *p1++;
|
tomwalters@0
|
570 *p1++;
|
tomwalters@0
|
571
|
tomwalters@0
|
572
|
tomwalters@0
|
573 /** copy up to display **/
|
tomwalters@0
|
574
|
tomwalters@0
|
575 p2 = HeaderString( napheader , "display" ) ;
|
tomwalters@0
|
576 while ( p1 < p2 )
|
tomwalters@0
|
577 *p0++ = *p1++ ;
|
tomwalters@0
|
578
|
tomwalters@0
|
579 sprintf(str,"%s\n", dispstr );
|
tomwalters@0
|
580 for (s = str ; *s != '\n' ; )
|
tomwalters@0
|
581 *p0++ = *s++;
|
tomwalters@0
|
582 *p0++ = *s;
|
tomwalters@0
|
583 while (*p1 != '\n')
|
tomwalters@0
|
584 *p1++;
|
tomwalters@0
|
585 *p1++;
|
tomwalters@0
|
586
|
tomwalters@0
|
587
|
tomwalters@0
|
588 /** copy rest of header **/
|
tomwalters@0
|
589
|
tomwalters@0
|
590 p2 = HeaderString( napheader , "Version" ) ;
|
tomwalters@0
|
591 while ( p1 < p2 )
|
tomwalters@0
|
592 *p0++ = *p1++ ;
|
tomwalters@0
|
593
|
tomwalters@0
|
594 while (*p1 != ']') /* change applic name [gennap] to [gensai] */
|
tomwalters@0
|
595 *p0++ = *p1++ ;
|
tomwalters@0
|
596 *(p0-3) = 's' ;
|
tomwalters@0
|
597 *(p0-2) = 'a' ;
|
tomwalters@0
|
598 *(p0-1) = 'i' ;
|
tomwalters@0
|
599 while (*p1 != '\n')
|
tomwalters@0
|
600 *p0++ = *p1++ ;
|
tomwalters@0
|
601 *p0++ = *p1++ ;
|
tomwalters@0
|
602
|
tomwalters@0
|
603
|
tomwalters@0
|
604 /** update header_bytes **/
|
tomwalters@0
|
605
|
tomwalters@0
|
606 sprintf(str, "%0*d", 7, p0-saiheader);
|
tomwalters@0
|
607 p0 = HeaderString( saiheader , "header_bytes" ) ;
|
tomwalters@0
|
608 s = str;
|
tomwalters@0
|
609 while(*p0 != '\n')
|
tomwalters@0
|
610 *p0++ = *s++ ;
|
tomwalters@0
|
611
|
tomwalters@0
|
612
|
tomwalters@0
|
613 return saiheader;
|
tomwalters@0
|
614 }
|
tomwalters@0
|
615
|
tomwalters@0
|
616
|