tomwalters@0
|
1 /*
|
tomwalters@0
|
2 bufwave.c a shifting waveform buffer.
|
tomwalters@0
|
3 ---------
|
tomwalters@0
|
4
|
tomwalters@0
|
5 A buffer (or window) is shifted along the input, and the
|
tomwalters@0
|
6 contents of the buffer are written to the stdout on each shift.
|
tomwalters@0
|
7
|
tomwalters@0
|
8 Input is buffered in frames of size `width' samples, and the buffer is
|
tomwalters@0
|
9 shifted along the input in steps of `frstep' samples.
|
tomwalters@0
|
10 Both `width' and `frstep' may be given with time units (s or ms), in which
|
tomwalters@0
|
11 case the they are converted to a number of samples using the given
|
tomwalters@0
|
12 `samplerate' option.
|
tomwalters@0
|
13
|
tomwalters@0
|
14 The `type' option sets the size of a binary sample in bytes.
|
tomwalters@0
|
15 Standard type names are recognised (char, short, int, float, double).
|
tomwalters@0
|
16 For example, type=1 is synonymous with type=char, both specifying a
|
tomwalters@0
|
17 binary sample of 1 byte.
|
tomwalters@0
|
18
|
tomwalters@0
|
19 The special case of type=ASCII sets a sample to be a line of ASCII text
|
tomwalters@0
|
20 (delimited by a CR), of size up to a maximum number of characters set by
|
tomwalters@0
|
21 the `length' option.
|
tomwalters@0
|
22
|
tomwalters@0
|
23 The `frame' option selects a sequence of contiguous frames for output by:
|
tomwalters@0
|
24 frame=a[-b]
|
tomwalters@0
|
25 where `a' and `b' are frame numbers: 1,2,3,...
|
tomwalters@0
|
26 The upper limit `b' is optional, and when it is missing then the frame
|
tomwalters@0
|
27 sequence is a single frame, otherwise `a' and `b' are inclusive limits.
|
tomwalters@0
|
28 The strings "min" and "max" are recognised as extreme limits.
|
tomwalters@0
|
29
|
tomwalters@0
|
30 The `start' option is an offset to the start of the first frame in samples.
|
tomwalters@0
|
31 If given with time units, the start is converted to samples using the
|
tomwalters@0
|
32 given `samplerate' option.
|
tomwalters@0
|
33
|
tomwalters@0
|
34 The `reverse' option causes each buffer to be written out in reverse order
|
tomwalters@0
|
35 of its samples.
|
tomwalters@0
|
36
|
tomwalters@0
|
37 For example, if a file foo contains a sequence of frames, each 75 samples
|
tomwalters@0
|
38 long, then to reverse the contents of each frame do:
|
tomwalters@0
|
39
|
tomwalters@0
|
40 bufwave rev=on width=75 frstep=75 foo
|
tomwalters@0
|
41
|
tomwalters@0
|
42 */
|
tomwalters@0
|
43
|
tomwalters@0
|
44 #include <stdio.h>
|
tomwalters@0
|
45 #include <math.h>
|
tomwalters@0
|
46 #include "options.h"
|
tomwalters@0
|
47 #include "units.h"
|
tomwalters@0
|
48 #include "strmatch.h"
|
tomwalters@0
|
49
|
tomwalters@0
|
50 char applic[] = "shifting waveform buffer." ;
|
tomwalters@0
|
51
|
tomwalters@0
|
52 static char *helpstr, *debugstr, *fstr, *bstr, *nstr, *ostr, *sstr, *sampstr, *rstr, *lenstr ;
|
tomwalters@0
|
53
|
tomwalters@0
|
54 static Options option[] = {
|
tomwalters@0
|
55 { "help" , "off" , &helpstr , "help" , DEBUG },
|
tomwalters@0
|
56 { "debug" , "off" , &debugstr , "debugging switch" , DEBUG },
|
tomwalters@0
|
57 { "samplerate", "20kHz" , &sampstr , "samplerate " , VAL },
|
tomwalters@0
|
58 { "frame" , "1-max" , &fstr , "select frames inclusively" , VAL },
|
tomwalters@0
|
59 { "width" , "10ms" , &nstr , "frame width" , VAL },
|
tomwalters@0
|
60 { "frstep" , "0" , &ostr , "frame step (ie. shift)" , VAL },
|
tomwalters@0
|
61 { "start" , "0" , &sstr , "offset to start first frame" , VAL },
|
tomwalters@0
|
62 { "type" , "short" , &bstr , "data type or size in bytes" , VAL },
|
tomwalters@0
|
63 { "reverse" , "off" , &rstr , "write each frame in reverse" , SETFLAG },
|
tomwalters@0
|
64 { "length" , "256" , &lenstr , "max line length in chars" , SVAL },
|
tomwalters@0
|
65 ( char * ) 0 } ;
|
tomwalters@0
|
66
|
tomwalters@0
|
67
|
tomwalters@0
|
68 int samplerate ;
|
tomwalters@0
|
69 int width ;
|
tomwalters@0
|
70 int frstep ;
|
tomwalters@0
|
71 int overlap ;
|
tomwalters@0
|
72 int start ;
|
tomwalters@0
|
73 int reverse ;
|
tomwalters@0
|
74
|
tomwalters@0
|
75 main (argc, argv)
|
tomwalters@0
|
76 int argc;
|
tomwalters@0
|
77 char **argv;
|
tomwalters@0
|
78 {
|
tomwalters@0
|
79 FILE *fp ;
|
tomwalters@0
|
80 char *buf, **linebuf ;
|
tomwalters@0
|
81 int m, bytes ;
|
tomwalters@0
|
82 int a, b, f, i, j, k0, k1 ;
|
tomwalters@0
|
83 int helpdatatype() ;
|
tomwalters@0
|
84
|
tomwalters@0
|
85 fp = openopts( option,argc,argv ) ;
|
tomwalters@0
|
86 if ( !isoff( helpstr ) )
|
tomwalters@0
|
87 helpopts1( helpstr, argv[0], applic, option, helpdatatype ) ;
|
tomwalters@0
|
88
|
tomwalters@0
|
89 samplerate = to_Hz( sampstr ) ;
|
tomwalters@0
|
90 width = to_p( nstr, samplerate ) ;
|
tomwalters@0
|
91 frstep = to_p( ostr, samplerate ) ;
|
tomwalters@0
|
92 start = to_p( sstr, samplerate ) ;
|
tomwalters@0
|
93 reverse = ison( rstr ) ;
|
tomwalters@0
|
94 overlap = width - frstep ;
|
tomwalters@0
|
95
|
tomwalters@0
|
96 if ( ( bytes = databytes( bstr ) ) < 0 ) {
|
tomwalters@0
|
97 fprintf( stderr, "bufwave: bad type [%s]\n", bstr ) ;
|
tomwalters@0
|
98 exit( 1 ) ;
|
tomwalters@0
|
99 }
|
tomwalters@0
|
100
|
tomwalters@0
|
101 if ( selector( fstr, &a, &b ) == 0 ) {
|
tomwalters@0
|
102 fprintf(stderr,"bufwave: bad frame selector [%s]\n", fstr ) ;
|
tomwalters@0
|
103 exit( 1 ) ;
|
tomwalters@0
|
104 }
|
tomwalters@0
|
105
|
tomwalters@0
|
106 if ( ison( debugstr ) ) {
|
tomwalters@0
|
107 printf("width=%d frstep=%d start=%d bytes=%d samplerate=%d reverse=%d a=%d b=%d \n",
|
tomwalters@0
|
108 width, frstep, start, bytes, samplerate, reverse, a, b );
|
tomwalters@0
|
109 exit(0);
|
tomwalters@0
|
110 }
|
tomwalters@0
|
111
|
tomwalters@0
|
112
|
tomwalters@0
|
113 if (bytes > 0) { /* binary objects of size `bytes' */
|
tomwalters@0
|
114
|
tomwalters@0
|
115 /* Allocate space for frame buffer */
|
tomwalters@0
|
116 if ( ( buf = (char *)malloc( width*bytes ) ) == (char *)0 ) {
|
tomwalters@0
|
117 fprintf( stderr, "bufwave: cannot allocate %d * %d bytes\n", width, bytes ) ;
|
tomwalters@0
|
118 exit( 1 ) ;
|
tomwalters@0
|
119 }
|
tomwalters@0
|
120
|
tomwalters@0
|
121 /* Seek to start, past start*bytes and a-1 frame shifts of frstep*bytes */
|
tomwalters@0
|
122
|
tomwalters@0
|
123 if ( start>0 && seekstart( start, bytes, fp ) < start ) {
|
tomwalters@0
|
124 fprintf(stderr,"bufwave: seek overshot end-of-file\n");
|
tomwalters@0
|
125 exit(1);
|
tomwalters@0
|
126 }
|
tomwalters@0
|
127 for (f=1 ; f<a && fread(buf,bytes,frstep,fp) ; f++)
|
tomwalters@0
|
128 ;
|
tomwalters@0
|
129
|
tomwalters@0
|
130 /* Buffer b-a+1 frames (or the remainder if b==0) */
|
tomwalters@0
|
131 m = fread(buf, bytes, width, fp); /* m enables oversizing single frames for direct reversing */
|
tomwalters@0
|
132 if ( reverse )
|
tomwalters@0
|
133 for (k0=m-1 ; k0>=0 && fwrite(&buf[(k0)*bytes], bytes, 1, stdout) ; --k0)
|
tomwalters@0
|
134 ;
|
tomwalters@0
|
135 else
|
tomwalters@0
|
136 fwrite(buf, bytes, m, stdout);
|
tomwalters@0
|
137
|
tomwalters@0
|
138 k0 = k1 = 0;
|
tomwalters@0
|
139 for (i=width, f++ ; k0 == k1 && (f<=b || b==0) ; i+=width, f++) {
|
tomwalters@0
|
140 for (k0=i, k1=i+frstep ; k0<k1 && fread(&buf[(k0%width)*bytes], bytes, 1, fp) ; k0++)
|
tomwalters@0
|
141 ;
|
tomwalters@0
|
142 i -= overlap ;
|
tomwalters@0
|
143 if (k0 == k1) {
|
tomwalters@0
|
144 if ( reverse ) /* write out in reverse */
|
tomwalters@0
|
145 for (k0=i+width-1, k1=i-1 ; k0>k1 && fwrite(&buf[(k0%width)*bytes], bytes, 1, stdout) ; --k0)
|
tomwalters@0
|
146 ;
|
tomwalters@0
|
147 else /* write out correct order */
|
tomwalters@0
|
148 for (k0=i, k1=i+width ; k0<k1 && fwrite(&buf[(k0%width)*bytes], bytes, 1, stdout) ; k0++)
|
tomwalters@0
|
149 ;
|
tomwalters@0
|
150 }
|
tomwalters@0
|
151 }
|
tomwalters@0
|
152 }
|
tomwalters@0
|
153
|
tomwalters@0
|
154 else { /* ASCII objects of size lines up to lenstr chars */
|
tomwalters@0
|
155
|
tomwalters@0
|
156 /* Allocate space for `width' lines */
|
tomwalters@0
|
157 bytes = atoi( lenstr ) ;
|
tomwalters@0
|
158 if ( ( linebuf = (char **)malloc( width * sizeof( char * ) ) ) == (char **)0 ) {
|
tomwalters@0
|
159 fprintf( stderr, "bufwave: cannot allocate %d * sizeof( char * )\n", width ) ;
|
tomwalters@0
|
160 exit( 1 ) ;
|
tomwalters@0
|
161 }
|
tomwalters@0
|
162 for ( i = 0 ; i < width ; i++)
|
tomwalters@0
|
163 if ( ( linebuf[i] = (char *)malloc( bytes ) ) == (char *)0 ) {
|
tomwalters@0
|
164 fprintf( stderr, "bufwave: cannot allocate %d bytes %d times\n", bytes, i+1 ) ;
|
tomwalters@0
|
165 exit( 1 ) ;
|
tomwalters@0
|
166 }
|
tomwalters@0
|
167
|
tomwalters@0
|
168 /* Seek to start, past start*bytes and frstep*a-1 lines */
|
tomwalters@0
|
169 for (i=0 ; i<start && fgets( *linebuf, bytes, fp ) ; i++)
|
tomwalters@0
|
170 ;
|
tomwalters@0
|
171 if (i<start) {
|
tomwalters@0
|
172 fprintf(stderr,"bufwave: seek overshot end-of-file\n");
|
tomwalters@0
|
173 exit(1);
|
tomwalters@0
|
174 }
|
tomwalters@0
|
175 m = frstep * ( a-1 ) ;
|
tomwalters@0
|
176 for (i=0 ; i<m && fgets( *linebuf, bytes, fp ) ; i++)
|
tomwalters@0
|
177 ;
|
tomwalters@0
|
178 if ( m > 0 ) f = m/frstep + 1 ;
|
tomwalters@0
|
179 else f = 1 ;
|
tomwalters@0
|
180
|
tomwalters@0
|
181 /* Buffer b-a+1 lines (or the remainder if b==0) */
|
tomwalters@0
|
182 /* (m enables oversizing single frames for direct reversing) */
|
tomwalters@0
|
183 for ( m = 0 ; m < width && fgets( linebuf[m], bytes, fp ) ; m++ )
|
tomwalters@0
|
184 ;
|
tomwalters@0
|
185 if ( reverse )
|
tomwalters@0
|
186 for (k0=m-1 ; k0>=0 ; --k0)
|
tomwalters@0
|
187 fputs( linebuf[k0], stdout ) ;
|
tomwalters@0
|
188 else
|
tomwalters@0
|
189 for (k0=0 ; k0<m ; k0++)
|
tomwalters@0
|
190 fputs( linebuf[k0], stdout ) ;
|
tomwalters@0
|
191
|
tomwalters@0
|
192 k0 = k1 = 0;
|
tomwalters@0
|
193 for (i=width, f++ ; k0 == k1 && (f<=b || b==0) ; i+=width, f++) {
|
tomwalters@0
|
194 for (k0=i, k1=i+frstep ; k0<k1 && fgets( linebuf[k0%width], bytes, fp ) ; k0++)
|
tomwalters@0
|
195 ;
|
tomwalters@0
|
196 i -= overlap ;
|
tomwalters@0
|
197 if (k0 == k1) {
|
tomwalters@0
|
198 if ( reverse ) /* write out in reverse */
|
tomwalters@0
|
199 for (k0=i+width-1, k1=i-1 ; k0>k1 ; --k0)
|
tomwalters@0
|
200 fputs( linebuf[k0%width], stdout ) ;
|
tomwalters@0
|
201 else /* write out correct order */
|
tomwalters@0
|
202 for (k0=i, k1=i+width ; k0<k1 ; k0++)
|
tomwalters@0
|
203 fputs( linebuf[k0%width], stdout) ;
|
tomwalters@0
|
204 }
|
tomwalters@0
|
205 }
|
tomwalters@0
|
206 }
|
tomwalters@0
|
207
|
tomwalters@0
|
208 }
|
tomwalters@0
|
209
|
tomwalters@0
|
210
|
tomwalters@0
|
211 helpdatatype()
|
tomwalters@0
|
212 {
|
tomwalters@0
|
213 fprintf(stderr,"\ndata types: \n");
|
tomwalters@0
|
214 fprintf(stderr," char \n");
|
tomwalters@0
|
215 fprintf(stderr," short \n");
|
tomwalters@0
|
216 fprintf(stderr," int \n");
|
tomwalters@0
|
217 fprintf(stderr," float \n");
|
tomwalters@0
|
218 fprintf(stderr," double \n");
|
tomwalters@0
|
219 fprintf(stderr," <number> (sizeof binary object in bytes) \n" ) ;
|
tomwalters@0
|
220 fprintf(stderr," ASCII (lines of up to %d characters) \n", atoi( lenstr ) ) ;
|
tomwalters@0
|
221 exit( 1 ) ;
|
tomwalters@0
|
222 }
|