view 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 source
/*
    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 ) ;
}