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

📄 ath.c

📁 音频编码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* $Id: ath.c,v 1.12 2000/12/05 15:37:26 aleidinger Exp $ *//* * Known bugs (sorted by importance):  *     - human delay (ca. 200 ms or more???) and buffering delay (341 ms @48 kHz/64 KByte) *       should be subtracted *     - error handling *     - cos slope on direction changes *     - calibration file of soundcard/amplifier/head phone *     - worse handling *     - +/- handling via mouse (do you have code?) in a dark room *     - ENTER as direction change *     - finer precalculated ATH for pre-emphasis *//*  * Suggested level ranges: *     180 Hz...13.5 kHz:  50...70 dB *     100 Hz...15.0 kHz:  40...70 dB *      70 Hz...16.0 kHz:  30...70 dB *      45 Hz...16.5 kHz:  20...70 dB *      30 Hz...17.5 kHz:  10...70 dB *      25 Hz...18.0 kHz:   5...75 dB *      20 Hz...19.0 kHz:   0...80 dB *      16 Hz...20.0 kHz: -10...80 dB */#ifdef HAVE_CONFIG_H# include <config.h>#endif#include <assert.h>#include <errno.h>#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <string.h>#include <fcntl.h>#include <limits.h>#include <termios.h>#include <math.h>#include <time.h>#include <signal.h>#include <sys/ioctl.h>#include <sys/time.h>#include <sys/types.h>#include <sys/stat.h>#ifdef HAVE_SYS_SOUNDCARD_H# include <sys/soundcard.h>#elif defined(HAVE_LINUX_SOUNDCARD_H)# include <linux/soundcard.h>#else# error no soundcard include#endif     #define AUDIO_DEVICE       "/dev/dsp"//#define COOLEDIT_FILE      "/mnt/dosd/cooledit.wav"#define DELAY_UNTIL_XCHG   2.5#define TURN_STEPS	   2400/****************************************************************************************************** *  soundcard stuff ******************************************************************************************************/const double dither_coeff [] [16] = {    {  /* 48 kHz */ 3.35185352775391591311,  4.24914379295482032978,  1.78042251729150153086, -0.92601381419186201184, -1.37308596104182343645, -1.85951915999247704829, -3.28074437872632330526, -3.05496670185702990882, -1.22855462839450528837, -0.30291531959171267015, -0.18598486195652600770,  0.42010512205702003790,  0.92278786111368653452,  0.62102380451771775193,  0.14312897206650044828, -0.00454721508203927746 },    {  /* 56 kHz */ 3.86404134982280628749,  6.67195592701613291071,  5.90576195467245802046,  1.57589705921487261981, -2.10618201389737372178, -2.74191788822507184395, -2.62175070636849999396, -3.78505226463032808863, -4.45698848578010438284, -2.76825966243460536110, -0.26509931375584007312,  0.67853812028968716799,  0.17633528441477021892, -0.28511417191837823770, -0.21866605100975608470, -0.04751674094456833719 },    {  /* 64 kHz */ 4.09276938880098092172,  8.27424044674659812937, 10.11503162292146762880,  7.19159801569544317353,  1.39770070291739556523, -2.86595901981244688601, -3.76567274050094691362, -3.58051445684472378298, -4.78262917738758022539, -6.53075750894777650899, -6.31330514306857055627, -3.69971382767763534195, -0.78125094191744878298,  0.59027508113837267217,  0.53500264009607367648,  0.14860043567206217506 },    {  /* 72 kHz */ 4.13833553801985235465,  9.02461778089340082437, 12.93090366932740510782, 12.66372285767699051948,  7.76122176702274149630,  1.30617257555732278296, -2.92859120887121285358, -4.02438598495837830627, -4.16673068132491936262, -5.55618065300129916574, -7.82657788611231653103, -8.83055904466106668035, -7.34884789347713815672, -4.33977664906048314891, -1.67711310288611975398, -0.33086687044710235420 },    {  /* 80 kHz */ 4.22135293342667005517,  9.76639846582539722375, 15.46562682418357478290, 17.54378549927855248346, 13.29112084313158963396,  3.51512441998252657470, -7.51025671462502577300,-14.84164320864536219368,-16.10306907358826504148,-12.54775907691866414402, -7.40560667268782655149, -3.34708029482052565732, -1.19572214872925790860, -0.39582185216275086786, -0.14803160816846603424, -0.04292818488627011881 },    {  /* 88 kHz */ 4.18521467865996935325,  9.96765821475909556942, 16.91905760389390617551, 21.74016824668913557689, 20.96457146354060682367, 13.28640453421253890542,  0.85116933842171101587,-11.66054516261007127469,-19.62750656985581800169,-20.98831962473015904508,-16.95374072505042825458,-10.68848180295390154146, -5.17169792984369678908, -1.79975409439650319129, -0.38057073791415898674, -0.02672653932844656975 },    {  /* 96 kHz */ 4.09418877324899473189,  9.77977364010870211207, 17.10120082680385341159, 23.37356217615995036818, 25.27121942060722374276, 20.64059991613550174190,  9.99721445051475610371, -3.39833000550997938512,-15.03410054392933377278,-21.36704201000683067679,-21.40772859969388741685,-16.79355426136657673808,-10.48570200688141622163, -5.07642951516127438486, -1.75555240936989159436, -0.33817997298586054131 },};typedef struct {    const char*    device;    int            fd;    long double    sample_freq;    const double*  dither;    int            channels;    int            bits;} soundcard_t;typedef signed short  sample_t;typedef sample_t      stereo_t [2]; int  open_soundcard (     soundcard_t* const  k,     const char*         device,     const int           channels,    const int           bits,     const long double   freq ){    int  arg;    int  org;    int  index;    int  status;        k->device = device;    if ( -1 == (k->fd = open ( k->device, O_WRONLY )) ) {        perror("opening of audio device failed");	return -1;    }        if ( -1 == (status = ioctl (k->fd, SOUND_PCM_SYNC, 0))) {        fprintf ( stderr, "%s: SOUND_PCM_SYNC ioctl failed: %s\n", k->device, strerror (errno));        return -1;    }    org = arg = channels;    if ( -1 == (status = ioctl (k->fd, SOUND_PCM_WRITE_CHANNELS, &arg)) ) {	fprintf ( stderr, "%s: SOUND_PCM_WRITE_CHANNELS (%d) ioctl failed: %s\n" , k->device, channels, strerror (errno) );	return -1;    }    if (arg != org) {	fprintf ( stderr, "%s: unable to set number of channels: %d instead of %d\n", k->device, arg, org );	return -1;    }    k->channels = arg;        org = arg = bits;    if ( -1 == (status = ioctl (k->fd, SOUND_PCM_WRITE_BITS, &arg)) ) {	fprintf ( stderr, "%s: SOUND_PCM_WRITE_BITS ioctl failed\n", k->device );	return -1;    }    if (arg != org) {	fprintf ( stderr, "%s: unable to set sample size: %d instead of %d\n", k->device, arg, org );	return -1;    }    k->bits = arg;    org = arg = k->bits <= 8  ?  AFMT_U8  :  AFMT_S16_LE;    if ( -1 == ioctl (k->fd, SNDCTL_DSP_SETFMT, &arg) ) {	fprintf ( stderr, "%s: SNDCTL_DSP_SETFMT ioctl failed\n", k->device );	return -1;    }    if ((arg & org) == 0) {	fprintf ( stderr, "%s: unable to set data format\n", k->device );	return -1;    }        org = arg = (int) floor ( freq + 0.5 );    if ( -1 == (status = ioctl (k->fd, SOUND_PCM_WRITE_RATE, &arg)) ) {	fprintf ( stderr, "%s: SOUND_PCM_WRITE_WRITE ioctl failed\n", k->device );	return -1;    }    k->sample_freq = (long double)arg;    index          = (arg - 44000) / 8000;    if ( index <                                           0 ) index = 0;    if ( index >= sizeof(dither_coeff)/sizeof(*dither_coeff) ) index = sizeof(dither_coeff)/sizeof(*dither_coeff) - 1;    k->dither      = dither_coeff [ index ];    return 0;}int  play_soundcard    ( soundcard_t* const k, stereo_t* samples, size_t length ){    size_t  bytes = length * sizeof (*samples);    #ifdef COOLEDIT_FILE    static int fd = -1;    if ( fd < 0 ) fd = open ( COOLEDIT_FILE, O_WRONLY | O_CREAT );    write ( fd, samples, bytes );#endif            return write ( k->fd, samples, bytes ) == bytes  ?  0  :  -1;}int  close_soundcard   ( soundcard_t* const k ){    return close (k->fd);}/****************************************************************************************************** *  frequency stuff ******************************************************************************************************/typedef enum {    linear    = 0,    logarithm = 1,    square    = 2,    cubic     = 3,    erb       = 4,    recip     = 5} genmode_t;static long double linear_f        ( long double x ) { return x > 0.L  ?  x             :  0.0L; }static long double logarithm_f     ( long double x ) { return x > 0.L  ?  log10 (x)     : -3.5L; }static long double square_f        ( long double x ) { return x > 0.L  ?  sqrt (x)      :  0.0L; }static long double cubic_f         ( long double x ) { return x > 0.L  ?  pow (x,1/3.)  :  0.0L; }static long double erb_f           ( long double x ) { return log (1. + 0.00437*x); }static long double recip_f         ( long double x ) { return x > 1.L  ?  1.L/x         :  1.0L; }static long double inv_linear_f    ( long double x ) { return x;  }static long double inv_logarithm_f ( long double x ) { return pow (10., x);  }static long double inv_square_f    ( long double x ) { return x*x;  }static long double inv_cubic_f     ( long double x ) { return x*x*x;  }static long double inv_erb_f       ( long double x ) { return (exp(x) - 1.) * (1./0.00437); }static long double inv_recip_f     ( long double x ) { return x > 1.L  ?  1.L/x         :  1.0L; }typedef long double (*converter_fn_t) ( long double );const converter_fn_t  func     [] = { linear_f,     logarithm_f,     square_f,     cubic_f    , erb_f    , recip_f     };const converter_fn_t  inv_func [] = { inv_linear_f, inv_logarithm_f, inv_square_f, inv_cubic_f, inv_erb_f, inv_recip_f };typedef struct {    genmode_t      genmode;    long double    start_freq;    long double    stop_freq;    long double    sample_freq;    unsigned long  duration;    long double    phase;    long double    param1;    long double    param2;    unsigned long  counter; } generator_t;int  open_generator (     generator_t* const  g,    const soundcard_t*  const s,    const genmode_t     genmode,     const long double   duration,     const long double   start_freq,     const long double   stop_freq ){    g->sample_freq = s->sample_freq;    g->genmode     = genmode;    g->start_freq  = start_freq;    g->stop_freq   = stop_freq;    g->duration    = (unsigned long) floor ( duration * g->sample_freq + 0.5 );        if ( g->duration < 2 )	return -1;    if ( g->genmode >= sizeof (func)/sizeof(*func) )	return -1;        g->param1 = func [g->genmode] ( g->start_freq / g->sample_freq );    g->param2 = ( func [ g->genmode ] ( g->stop_freq / g->sample_freq ) - g->param1 ) 	      / ( g->duration - 1 );    g->phase  = 0.L;    g->counter= 0;        return 0;}long double  iterate_generator ( generator_t* const g ){    long double  freq;        freq = inv_func [ g->genmode ] ( g->param1 + g->counter++ * g->param2 );	    g->phase += freq;    if (g->phase > 15.)	g->phase -= 16.;    return sin ( 2.*M_PI * g->phase );}long double  get_sine ( generator_t* const g ){    return sin ( 2.*M_PI * g->phase );}long double  get_cosine ( generator_t* const g ){    return cos ( 2.*M_PI * g->phase );}long double  frequency ( const generator_t* const g ){    return inv_func [ g->genmode ] ( g->param1 + g->counter * g->param2 ) * g->sample_freq;}int  close_generator ( generator_t* const g ){    return 0;}/****************************************************************************************************** *  amplitude stuff ******************************************************************************************************/typedef enum {    up         = 0,    down       = 1,    turn_up    = 2,    turn_down  = 3,    still_up   = 4,    still_down = 5,    change     = 6} direction_t;		typedef struct {    long double    sample_freq;    direction_t    direction;            // down, up, still_up, still_down, turn_down, turn_up    int            multiplier;           // -TURN_STEPS: down, +TURN_STEPS up    long double    amplitude;    long double    delta_amplitude;    long           direction_change;} amplitude_t;int  open_amplifier (     amplitude_t* const        a,    const soundcard_t* const  s,    const long double         start_ampl,    const double              dB_per_sec ){    a->sample_freq      = s->sample_freq;    a->direction        = up;    a->multiplier       = +TURN_STEPS;    a->amplitude        = start_ampl * 32767.;    a->delta_amplitude  = dB_per_sec * 0.1151292546497022842 / s->sample_freq / TURN_STEPS;    a->direction_change = 0;        srand ( time (NULL) );    return 0;}long double iterate_amplifier ( amplitude_t* const a ){    switch ( a->direction ) {    case still_up:        assert (a->multiplier == +TURN_STEPS);        if (a->direction_change > 0 )	    a->direction_change--;	else	    a->direction = turn_down;	break;    case still_down:        assert (a->multiplier == -TURN_STEPS);        if (a->direction_change > 0 )	    a->direction_change--;	else	    a->direction = turn_up;	break;    case turn_up:        assert (a->direction_change == 0);	if ( a->multiplier < +TURN_STEPS )	    a->multiplier++;	else	    a->direction = up;	break;    case turn_down:        assert (a->direction_change == 0);	if ( a->multiplier > -TURN_STEPS )	    a->multiplier--;	else	    a->direction = down;	break;    case up:        assert (a->multiplier == +TURN_STEPS);        assert (a->direction_change == 0);	break;    case down:        assert (a->multiplier == -TURN_STEPS);        assert (a->direction_change == 0);	break;    default:	fprintf ( stderr, "\n\r*** Bug! ***\n");	break;    }    a->amplitude *= 1.L + a->delta_amplitude * a->multiplier;    return a->amplitude;         }long double amplitude ( const amplitude_t* const a ){    return a->amplitude / 32767.;}int change_direction ( amplitude_t* const a, direction_t new_direction ){    switch ( new_direction ) {    case up:        if (a->direction == down) {	    a->direction = still_down;	} else {	    fprintf ( stderr, "Direction not down, so ignored\n" );	    return -1;	}	break;    case down:        if (a->direction == up) {	    a->direction = still_up;	} else {	    fprintf ( stderr, "Direction not up, so ignored\n" );	    return -1;	}	break;    case change:        switch ( a->direction ) {        case up:	    a->direction = still_up;	    break;	case down:	    a->direction = still_down;	    break;	default:	    fprintf ( stderr, "Direction still changing, so ignored\n" );	    return -1;	}	break;        default:	fprintf ( stderr, "Direction unknown, so ignored\n" );	return -1;    }    a->direction_change = 1 + rand () * (a->sample_freq * DELAY_UNTIL_XCHG / RAND_MAX);    return 0;}int  close_amplifier ( amplitude_t* const a ){    return 0;

⌨️ 快捷键说明

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