Mercurial > hg > aim92
diff tools/conv.c @ 0:5242703e91d3 tip
Initial checkin for AIM92 aimR8.2 (last updated May 1997).
author | tomwalters |
---|---|
date | Fri, 20 May 2011 15:19:45 +0100 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/conv.c Fri May 20 15:19:45 2011 +0100 @@ -0,0 +1,128 @@ +/* + conv.c Convolution. [NR: 407-413]. + ------ + + Usage: conv [options] signal_file response_file + + The response of a linear filter to an arbitiary input signal is the + convolution of the signal with the filter's impulse response. + The `response_file' contains the impulse response which characterises the + filter, and the result of the convolution operation is the response of + that filter to the signal contained in the `signal_file'. + + The program uses the FFT to transform both input files, and then obtains + the convolution by multiplying in the frequency domain, and inverse + transforming the result. + +Eg: + +ptrain > foo1 -signal +gauss -b5 | op type=float mult=500 > foo3 -response +conv factor=.0005 foo1 foo3 | x11plot + +Deconv doesn't seem to work ! +*/ + + +#include <stdio.h> +#include <math.h> +#include <sys/types.h> +#include <sys/dir.h> +#include <sys/stat.h> +#include "options.h" +#include "units.h" +#include "strmatch.h" +#include "sigproc.h" + +char applic[] = "Convolution. \n i/p and o/p signal in binary shorts, impulse response file in floats." ; +char usage[] = "conv [options] signal_file response_file" ; + +static char *helpstr, *debugstr, *sampstr, *lenstr, *domstr, *scalestr ; + +static Options option[] = { + { "help" , "off" , &helpstr , "help" , DEBUG }, + { "debug" , "off" , &debugstr , "debugging switch" , DEBUG }, + { "samplerate", "20kHz" , &sampstr , "samplerate " , VAL }, + { "length" , "max" , &lenstr , "Size of input." , VAL }, + { "domain" , "time" , &domstr , "Convolve in time or frequency domain" , VAL }, + { "scale" , "1.0" , &scalestr , "scale factor for output" , VAL }, + ( char * ) 0 } ; + + +int samplerate ; +float scale ; + +short *signal ; +float *response ; +float *out ; + +main (argc, argv) +int argc; +char **argv; +{ + FILE *fp1, *fp2 ; + struct stat stbuf ; + int i, n, m ; + float f ; + + if ( getopts( option, argc, argv ) != 2 || !isoff( helpstr ) ) + helpopts3( helpstr, argv[0], applic, usage, option ) ; + + samplerate = to_Hz( sampstr ) ; + scale = atof( scalestr ) ; + + if ( ( fp1 = fopen( argv[argc-2], "r" ) ) == (FILE *)0 ) { + fprintf( stderr,"%s: can't open %s\n", argv[0], argv[argc-2] ) ; + exit( 1 ) ; + } + stat( argv[argc-2], &stbuf ) ; + if ( ismax( lenstr ) ) + n = stbuf.st_size / sizeof( short ) ; /* size of signal file */ + else if ( ( n = to_p( lenstr, samplerate ) ) > stbuf.st_size / sizeof( short ) ) { + fprintf( stderr,"conv: insufficient signal\n"); + exit( 1 ) ; + } + + + if ( ( fp2 = fopen( argv[argc-1], "r" ) ) == (FILE *)0 ) { + fprintf( stderr,"%s: can't open %s\n", argv[0], argv[argc-1] ) ; + exit( 1 ) ; + } + stat( argv[argc-1], &stbuf ) ; + m = stbuf.st_size / sizeof( float ) ; /* size of response file */ + + if ( m > n ) { /* size of response file must <= signal file */ + fprintf( stderr,"conv: size of response file must be <= size of signal file\n" ) ; + exit( 1 ) ; + } + + signal = (short *)malloc( n * sizeof(short) ) ; + response = (float *)malloc( m * sizeof(float) ) ; + out = (float *)malloc( n * sizeof(float) ) ; + + fread( signal, sizeof(short), n, fp1 ) ; + fread( response, sizeof(float), m, fp2 ) ; + fclose( fp1 ) ; fclose( fp2 ) ; + + + if ( iststr( domstr, "time" ) ) + convolve_time( signal, n, response, m, out ) ; + + else if ( iststr( domstr, "frequency" ) ) + convolve_freq( signal, n, response, m, out ) ; + + else { + fprintf( stderr,"conv: unknown domain [%s]\n", domstr ) ; + exit( 1 ) ; + } + + + if ( ( f = ftos( out, signal, n, scale ) ) < 1. ) + fprintf( stderr,"Warning: 16-bit overflow during convolution. Try scale factor < %f\n", f ) ; + + fwrite( signal, sizeof(short), n, stdout ) ; + +} + + +