diff tools/fbank.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/fbank.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,199 @@
+/*
+    fbank.c     Print parameters and misc info of a filterbank.
+    -------
+
+  The filterbank parameters are read from defaults or overriding options.
+  If the "input" option is set, then the parameters are read from a model
+  header, which can be given as a model output filename, or piped in.
+
+  Channels may be specified using option: freq=a-b
+  where "a" and "b" may be numbers with optional units of Hz or kHz appended,
+  or may be the strings "min" or "max".
+
+  With no units, the specifier is interpreted as channel (ie row) numbers.
+  These must be in the range 0 to channels-1, (where the lowest centre-freq
+  channel has the lowest channel number, 0, and `channels' is the max number
+  of channels, depending upon the parameters of the filterbank).
+
+  "min" is interpreted as the lowest  frequency channel (number 0).
+  "max" is interpreted as the highest frequency channel (number channels-1).
+
+  With frequency units, the specifier is interpreted as centre-frequencies.
+  These are converted to channel numbers using the "closest" channel number
+  in the filterbank to each specified centre-frequency.
+
+  Single channels or ranges can be specified.
+  The default specifier is freq=min-max
+  Eg:
+	specifier    channel number
+	----------   ---------------
+	freq=5       5
+	freq=1kHz    channel number with centre-freq closest to 1kHz
+	freq=max     max channel number (channels-1)
+	freq=10-max  10 to channels-1
+	freq=min-15  0 to 15
+
+*/
+
+
+#include <stdio.h>
+#include <math.h>
+#include "header.h"
+#include "options.h"
+#include "units.h"
+#include "strmatch.h"
+#include "freqs.c"
+
+char applic[]     = "Print parameters of a filterbank. " ;
+
+static char *helpstr, *debugstr, *instr, *cfstr, *sampstr, *chanstr, *minstr, *maxstr, *denstr, *bwstr, *qualstr ;
+
+static Options option[] = {
+    {   "help"      ,   "off"       ,  &helpstr     ,   "help"                                          , DEBUG   },
+    {   "debug"     ,   "off"       ,  &debugstr    ,   "debugging switch"                              , DEBUG   },
+    {   "input"     ,   "off"       ,  &instr       ,   "Input (off/on)"                                , FLAG    },
+    {   "freq"      ,   "min-max"   ,  &cfstr       ,   "Frequency (or channel number)"                 , VAL     },
+    {   "samplerate",   "20000."    ,  &sampstr     ,   "Input wave sample rate (Hz)"                   , VAL     },
+    {   "channels"  ,   "75"        ,  &chanstr     ,   "Number of channels in filter"                  , VAL     },
+    {   "mincf"     ,   "100Hz"     ,  &minstr      ,   "Minimum center frequency (Hz)"                 , VAL     },
+    {   "maxcf"     ,   "6000Hz"    ,  &maxstr      ,   "Maximum center frequency (Hz)"                 , VAL     },
+    {   "dencf"     ,   "off"       ,  &denstr      ,   "Filter density (filters/critical band)"        , VAL     },
+    {   "bwmin"     ,   "24.7Hz"    ,  &bwstr       ,   "Minimum filter bandwith"                       , VAL     },
+    {   "quality"   ,   "9.265"     ,  &qualstr     ,   "Ultimate qualtity factor of filters"           , VAL     },
+   ( char * ) 0 } ;
+
+
+int     samplerate  ;
+int     channels    ;
+double *frequencies ;
+
+
+main(argc, argv)
+int   argc ;
+char *argv[] ;
+{
+    FILE  *fp ;
+    char  *header ;
+    char  *val1, *val2, *headerstring() ;
+    int    i, cf1, cf2 ;
+
+    fp = openopts( option,argc,argv ) ;
+    if ( !isoff( helpstr ) )
+	helpopts( helpstr, argv[0], applic, option ) ;
+
+    if ( !isoff( instr ) ) {
+
+	if ( (header = ReadHeader(fp)) == (char *) 0 ) {
+	    fprintf(stderr,"fbank: header not found\n");
+	    exit(1);
+	}
+	sampstr  =  headerstring( header, "samplerate"   ) ;
+	chanstr  =  headerstring( header, "channels_afb" ) ;
+	minstr   =  headerstring( header, "mincf_afb"    ) ;
+	maxstr   =  headerstring( header, "maxcf_afb"    ) ;
+	denstr   =  headerstring( header, "dencf_afb"    ) ;
+	bwstr    =  headerstring( header, "bwmin_afb"    ) ;
+	qualstr  =  headerstring( header, "quality_afb"  ) ;
+    }
+
+    samplerate = to_Hz( sampstr, 0 ) ;
+    channels   = OptionInt( chanstr ) ;
+
+    SetErbParameters( to_Hz( bwstr, samplerate ), atof( qualstr ) ) ;
+    if( channels == 0 ) {
+	frequencies = GenerateCenterFrequencies( to_Hz( minstr, samplerate ), to_Hz( maxstr, samplerate ), atof( denstr ) ) ;
+	channels = NumberCenterFrequencies( to_Hz( minstr, samplerate ), to_Hz( maxstr, samplerate ), atof( denstr ) ) ;
+    }
+    else
+	frequencies = NumberedCenterFrequencies( to_Hz( minstr, samplerate ), to_Hz( maxstr, samplerate ), OptionInt( chanstr ) ) ;
+
+
+    /* Get limits on specified frequency (ie channels or rows) */
+
+    if ( getvals( cfstr, &val1, &val2, "-" ) == BADVAL ) {
+	fprintf(stderr,"fbank: bad frequency selector [%s]\n", cfstr ) ;
+	exit( 1 ) ;
+    }
+    if ( ismin( val1 ) )         cf1 = 0 ;
+    else if ( ismax( val1 ) )    cf1 = channels-1 ;
+    else if ( Units( val1 ) )    cf1 = closest( to_Hz( val1, samplerate ), frequencies, channels ) ;
+    else                         cf1 = atoi( val1 ) ;
+
+    if (      isempty( val2 ) )  cf2 = cf1 ;
+    else if ( ismin( val2 ) )    cf2 = 0 ;
+    else if ( ismax( val2 ) )    cf2 = channels-1 ;
+    else if ( Units( val2 ) )    cf2 = closest( to_Hz( val2, samplerate ), frequencies, channels ) ;
+    else                         cf2 = atoi( val2 ) ;
+
+    if ( cf1<0 || cf1>cf2 || cf2>channels ) {
+	fprintf( stderr,"fbank: incorrect frequency specifier [%s] for %d channel filterbank\n", cfstr, channels ) ;
+	exit( 1 ) ;
+    }
+
+    printf("channel     cf         period            ERB   \n");
+    printf("number     (Hz)     (ms)  (samples)      (Hz)  \n");
+    printf("-------   ------    ---------------     ------ \n");
+
+    for (i=cf1 ; i<=cf2 ; i++)
+	printf( "%3d      %7.2f   %6.2f    %6.2f    %6.2f \n", i, frequencies[i], 1000./frequencies[i], (double)samplerate/frequencies[i], frequencies[i]/9.26449 + 24.7 );
+
+}
+
+
+/* Return the index of the frequency closest to the given "freq" */
+
+int closest( freq, frequencies, channels )
+double freq, *frequencies ;
+int    channels ;
+{
+    int i;
+
+    for (i=0 ; i<channels && frequencies[i]<freq ; i++)
+	;
+    if (i==channels) return ( i-1 ) ;
+    if (i==0) return i ;
+    if ( frequencies[i]-freq < freq-frequencies[i-1] ) return i ;
+    else return ( i-1 ) ;
+}
+
+/* Return 1 if the str has appended units. Otherwise return 0.             */
+/* (A freqency specifier with no units is interpreted as a channel number) */
+
+Units(str)
+char *str ;
+{
+    char *eptr = str + strlen( str ) ;
+
+    if( isdigit( *--eptr ) ) return 0 ; /* last char is digit, so no units */
+    else return 1 ;
+}
+
+
+int OptionInt( str )
+char *str ;
+{
+    if( strcmp( str, "on" ) == 0 )
+	return( 1 ) ;
+    else if( strcmp( str, "Not_used" ) == 0 )
+	return( 0 ) ;
+    else
+	return( atoi( str ) ) ;
+}
+
+
+/*
+Return an allocated string to the value part of an option in the header
+with the given name. Exit if option not found in header.
+*/
+
+char *headerstring( header, name )
+char *header, *name ;
+{
+    char  *valuestr ;
+
+    if ( (valuestr = HeaderStringOnly( header, name )) == (char *) 0) {
+	fprintf(stderr,"edframe: option %s not found in header\n", name);
+	exit(1);
+    }
+    return ( valuestr ) ;
+}