tomwalters@0
|
1 /*
|
tomwalters@0
|
2 conv.c Convolution. [NR: 407-413].
|
tomwalters@0
|
3 ------
|
tomwalters@0
|
4
|
tomwalters@0
|
5 Usage: conv [options] signal_file response_file
|
tomwalters@0
|
6
|
tomwalters@0
|
7 The response of a linear filter to an arbitiary input signal is the
|
tomwalters@0
|
8 convolution of the signal with the filter's impulse response.
|
tomwalters@0
|
9 The `response_file' contains the impulse response which characterises the
|
tomwalters@0
|
10 filter, and the result of the convolution operation is the response of
|
tomwalters@0
|
11 that filter to the signal contained in the `signal_file'.
|
tomwalters@0
|
12
|
tomwalters@0
|
13 The program uses the FFT to transform both input files, and then obtains
|
tomwalters@0
|
14 the convolution by multiplying in the frequency domain, and inverse
|
tomwalters@0
|
15 transforming the result.
|
tomwalters@0
|
16
|
tomwalters@0
|
17 Eg:
|
tomwalters@0
|
18
|
tomwalters@0
|
19 ptrain > foo1 -signal
|
tomwalters@0
|
20 gauss -b5 | op type=float mult=500 > foo3 -response
|
tomwalters@0
|
21 conv factor=.0005 foo1 foo3 | x11plot
|
tomwalters@0
|
22
|
tomwalters@0
|
23 Deconv doesn't seem to work !
|
tomwalters@0
|
24 */
|
tomwalters@0
|
25
|
tomwalters@0
|
26
|
tomwalters@0
|
27 #include <stdio.h>
|
tomwalters@0
|
28 #include <math.h>
|
tomwalters@0
|
29 #include <sys/types.h>
|
tomwalters@0
|
30 #include <sys/dir.h>
|
tomwalters@0
|
31 #include <sys/stat.h>
|
tomwalters@0
|
32 #include "options.h"
|
tomwalters@0
|
33 #include "units.h"
|
tomwalters@0
|
34 #include "strmatch.h"
|
tomwalters@0
|
35 #include "sigproc.h"
|
tomwalters@0
|
36
|
tomwalters@0
|
37 char applic[] = "Convolution. \n i/p and o/p signal in binary shorts, impulse response file in floats." ;
|
tomwalters@0
|
38 char usage[] = "conv [options] signal_file response_file" ;
|
tomwalters@0
|
39
|
tomwalters@0
|
40 static char *helpstr, *debugstr, *sampstr, *lenstr, *domstr, *scalestr ;
|
tomwalters@0
|
41
|
tomwalters@0
|
42 static Options option[] = {
|
tomwalters@0
|
43 { "help" , "off" , &helpstr , "help" , DEBUG },
|
tomwalters@0
|
44 { "debug" , "off" , &debugstr , "debugging switch" , DEBUG },
|
tomwalters@0
|
45 { "samplerate", "20kHz" , &sampstr , "samplerate " , VAL },
|
tomwalters@0
|
46 { "length" , "max" , &lenstr , "Size of input." , VAL },
|
tomwalters@0
|
47 { "domain" , "time" , &domstr , "Convolve in time or frequency domain" , VAL },
|
tomwalters@0
|
48 { "scale" , "1.0" , &scalestr , "scale factor for output" , VAL },
|
tomwalters@0
|
49 ( char * ) 0 } ;
|
tomwalters@0
|
50
|
tomwalters@0
|
51
|
tomwalters@0
|
52 int samplerate ;
|
tomwalters@0
|
53 float scale ;
|
tomwalters@0
|
54
|
tomwalters@0
|
55 short *signal ;
|
tomwalters@0
|
56 float *response ;
|
tomwalters@0
|
57 float *out ;
|
tomwalters@0
|
58
|
tomwalters@0
|
59 main (argc, argv)
|
tomwalters@0
|
60 int argc;
|
tomwalters@0
|
61 char **argv;
|
tomwalters@0
|
62 {
|
tomwalters@0
|
63 FILE *fp1, *fp2 ;
|
tomwalters@0
|
64 struct stat stbuf ;
|
tomwalters@0
|
65 int i, n, m ;
|
tomwalters@0
|
66 float f ;
|
tomwalters@0
|
67
|
tomwalters@0
|
68 if ( getopts( option, argc, argv ) != 2 || !isoff( helpstr ) )
|
tomwalters@0
|
69 helpopts3( helpstr, argv[0], applic, usage, option ) ;
|
tomwalters@0
|
70
|
tomwalters@0
|
71 samplerate = to_Hz( sampstr ) ;
|
tomwalters@0
|
72 scale = atof( scalestr ) ;
|
tomwalters@0
|
73
|
tomwalters@0
|
74 if ( ( fp1 = fopen( argv[argc-2], "r" ) ) == (FILE *)0 ) {
|
tomwalters@0
|
75 fprintf( stderr,"%s: can't open %s\n", argv[0], argv[argc-2] ) ;
|
tomwalters@0
|
76 exit( 1 ) ;
|
tomwalters@0
|
77 }
|
tomwalters@0
|
78 stat( argv[argc-2], &stbuf ) ;
|
tomwalters@0
|
79 if ( ismax( lenstr ) )
|
tomwalters@0
|
80 n = stbuf.st_size / sizeof( short ) ; /* size of signal file */
|
tomwalters@0
|
81 else if ( ( n = to_p( lenstr, samplerate ) ) > stbuf.st_size / sizeof( short ) ) {
|
tomwalters@0
|
82 fprintf( stderr,"conv: insufficient signal\n");
|
tomwalters@0
|
83 exit( 1 ) ;
|
tomwalters@0
|
84 }
|
tomwalters@0
|
85
|
tomwalters@0
|
86
|
tomwalters@0
|
87 if ( ( fp2 = fopen( argv[argc-1], "r" ) ) == (FILE *)0 ) {
|
tomwalters@0
|
88 fprintf( stderr,"%s: can't open %s\n", argv[0], argv[argc-1] ) ;
|
tomwalters@0
|
89 exit( 1 ) ;
|
tomwalters@0
|
90 }
|
tomwalters@0
|
91 stat( argv[argc-1], &stbuf ) ;
|
tomwalters@0
|
92 m = stbuf.st_size / sizeof( float ) ; /* size of response file */
|
tomwalters@0
|
93
|
tomwalters@0
|
94 if ( m > n ) { /* size of response file must <= signal file */
|
tomwalters@0
|
95 fprintf( stderr,"conv: size of response file must be <= size of signal file\n" ) ;
|
tomwalters@0
|
96 exit( 1 ) ;
|
tomwalters@0
|
97 }
|
tomwalters@0
|
98
|
tomwalters@0
|
99 signal = (short *)malloc( n * sizeof(short) ) ;
|
tomwalters@0
|
100 response = (float *)malloc( m * sizeof(float) ) ;
|
tomwalters@0
|
101 out = (float *)malloc( n * sizeof(float) ) ;
|
tomwalters@0
|
102
|
tomwalters@0
|
103 fread( signal, sizeof(short), n, fp1 ) ;
|
tomwalters@0
|
104 fread( response, sizeof(float), m, fp2 ) ;
|
tomwalters@0
|
105 fclose( fp1 ) ; fclose( fp2 ) ;
|
tomwalters@0
|
106
|
tomwalters@0
|
107
|
tomwalters@0
|
108 if ( iststr( domstr, "time" ) )
|
tomwalters@0
|
109 convolve_time( signal, n, response, m, out ) ;
|
tomwalters@0
|
110
|
tomwalters@0
|
111 else if ( iststr( domstr, "frequency" ) )
|
tomwalters@0
|
112 convolve_freq( signal, n, response, m, out ) ;
|
tomwalters@0
|
113
|
tomwalters@0
|
114 else {
|
tomwalters@0
|
115 fprintf( stderr,"conv: unknown domain [%s]\n", domstr ) ;
|
tomwalters@0
|
116 exit( 1 ) ;
|
tomwalters@0
|
117 }
|
tomwalters@0
|
118
|
tomwalters@0
|
119
|
tomwalters@0
|
120 if ( ( f = ftos( out, signal, n, scale ) ) < 1. )
|
tomwalters@0
|
121 fprintf( stderr,"Warning: 16-bit overflow during convolution. Try scale factor < %f\n", f ) ;
|
tomwalters@0
|
122
|
tomwalters@0
|
123 fwrite( signal, sizeof(short), n, stdout ) ;
|
tomwalters@0
|
124
|
tomwalters@0
|
125 }
|
tomwalters@0
|
126
|
tomwalters@0
|
127
|
tomwalters@0
|
128
|