⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ath.c

📁 音频编码
💻 C
📖 第 1 页 / 共 2 页
字号:
}double ATH ( double freq ){    static float tab [] = {        /*    10.0 */  96.69, 96.69, 96.26, 95.12,        /*    12.6 */  93.53, 91.13, 88.82, 86.76,        /*    15.8 */  84.69, 82.43, 79.97, 77.48,        /*    20.0 */  74.92, 72.39, 70.00, 67.62,        /*    25.1 */  65.29, 63.02, 60.84, 59.00,        /*    31.6 */  57.17, 55.34, 53.51, 51.67,        /*    39.8 */  50.04, 48.12, 46.38, 44.66,        /*    50.1 */  43.10, 41.73, 40.50, 39.22,        /*    63.1 */  37.23, 35.77, 34.51, 32.81,        /*    79.4 */  31.32, 30.36, 29.02, 27.60,        /*   100.0 */  26.58, 25.91, 24.41, 23.01,        /*   125.9 */  22.12, 21.25, 20.18, 19.00,        /*   158.5 */  17.70, 16.82, 15.94, 15.12,        /*   199.5 */  14.30, 13.41, 12.60, 11.98,        /*   251.2 */  11.36, 10.57,  9.98,  9.43,        /*   316.2 */   8.87,  8.46,  7.44,  7.12,        /*   398.1 */   6.93,  6.68,  6.37,  6.06,        /*   501.2 */   5.80,  5.55,  5.29,  5.02,        /*   631.0 */   4.75,  4.48,  4.22,  3.98,        /*   794.3 */   3.75,  3.51,  3.27,  3.22,        /*  1000.0 */   3.12,  3.01,  2.91,  2.68,        /*  1258.9 */   2.46,  2.15,  1.82,  1.46,        /*  1584.9 */   1.07,  0.61,  0.13, -0.35,        /*  1995.3 */  -0.96, -1.56, -1.79, -2.35,        /*  2511.9 */  -2.95, -3.50, -4.01, -4.21,        /*  3162.3 */  -4.46, -4.99, -5.32, -5.35,        /*  3981.1 */  -5.13, -4.76, -4.31, -3.13,        /*  5011.9 */  -1.79,  0.08,  2.03,  4.03,        /*  6309.6 */   5.80,  7.36,  8.81, 10.22,        /*  7943.3 */  11.54, 12.51, 13.48, 14.21,        /* 10000.0 */  14.79, 13.99, 12.85, 11.93,        /* 12589.3 */  12.87, 15.19, 19.14, 23.69,        /* 15848.9 */  33.52, 48.65, 59.42, 61.77,        /* 19952.6 */  63.85, 66.04, 68.33, 70.09,        /* 25118.9 */  70.66, 71.27, 71.91, 72.60,    };    double    freq_log;    double    dB;    unsigned  index;        if ( freq <    10. ) freq =    10.;    if ( freq > 25000. ) freq = 25000.;        freq_log = 40. * log10 (0.1 * freq);   /* 4 steps per third, starting at 10 Hz */    index    = (unsigned) freq_log;    assert ( index < sizeof(tab)/sizeof(*tab) );    dB = tab [index] * (1 + index - freq_log) + tab [index+1] * (freq_log - index);    return pow ( 10., 0.05*dB );}/****************************************************************************************************** *  keyboard stuff ******************************************************************************************************/typedef struct {    int             init;    struct termios  stored_setting;    struct termios  current_setting;} keyboard_t;static keyboard_t* __k;/* Restore term-settings to those saved when term_init was called */static void  term_restore (void){    tcsetattr ( 0, TCSANOW, &(__k->stored_setting) );}  /* term_restore *//* Clean up terminal; called on exit */static void  term_exit ( int sig ){    term_restore ();}  /* term_exit *//* Will be called when ctrl-Z is pressed, this correctly handles the terminal */static void  term_ctrl_z ( int sig ){    signal ( SIGTSTP, term_ctrl_z );    term_restore ();    kill ( getpid(), SIGSTOP );}  /* term_ctrl_z *//* Will be called when application is continued after having been stopped */static void  term_cont ( int sig ){    signal ( SIGCONT, term_cont );    tcsetattr ( 0, TCSANOW, &(__k->current_setting) );} /* term_cont() */int  open_keyboard    ( keyboard_t* const k ){    __k = k;    tcgetattr ( 0, &(k->stored_setting) );    tcgetattr ( 0, &(k->current_setting) );    signal ( SIGINT,  term_exit   );       /* We _must_ clean up when we exit */    signal ( SIGQUIT, term_exit   );    signal ( SIGTSTP, term_ctrl_z );       /* Ctrl-Z must also be handled     */    signal ( SIGCONT, term_cont   );//  atexit ( term_exit );    /* One or more characters are sufficient to cause a read to return */    cfmakeraw ( &(k->current_setting) );    k->current_setting.c_oflag     |= ONLCR | OPOST;  /* enables NL => CRLF on output */        tcsetattr ( 0, TCSANOW, &(k->current_setting) );    return 0;}int  getchar_keyboard ( keyboard_t* const k ){    struct timeval  t;    fd_set          fd [1];    int             ret;    unsigned char   c;    FD_SET (0, fd);    t.tv_sec  = 0;    t.tv_usec = 0;    ret = select ( 1, fd, NULL, NULL, &t );        switch ( ret ) {    case  0:        return -1;    case  1:        ret = read (0, &c, 1);        return ret == 1  ?  c  :  -1;    default:        return -2;    }}int  close_keyboard   ( keyboard_t* const k ){    term_restore ();    return 0;}/****************************************************************************************************** *  reporting stuff ******************************************************************************************************/int  report_open ( void ){    static char buff [32767];    fflush  ( stdout );    setvbuf ( stdout, buff, _IOFBF, sizeof(buff) );    return 0;}int  report ( const generator_t* const g, const amplitude_t* const a ){    static double  last_freq  = -1.;    static double  last_level = -1.;    double         freq;    double         level;    freq  = frequency (g);    level = 20. * log10 (amplitude (a) * ATH (freq) ) + 80.;        if ( last_freq >= 0 )        printf ( "%11.3f %8.2f\n", sqrt (freq*last_freq), 0.5 * (level+last_level) );    printf ( "# %9.3f %8.2f\n", freq, level );        fflush ( stdout );        last_freq  = freq;    last_level = level;    return 0;}int  report_close ( void ){    printf ( "%%%%\n\n" );    fflush  ( stdout );    close ( dup ( fileno(stdout) ) );    setvbuf ( stdout, NULL, _IONBF, 0 );    return 0;}/****************************************************************************************************** *  main stuff ******************************************************************************************************/typedef enum {     left     = 0,     right    = 1,     phase0   = 2,     both     = 2,    phase90  = 3,     phase180 = 4,     phasemod = 5 } earmode_t;static long double scalar ( const double* a, const double* b ){    return  a[ 0]*b[ 0] + a[ 1]*b[ 1] + a[ 2]*b[ 2] + a[ 3]*b[ 3]           +a[ 4]*b[ 4] + a[ 5]*b[ 5] + a[ 6]*b[ 6] + a[ 7]*b[ 7]           +a[ 8]*b[ 8] + a[ 9]*b[ 9] + a[10]*b[10] + a[11]*b[11]           +a[12]*b[12] + a[13]*b[13] + a[14]*b[14] + a[15]*b[15];}int experiment ( generator_t* const  g,		 amplitude_t* const  a,		 keyboard_t*  const  k,		 soundcard_t* const  s,		 earmode_t           earmode ){        long           i;    int            j;    stereo_t       samples [512];    static double  quant_errors [2] [16];    long double    val;    double         ampl;    long           ival;        fprintf ( stderr, "\r+++  up  +++" );    for ( i = 0; i < g->duration; i += sizeof(samples)/sizeof(*samples) ) {        fprintf ( stderr, "%3lu%%\b\b\b\b", i*100lu/g->duration );		for (j = 0; j < sizeof(samples)/sizeof(*samples); j++ ) {	    ampl = iterate_amplifier (a) * ATH (frequency (g));	    val  = ampl * iterate_generator (g);	    ival = (long) floor ( val + 0.5 + scalar (quant_errors[0], s->dither) );	    	    if ( ival != (sample_t) ival ) {		report (g, a);		fprintf ( stderr, "\rOverrun     \n\n" );		return -1;	    }	    memmove ( & quant_errors [0] [1], & quant_errors [0] [0], 	              sizeof(quant_errors[0]) - sizeof(quant_errors[0][0]) );	    quant_errors [0] [0] = val - ival; 	    switch ( earmode ) {	    case both: 	        samples [j] [0] = samples [j] [1] = ival; 		break;	    case left: 	        samples [j] [0] = ival;		samples [j] [1] = 0; 		break;	    case right: 	        samples [j] [0] = 0;		samples [j] [1] = ival; 		break;	    case phase180: 	        samples [j] [0] = ival == -32768 ? 32767 : -ival;		samples [j] [1] = +ival; 		break;	    case phase90:	        samples [j] [0] = ival;	        val  = ampl * get_cosine (g);	        ival = (long) floor ( val + 0.5 + scalar (quant_errors[1], s->dither) );	        if ( ival != (sample_t) ival ) {		    report (g, a);		    fprintf ( stderr, "\rOverrun     \n\n" );		    return -1;	        }	        memmove ( & quant_errors [1] [1], & quant_errors [1] [0], 	              sizeof(quant_errors[1]) - sizeof(quant_errors[1][0]) );  	        quant_errors [1] [0] = val - ival; 	        samples [j] [1] = ival;		break;	    default:	        assert (0);		return -1;	    }	}	play_soundcard ( s, samples, sizeof(samples)/sizeof(*samples) );	if ( amplitude (a) * ATH (frequency (g)) <= 3.16227766e-6 ) {            report (g, a);	    fprintf ( stderr, "\rUnderrun      \n\n" );	    return -1;	}		switch ( getchar_keyboard (k) ) {	case '+':	    fprintf ( stderr, "\r+++  up  +++" );	    report (g, a);	    change_direction ( a, up );	    break;	case '-':	    fprintf ( stderr, "\r--- down ---" );            report (g, a);	    change_direction ( a, down );	    break;	case '\r':	case '\n':	    fprintf ( stderr, "\r** change **" );            report (g, a);	    change_direction ( a, change );	    break;	case 'C'&0x1F:	case 'q':	case 'Q':	case 'x':	case 'X':	    fprintf ( stderr, "\rBreak       \n\n" );	    fflush  ( stderr );	    return -1;	default:	    fprintf ( stderr, "\a" );	    break;	case -1:	    break;	}    }	    fprintf ( stderr, "\rReady       \n\n" );    return 0;}static void usage ( void ){    static const char help[] =         "'Absolute Threshold of Hearing' -- Version 0.07   (C) Frank Klemm 2000\n"	"\n"	"usage:\n" 	"    ath  type minfreq maxfreq duration ampl_speed [start_level [earmode] > reportfile\n"	"\n"	"         type:         linear, logarithm, square, cubic, erb, recip\n"	"         minfreq:      initial frequency [Hz]\n"	"         maxfreq:      end frequency [Hz]\n"	"         duration:     duration of the experiment [s]\n"	"         ampl_speed:   amplitude slope speed [phon/s]\n"	"         start_level:  absolute level at startup [0...1]\n"	"         earmode:      left, right, both, phase90, phase180\n"	"\n"	"example:\n"        "    ath  erb  700 22000 600 3 0.0001 > result1\n"	"    ath  erb 1400    16 360 3 0.0001 > result2\n"	"\n"	"handling:\n"	"    press '-' once when you start hearing a tone\n"	"    press '+' once when you stop hearing a tone\n"	"    press 'q' to early leave the program\n"	"    on errors the pressed key is ignored\n";        fprintf ( stderr, "%s\n", help );}int main ( int argc, char** argv ){    generator_t  g;    amplitude_t  a;    soundcard_t  s;    keyboard_t   k;    genmode_t    genmode;    earmode_t    earmode;    if ( argc == 1 ) {        usage ();        system ( "./ath erb  700 22000 600 3 0.0001 > result1" );	system ( "./ath erb 1400    16 360 3 0.0001 > result2" );	system ( "xmgr result1 result2 &> /dev/null &" );	return 0;    }        if ( argc < 6 ) {	usage ();	return 1;    }        if      ( 0 == strncmp ( argv[1], "li" , 2) ) genmode = linear;    else if ( 0 == strncmp ( argv[1], "lo" , 2) ) genmode = logarithm;    else if ( 0 == strncmp ( argv[1], "sq" , 2) ) genmode = square;    else if ( 0 == strncmp ( argv[1], "cu" , 2) ) genmode = cubic;    else if ( 0 == strncmp ( argv[1], "er" , 2) ) genmode = erb;    else if ( 0 == strncmp ( argv[1], "re" , 2) ) genmode = recip;    else {	usage ();	return 1;    }    if      ( argc < 8 )                              earmode = both;    else if ( 0 == strncmp ( argv[7], "le"     , 2) ) earmode = left;    else if ( 0 == strncmp ( argv[7], "ri"     , 2) ) earmode = right;    else if ( 0 == strncmp ( argv[7], "bo"     , 2) ) earmode = both;    else if ( 0 == strncmp ( argv[7], "phase9" , 6) ) earmode = phase90;    else if ( 0 == strncmp ( argv[7], "phase1" , 6) ) earmode = phase180;    else {	usage ();	return 1;    }        open_soundcard ( &s, AUDIO_DEVICE, sizeof(stereo_t)/sizeof(sample_t), CHAR_BIT*sizeof(sample_t), 96000.0 );    open_generator ( &g, &s, genmode, atof (argv[4]), atof (argv[2]), atof (argv[3]) );    open_amplifier ( &a, &s, argc > 6  ?  atof (argv[6])  :  0.0001, atof (argv[5]) );    open_keyboard  ( &k );    report_open    ( );    experiment     ( &g, &a, &k, &s, earmode );    report_close   ( );        close_keyboard ( &k );    close_amplifier( &a );    close_generator( &g );    close_soundcard( &s );        return 0;}/* end of ath.c */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -