5 * Copyright (C) 2004-2012 Monty
7 * This analyzer is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2, or (at your option)
12 * The analyzer is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Postfish; see the file COPYING. If not, write to the
19 * Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
27 #include <fenv.h> // Thank you C99!
34 char *inputname
[MAX_FILES
];
39 void handler(int sig
){
43 "\nTrapped signal %d; exiting!\n"
44 "This signal almost certainly indicates a bug in the analyzer;\n"
45 "If this version of the analyzer is newer than a few months old,\n"
46 "please email a detailed report of the crash along with\n"
47 "processor type, OS version, and as much information as possible\n"
48 "about what caused the crash. The best possible report will\n"
49 "outline the exact steps needed to reproduce the error, ensuring\n"
50 "that I can fix the bug as quickly as possible.\n\n"
51 "-- monty@xiph.org, spectrum revision %s\n\n",sig
,version
);
57 const char *optstring
= "-r:c:EeBlb:suhT";
59 struct option options
[] = {
60 {"bold",no_argument
,NULL
,'T'},
61 {"rate",required_argument
,NULL
,'r'},
62 {"channels",required_argument
,NULL
,'c'},
63 {"big-endian",no_argument
,NULL
,'E'},
64 {"little-endian",no_argument
,NULL
,'e'},
65 {"bits",required_argument
,NULL
,'b'},
66 {"signed",no_argument
,NULL
,'s'},
67 {"unsigned",no_argument
,NULL
,'u'},
68 {"help",no_argument
,NULL
,'h'},
73 static void usage(FILE *f
){
75 "\ngtk2 waveform viewer, revision %s\n\n"
78 " waveform [options] [file]\n\n"
81 " -b --bits <bits> : Force input to be read as 8, 16, 24 or 32 bit\n"
82 " PCM. Default bit depth is normally read from\n"
83 " the file/stream header or set to 16 bits\n"
85 " -B -E --big-endian : Force input to be read as big endian.\n"
86 " Default endianness is normally read from the\n"
87 " file/stream header or set to host"
88 " endianness for raw input.\n"
89 " -c --channels <channels> : Input channel number override; use to\n"
90 " specify the number of channels in a raw\n"
91 " input. default: 1\n"
92 " -e -l --little-endian : Force input to be read as little endian.\n"
93 " Default endianness is normally read from the\n"
94 " file/stream header or set to host"
95 " endianness for raw input.\n"
96 " -h --help : print this help\n"
97 " -r --rate <Hz> : Input sample rate override in Hz; use to\n"
98 " specify the rate of a raw input.\n"
100 " -s --signed : Force input to be read as signed PCM.\n"
101 " Signedness is normally read from the \n"
102 " file/stream header or set to signed for raw\n"
104 " -T --bold : plot spectrum with thicker/bolder lines.\n"
105 " -u --unsigned : Force input to be read as unsigned PCM.\n"
106 " Signedness is normally read from the \n"
107 " file/stream header or set to signed for raw\n"
112 " Waveform takes raw, WAV or AIFF input either from stdin or from \n"
113 " file[s]/stream[s] specified on the command line.\n\n",version
);
117 void parse_command_line(int argc
, char **argv
){
118 int c
,long_option_index
;
120 while((c
=getopt_long(argc
,argv
,optstring
,options
,&long_option_index
))!=EOF
){
123 /* file name that belongs to current group */
124 if(inputs
>=MAX_FILES
){
125 fprintf(stderr
,"Maximum of MAX_FILES input files exceeded. Oops. Programmer was lazy.\n\n");
128 inputname
[inputs
++]=strdup(optarg
);
134 /* force bit width */
138 bits_force
[inputs
]=1;
139 if(a
!=8 && a
!=16 && a
!=24 && a
!=32){
146 /* force big endian */
148 bigendian_force
[inputs
]=1;
155 channels_force
[inputs
]=1;
163 /* force little endian */
165 bigendian_force
[inputs
]=1;
175 rate_force
[inputs
]=1;
176 if(a
<4000 || a
>200000){
185 signed_force
[inputs
]=1;
190 signed_force
[inputs
]=1;
200 void sigill_handler(int sig
){
202 if(sig
==SIGILL
)sigill
=1;
205 int main(int argc
, char **argv
){
208 version
=strstr(VERSION
,"version.h");
210 char *versionend
=strchr(version
,' ');
211 if(versionend
)versionend
=strchr(versionend
+1,' ');
212 if(versionend
)versionend
=strchr(versionend
+1,' ');
213 if(versionend
)versionend
=strchr(versionend
+1,' ');
215 int len
=versionend
-version
-9;
216 version
=strdup(version
+10);
223 /* parse command line and open all the input files */
224 parse_command_line(argc
, argv
);
226 /* We do not care about FPEs; rather, underflow is nominal case, and
227 its better to ignore other traps in production than to crash the
228 app. Please inform the FPU of this. */
231 fedisableexcept(FE_INVALID
);
232 fedisableexcept(FE_INEXACT
);
233 fedisableexcept(FE_UNDERFLOW
);
234 fedisableexcept(FE_OVERFLOW
);
236 feenableexcept(FE_INVALID
);
237 feenableexcept(FE_INEXACT
);
238 feenableexcept(FE_UNDERFLOW
);
239 feenableexcept(FE_OVERFLOW
);
242 /* Linux Altivec support has a very annoying problem; by default,
243 math on denormalized floats will simply crash the program. FFTW3
244 uses Altivec, so boom, but only random booms.
246 By the C99 spec, the above exception configuration is also
247 supposed to handle Altivec config, but doesn't. So we use the
248 below ugliness to both handle altivec and non-alitvec PPC. */
252 signal(SIGILL
,sigill_handler
);
254 #if (defined __GNUC__) && (__GNUC__ == 3) && ! (defined __APPLE_CC__)
255 __vector
unsigned short noTrap
=
256 (__vector
unsigned short){0,0,0,0,0,0,0x1,0};
258 vector
unsigned short noTrap
=
259 (vector
unsigned short)(0,0,0,0,0,0,0x1,0);
265 /* easiest way to inform gtk of changes and not deal with locking
266 issues around the UI */
268 fprintf(stderr
,"Unable to open event pipe:\n"
269 " %s\n",strerror(errno
));
274 /* Allows event compression on the read side */
275 if(fcntl(eventpipe
[0], F_SETFL
, O_NONBLOCK
)){
276 fprintf(stderr
,"Unable to set O_NONBLOCK on event pipe:\n"
277 " %s\n",strerror(errno
));
282 //signal(SIGINT,handler);
283 signal(SIGSEGV
,handler
);
285 if(input_load())exit(1);
287 /* set block size equal to maximum input rate + epsilon*/
288 /* (maximum display width: 1s, maximum update interval 1s) */
290 for(fi
=0;fi
<inputs
;fi
++)
291 if(rate
[fi
]>blocksize
)blocksize
=rate
[fi
]+16;
293 /* begin with a display width of 1s */
294 /* begin with an update interval (blockslice) of 100ms */
295 blockslice_frac
= 10;