ath.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839
  1. /* $Id$ */
  2. /*
  3. * Known bugs (sorted by importance):
  4. * - human delay (ca. 200 ms or more???) and buffering delay (341 ms @48 kHz/64 KByte)
  5. * should be subtracted
  6. * - error handling
  7. * - cos slope on direction changes
  8. * - calibration file of soundcard/amplifier/head phone
  9. * - worse handling
  10. * - +/- handling via mouse (do you have code?) in a dark room
  11. * - ENTER as direction change
  12. * - finer precalculated ATH for pre-emphasis
  13. */
  14. /*
  15. * Suggested level ranges:
  16. * 180 Hz...13.5 kHz: 50...70 dB
  17. * 100 Hz...15.0 kHz: 40...70 dB
  18. * 70 Hz...16.0 kHz: 30...70 dB
  19. * 45 Hz...16.5 kHz: 20...70 dB
  20. * 30 Hz...17.5 kHz: 10...70 dB
  21. * 25 Hz...18.0 kHz: 5...75 dB
  22. * 20 Hz...19.0 kHz: 0...80 dB
  23. * 16 Hz...20.0 kHz: -10...80 dB
  24. */
  25. #ifdef HAVE_CONFIG_H
  26. # include <config.h>
  27. #endif
  28. #include <assert.h>
  29. #include <errno.h>
  30. #include <stdio.h>
  31. #include <stdlib.h>
  32. #include <unistd.h>
  33. #include <string.h>
  34. #include <fcntl.h>
  35. #include <limits.h>
  36. #include <termios.h>
  37. #include <math.h>
  38. #include <time.h>
  39. #include <signal.h>
  40. #include <sys/ioctl.h>
  41. #include <sys/time.h>
  42. #include <sys/types.h>
  43. #include <sys/stat.h>
  44. #ifdef HAVE_SYS_SOUNDCARD_H
  45. # include <sys/soundcard.h>
  46. #elif defined(HAVE_LINUX_SOUNDCARD_H)
  47. # include <linux/soundcard.h>
  48. #else
  49. # error no soundcard include
  50. #endif
  51. #define AUDIO_DEVICE "/dev/dsp"
  52. //#define COOLEDIT_FILE "/mnt/dosd/cooledit.wav"
  53. #define DELAY_UNTIL_XCHG 2.5
  54. #define TURN_STEPS 2400
  55. /******************************************************************************************************
  56. * soundcard stuff
  57. ******************************************************************************************************/
  58. const double dither_coeff [] [16] = {
  59. { /* 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 },
  60. { /* 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 },
  61. { /* 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 },
  62. { /* 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 },
  63. { /* 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 },
  64. { /* 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 },
  65. { /* 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 },
  66. };
  67. typedef struct {
  68. const char* device;
  69. int fd;
  70. long double sample_freq;
  71. const double* dither;
  72. int channels;
  73. int bits;
  74. } soundcard_t;
  75. typedef signed short sample_t;
  76. typedef sample_t stereo_t [2];
  77. int open_soundcard (
  78. soundcard_t* const k,
  79. const char* device,
  80. const int channels,
  81. const int bits,
  82. const long double freq )
  83. {
  84. int arg;
  85. int org;
  86. int index;
  87. int status;
  88. k->device = device;
  89. if ( -1 == (k->fd = open ( k->device, O_WRONLY )) ) {
  90. perror("opening of audio device failed");
  91. return -1;
  92. }
  93. if ( -1 == (status = ioctl (k->fd, SOUND_PCM_SYNC, 0))) {
  94. fprintf ( stderr, "%s: SOUND_PCM_SYNC ioctl failed: %s\n", k->device, strerror (errno));
  95. return -1;
  96. }
  97. org = arg = channels;
  98. if ( -1 == (status = ioctl (k->fd, SOUND_PCM_WRITE_CHANNELS, &arg)) ) {
  99. fprintf ( stderr, "%s: SOUND_PCM_WRITE_CHANNELS (%d) ioctl failed: %s\n" , k->device, channels, strerror (errno) );
  100. return -1;
  101. }
  102. if (arg != org) {
  103. fprintf ( stderr, "%s: unable to set number of channels: %d instead of %d\n", k->device, arg, org );
  104. return -1;
  105. }
  106. k->channels = arg;
  107. org = arg = bits;
  108. if ( -1 == (status = ioctl (k->fd, SOUND_PCM_WRITE_BITS, &arg)) ) {
  109. fprintf ( stderr, "%s: SOUND_PCM_WRITE_BITS ioctl failed\n", k->device );
  110. return -1;
  111. }
  112. if (arg != org) {
  113. fprintf ( stderr, "%s: unable to set sample size: %d instead of %d\n", k->device, arg, org );
  114. return -1;
  115. }
  116. k->bits = arg;
  117. org = arg = k->bits <= 8 ? AFMT_U8 : AFMT_S16_LE;
  118. if ( -1 == ioctl (k->fd, SNDCTL_DSP_SETFMT, &arg) ) {
  119. fprintf ( stderr, "%s: SNDCTL_DSP_SETFMT ioctl failed\n", k->device );
  120. return -1;
  121. }
  122. if ((arg & org) == 0) {
  123. fprintf ( stderr, "%s: unable to set data format\n", k->device );
  124. return -1;
  125. }
  126. org = arg = (int) floor ( freq + 0.5 );
  127. if ( -1 == (status = ioctl (k->fd, SOUND_PCM_WRITE_RATE, &arg)) ) {
  128. fprintf ( stderr, "%s: SOUND_PCM_WRITE_WRITE ioctl failed\n", k->device );
  129. return -1;
  130. }
  131. k->sample_freq = (long double)arg;
  132. index = (arg - 44000) / 8000;
  133. if ( index < 0 ) index = 0;
  134. if ( index >= sizeof(dither_coeff)/sizeof(*dither_coeff) ) index = sizeof(dither_coeff)/sizeof(*dither_coeff) - 1;
  135. k->dither = dither_coeff [ index ];
  136. return 0;
  137. }
  138. int play_soundcard ( soundcard_t* const k, stereo_t* samples, size_t length )
  139. {
  140. size_t bytes = length * sizeof (*samples);
  141. #ifdef COOLEDIT_FILE
  142. static int fd = -1;
  143. if ( fd < 0 ) fd = open ( COOLEDIT_FILE, O_WRONLY | O_CREAT );
  144. write ( fd, samples, bytes );
  145. #endif
  146. return write ( k->fd, samples, bytes ) == bytes ? 0 : -1;
  147. }
  148. int close_soundcard ( soundcard_t* const k )
  149. {
  150. return close (k->fd);
  151. }
  152. /******************************************************************************************************
  153. * frequency stuff
  154. ******************************************************************************************************/
  155. typedef enum {
  156. linear = 0,
  157. logarithm = 1,
  158. square = 2,
  159. cubic = 3,
  160. erb = 4,
  161. recip = 5
  162. } genmode_t;
  163. static long double linear_f ( long double x ) { return x > 0.L ? x : 0.0L; }
  164. static long double logarithm_f ( long double x ) { return x > 0.L ? log10 (x) : -3.5L; }
  165. static long double square_f ( long double x ) { return x > 0.L ? sqrt (x) : 0.0L; }
  166. static long double cubic_f ( long double x ) { return x > 0.L ? pow (x,1/3.) : 0.0L; }
  167. static long double erb_f ( long double x ) { return log (1. + 0.00437*x); }
  168. static long double recip_f ( long double x ) { return x > 1.L ? 1.L/x : 1.0L; }
  169. static long double inv_linear_f ( long double x ) { return x; }
  170. static long double inv_logarithm_f ( long double x ) { return pow (10., x); }
  171. static long double inv_square_f ( long double x ) { return x*x; }
  172. static long double inv_cubic_f ( long double x ) { return x*x*x; }
  173. static long double inv_erb_f ( long double x ) { return (exp(x) - 1.) * (1./0.00437); }
  174. static long double inv_recip_f ( long double x ) { return x > 1.L ? 1.L/x : 1.0L; }
  175. typedef long double (*converter_fn_t) ( long double );
  176. const converter_fn_t func [] = { linear_f, logarithm_f, square_f, cubic_f , erb_f , recip_f };
  177. const converter_fn_t inv_func [] = { inv_linear_f, inv_logarithm_f, inv_square_f, inv_cubic_f, inv_erb_f, inv_recip_f };
  178. typedef struct {
  179. genmode_t genmode;
  180. long double start_freq;
  181. long double stop_freq;
  182. long double sample_freq;
  183. unsigned long duration;
  184. long double phase;
  185. long double param1;
  186. long double param2;
  187. unsigned long counter;
  188. } generator_t;
  189. int open_generator (
  190. generator_t* const g,
  191. const soundcard_t* const s,
  192. const genmode_t genmode,
  193. const long double duration,
  194. const long double start_freq,
  195. const long double stop_freq )
  196. {
  197. g->sample_freq = s->sample_freq;
  198. g->genmode = genmode;
  199. g->start_freq = start_freq;
  200. g->stop_freq = stop_freq;
  201. g->duration = (unsigned long) floor ( duration * g->sample_freq + 0.5 );
  202. if ( g->duration < 2 )
  203. return -1;
  204. if ( g->genmode >= sizeof (func)/sizeof(*func) )
  205. return -1;
  206. g->param1 = func [g->genmode] ( g->start_freq / g->sample_freq );
  207. g->param2 = ( func [ g->genmode ] ( g->stop_freq / g->sample_freq ) - g->param1 )
  208. / ( g->duration - 1 );
  209. g->phase = 0.L;
  210. g->counter= 0;
  211. return 0;
  212. }
  213. long double iterate_generator ( generator_t* const g )
  214. {
  215. long double freq;
  216. freq = inv_func [ g->genmode ] ( g->param1 + g->counter++ * g->param2 );
  217. g->phase += freq;
  218. if (g->phase > 15.)
  219. g->phase -= 16.;
  220. return sin ( 2.*M_PI * g->phase );
  221. }
  222. long double get_sine ( generator_t* const g )
  223. {
  224. return sin ( 2.*M_PI * g->phase );
  225. }
  226. long double get_cosine ( generator_t* const g )
  227. {
  228. return cos ( 2.*M_PI * g->phase );
  229. }
  230. long double frequency ( const generator_t* const g )
  231. {
  232. return inv_func [ g->genmode ] ( g->param1 + g->counter * g->param2 ) * g->sample_freq;
  233. }
  234. int close_generator ( generator_t* const g )
  235. {
  236. return 0;
  237. }
  238. /******************************************************************************************************
  239. * amplitude stuff
  240. ******************************************************************************************************/
  241. typedef enum {
  242. up = 0,
  243. down = 1,
  244. turn_up = 2,
  245. turn_down = 3,
  246. still_up = 4,
  247. still_down = 5,
  248. change = 6
  249. } direction_t;
  250. typedef struct {
  251. long double sample_freq;
  252. direction_t direction; // down, up, still_up, still_down, turn_down, turn_up
  253. int multiplier; // -TURN_STEPS: down, +TURN_STEPS up
  254. long double amplitude;
  255. long double delta_amplitude;
  256. long direction_change;
  257. } amplitude_t;
  258. int open_amplifier (
  259. amplitude_t* const a,
  260. const soundcard_t* const s,
  261. const long double start_ampl,
  262. const double dB_per_sec )
  263. {
  264. a->sample_freq = s->sample_freq;
  265. a->direction = up;
  266. a->multiplier = +TURN_STEPS;
  267. a->amplitude = start_ampl * 32767.;
  268. a->delta_amplitude = dB_per_sec * 0.1151292546497022842 / s->sample_freq / TURN_STEPS;
  269. a->direction_change = 0;
  270. srand ( time (NULL) );
  271. return 0;
  272. }
  273. long double iterate_amplifier ( amplitude_t* const a )
  274. {
  275. switch ( a->direction ) {
  276. case still_up:
  277. assert (a->multiplier == +TURN_STEPS);
  278. if (a->direction_change > 0 )
  279. a->direction_change--;
  280. else
  281. a->direction = turn_down;
  282. break;
  283. case still_down:
  284. assert (a->multiplier == -TURN_STEPS);
  285. if (a->direction_change > 0 )
  286. a->direction_change--;
  287. else
  288. a->direction = turn_up;
  289. break;
  290. case turn_up:
  291. assert (a->direction_change == 0);
  292. if ( a->multiplier < +TURN_STEPS )
  293. a->multiplier++;
  294. else
  295. a->direction = up;
  296. break;
  297. case turn_down:
  298. assert (a->direction_change == 0);
  299. if ( a->multiplier > -TURN_STEPS )
  300. a->multiplier--;
  301. else
  302. a->direction = down;
  303. break;
  304. case up:
  305. assert (a->multiplier == +TURN_STEPS);
  306. assert (a->direction_change == 0);
  307. break;
  308. case down:
  309. assert (a->multiplier == -TURN_STEPS);
  310. assert (a->direction_change == 0);
  311. break;
  312. default:
  313. fprintf ( stderr, "\n\r*** Bug! ***\n");
  314. break;
  315. }
  316. a->amplitude *= 1.L + a->delta_amplitude * a->multiplier;
  317. return a->amplitude;
  318. }
  319. long double amplitude ( const amplitude_t* const a )
  320. {
  321. return a->amplitude / 32767.;
  322. }
  323. int change_direction ( amplitude_t* const a, direction_t new_direction )
  324. {
  325. switch ( new_direction ) {
  326. case up:
  327. if (a->direction == down) {
  328. a->direction = still_down;
  329. } else {
  330. fprintf ( stderr, "Direction not down, so ignored\n" );
  331. return -1;
  332. }
  333. break;
  334. case down:
  335. if (a->direction == up) {
  336. a->direction = still_up;
  337. } else {
  338. fprintf ( stderr, "Direction not up, so ignored\n" );
  339. return -1;
  340. }
  341. break;
  342. case change:
  343. switch ( a->direction ) {
  344. case up:
  345. a->direction = still_up;
  346. break;
  347. case down:
  348. a->direction = still_down;
  349. break;
  350. default:
  351. fprintf ( stderr, "Direction still changing, so ignored\n" );
  352. return -1;
  353. }
  354. break;
  355. default:
  356. fprintf ( stderr, "Direction unknown, so ignored\n" );
  357. return -1;
  358. }
  359. a->direction_change = 1 + rand () * (a->sample_freq * DELAY_UNTIL_XCHG / RAND_MAX);
  360. return 0;
  361. }
  362. int close_amplifier ( amplitude_t* const a )
  363. {
  364. return 0;
  365. }
  366. double ATH ( double freq )
  367. {
  368. static float tab [] = {
  369. /* 10.0 */ 96.69, 96.69, 96.26, 95.12,
  370. /* 12.6 */ 93.53, 91.13, 88.82, 86.76,
  371. /* 15.8 */ 84.69, 82.43, 79.97, 77.48,
  372. /* 20.0 */ 74.92, 72.39, 70.00, 67.62,
  373. /* 25.1 */ 65.29, 63.02, 60.84, 59.00,
  374. /* 31.6 */ 57.17, 55.34, 53.51, 51.67,
  375. /* 39.8 */ 50.04, 48.12, 46.38, 44.66,
  376. /* 50.1 */ 43.10, 41.73, 40.50, 39.22,
  377. /* 63.1 */ 37.23, 35.77, 34.51, 32.81,
  378. /* 79.4 */ 31.32, 30.36, 29.02, 27.60,
  379. /* 100.0 */ 26.58, 25.91, 24.41, 23.01,
  380. /* 125.9 */ 22.12, 21.25, 20.18, 19.00,
  381. /* 158.5 */ 17.70, 16.82, 15.94, 15.12,
  382. /* 199.5 */ 14.30, 13.41, 12.60, 11.98,
  383. /* 251.2 */ 11.36, 10.57, 9.98, 9.43,
  384. /* 316.2 */ 8.87, 8.46, 7.44, 7.12,
  385. /* 398.1 */ 6.93, 6.68, 6.37, 6.06,
  386. /* 501.2 */ 5.80, 5.55, 5.29, 5.02,
  387. /* 631.0 */ 4.75, 4.48, 4.22, 3.98,
  388. /* 794.3 */ 3.75, 3.51, 3.27, 3.22,
  389. /* 1000.0 */ 3.12, 3.01, 2.91, 2.68,
  390. /* 1258.9 */ 2.46, 2.15, 1.82, 1.46,
  391. /* 1584.9 */ 1.07, 0.61, 0.13, -0.35,
  392. /* 1995.3 */ -0.96, -1.56, -1.79, -2.35,
  393. /* 2511.9 */ -2.95, -3.50, -4.01, -4.21,
  394. /* 3162.3 */ -4.46, -4.99, -5.32, -5.35,
  395. /* 3981.1 */ -5.13, -4.76, -4.31, -3.13,
  396. /* 5011.9 */ -1.79, 0.08, 2.03, 4.03,
  397. /* 6309.6 */ 5.80, 7.36, 8.81, 10.22,
  398. /* 7943.3 */ 11.54, 12.51, 13.48, 14.21,
  399. /* 10000.0 */ 14.79, 13.99, 12.85, 11.93,
  400. /* 12589.3 */ 12.87, 15.19, 19.14, 23.69,
  401. /* 15848.9 */ 33.52, 48.65, 59.42, 61.77,
  402. /* 19952.6 */ 63.85, 66.04, 68.33, 70.09,
  403. /* 25118.9 */ 70.66, 71.27, 71.91, 72.60,
  404. };
  405. double freq_log;
  406. double dB;
  407. unsigned index;
  408. if ( freq < 10. ) freq = 10.;
  409. if ( freq > 25000. ) freq = 25000.;
  410. freq_log = 40. * log10 (0.1 * freq); /* 4 steps per third, starting at 10 Hz */
  411. index = (unsigned) freq_log;
  412. assert ( index < sizeof(tab)/sizeof(*tab) );
  413. dB = tab [index] * (1 + index - freq_log) + tab [index+1] * (freq_log - index);
  414. return pow ( 10., 0.05*dB );
  415. }
  416. /******************************************************************************************************
  417. * keyboard stuff
  418. ******************************************************************************************************/
  419. typedef struct {
  420. int init;
  421. struct termios stored_setting;
  422. struct termios current_setting;
  423. } keyboard_t;
  424. static keyboard_t* __k;
  425. /* Restore term-settings to those saved when term_init was called */
  426. static void term_restore (void)
  427. {
  428. tcsetattr ( 0, TCSANOW, &(__k->stored_setting) );
  429. } /* term_restore */
  430. /* Clean up terminal; called on exit */
  431. static void term_exit ( int sig )
  432. {
  433. term_restore ();
  434. } /* term_exit */
  435. /* Will be called when ctrl-Z is pressed, this correctly handles the terminal */
  436. static void term_ctrl_z ( int sig )
  437. {
  438. signal ( SIGTSTP, term_ctrl_z );
  439. term_restore ();
  440. kill ( getpid(), SIGSTOP );
  441. } /* term_ctrl_z */
  442. /* Will be called when application is continued after having been stopped */
  443. static void term_cont ( int sig )
  444. {
  445. signal ( SIGCONT, term_cont );
  446. tcsetattr ( 0, TCSANOW, &(__k->current_setting) );
  447. } /* term_cont() */
  448. int open_keyboard ( keyboard_t* const k )
  449. {
  450. __k = k;
  451. tcgetattr ( 0, &(k->stored_setting) );
  452. tcgetattr ( 0, &(k->current_setting) );
  453. signal ( SIGINT, term_exit ); /* We _must_ clean up when we exit */
  454. signal ( SIGQUIT, term_exit );
  455. signal ( SIGTSTP, term_ctrl_z ); /* Ctrl-Z must also be handled */
  456. signal ( SIGCONT, term_cont );
  457. // atexit ( term_exit );
  458. /* One or more characters are sufficient to cause a read to return */
  459. cfmakeraw ( &(k->current_setting) );
  460. k->current_setting.c_oflag |= ONLCR | OPOST; /* enables NL => CRLF on output */
  461. tcsetattr ( 0, TCSANOW, &(k->current_setting) );
  462. return 0;
  463. }
  464. int getchar_keyboard ( keyboard_t* const k )
  465. {
  466. struct timeval t;
  467. fd_set fd [1];
  468. int ret;
  469. unsigned char c;
  470. FD_SET (0, fd);
  471. t.tv_sec = 0;
  472. t.tv_usec = 0;
  473. ret = select ( 1, fd, NULL, NULL, &t );
  474. switch ( ret ) {
  475. case 0:
  476. return -1;
  477. case 1:
  478. ret = read (0, &c, 1);
  479. return ret == 1 ? c : -1;
  480. default:
  481. return -2;
  482. }
  483. }
  484. int close_keyboard ( keyboard_t* const k )
  485. {
  486. term_restore ();
  487. return 0;
  488. }
  489. /******************************************************************************************************
  490. * reporting stuff
  491. ******************************************************************************************************/
  492. int report_open ( void )
  493. {
  494. static char buff [32767];
  495. fflush ( stdout );
  496. setvbuf ( stdout, buff, _IOFBF, sizeof(buff) );
  497. return 0;
  498. }
  499. int report ( const generator_t* const g, const amplitude_t* const a )
  500. {
  501. static double last_freq = -1.;
  502. static double last_level = -1.;
  503. double freq;
  504. double level;
  505. freq = frequency (g);
  506. level = 20. * log10 (amplitude (a) * ATH (freq) ) + 80.;
  507. if ( last_freq >= 0 )
  508. printf ( "%11.3f %8.2f\n", sqrt (freq*last_freq), 0.5 * (level+last_level) );
  509. printf ( "# %9.3f %8.2f\n", freq, level );
  510. fflush ( stdout );
  511. last_freq = freq;
  512. last_level = level;
  513. return 0;
  514. }
  515. int report_close ( void )
  516. {
  517. printf ( "%%%%\n\n" );
  518. fflush ( stdout );
  519. close ( dup ( fileno(stdout) ) );
  520. setvbuf ( stdout, NULL, _IONBF, 0 );
  521. return 0;
  522. }
  523. /******************************************************************************************************
  524. * main stuff
  525. ******************************************************************************************************/
  526. typedef enum {
  527. left = 0,
  528. right = 1,
  529. phase0 = 2,
  530. both = 2,
  531. phase90 = 3,
  532. phase180 = 4,
  533. phasemod = 5
  534. } earmode_t;
  535. static long double scalar ( const double* a, const double* b )
  536. {
  537. return a[ 0]*b[ 0] + a[ 1]*b[ 1] + a[ 2]*b[ 2] + a[ 3]*b[ 3]
  538. +a[ 4]*b[ 4] + a[ 5]*b[ 5] + a[ 6]*b[ 6] + a[ 7]*b[ 7]
  539. +a[ 8]*b[ 8] + a[ 9]*b[ 9] + a[10]*b[10] + a[11]*b[11]
  540. +a[12]*b[12] + a[13]*b[13] + a[14]*b[14] + a[15]*b[15];
  541. }
  542. int experiment ( generator_t* const g,
  543. amplitude_t* const a,
  544. keyboard_t* const k,
  545. soundcard_t* const s,
  546. earmode_t earmode )
  547. {
  548. long i;
  549. int j;
  550. stereo_t samples [512];
  551. static double quant_errors [2] [16];
  552. long double val;
  553. double ampl;
  554. long ival;
  555. fprintf ( stderr, "\r+++ up +++" );
  556. for ( i = 0; i < g->duration; i += sizeof(samples)/sizeof(*samples) ) {
  557. fprintf ( stderr, "%3lu%%\b\b\b\b", i*100lu/g->duration );
  558. for (j = 0; j < sizeof(samples)/sizeof(*samples); j++ ) {
  559. ampl = iterate_amplifier (a) * ATH (frequency (g));
  560. val = ampl * iterate_generator (g);
  561. ival = (long) floor ( val + 0.5 + scalar (quant_errors[0], s->dither) );
  562. if ( ival != (sample_t) ival ) {
  563. report (g, a);
  564. fprintf ( stderr, "\rOverrun \n\n" );
  565. return -1;
  566. }
  567. memmove ( & quant_errors [0] [1], & quant_errors [0] [0],
  568. sizeof(quant_errors[0]) - sizeof(quant_errors[0][0]) );
  569. quant_errors [0] [0] = val - ival;
  570. switch ( earmode ) {
  571. case both:
  572. samples [j] [0] = samples [j] [1] = ival;
  573. break;
  574. case left:
  575. samples [j] [0] = ival;
  576. samples [j] [1] = 0;
  577. break;
  578. case right:
  579. samples [j] [0] = 0;
  580. samples [j] [1] = ival;
  581. break;
  582. case phase180:
  583. samples [j] [0] = ival == -32768 ? 32767 : -ival;
  584. samples [j] [1] = +ival;
  585. break;
  586. case phase90:
  587. samples [j] [0] = ival;
  588. val = ampl * get_cosine (g);
  589. ival = (long) floor ( val + 0.5 + scalar (quant_errors[1], s->dither) );
  590. if ( ival != (sample_t) ival ) {
  591. report (g, a);
  592. fprintf ( stderr, "\rOverrun \n\n" );
  593. return -1;
  594. }
  595. memmove ( & quant_errors [1] [1], & quant_errors [1] [0],
  596. sizeof(quant_errors[1]) - sizeof(quant_errors[1][0]) );
  597. quant_errors [1] [0] = val - ival;
  598. samples [j] [1] = ival;
  599. break;
  600. default:
  601. assert (0);
  602. return -1;
  603. }
  604. }
  605. play_soundcard ( s, samples, sizeof(samples)/sizeof(*samples) );
  606. if ( amplitude (a) * ATH (frequency (g)) <= 3.16227766e-6 ) {
  607. report (g, a);
  608. fprintf ( stderr, "\rUnderrun \n\n" );
  609. return -1;
  610. }
  611. switch ( getchar_keyboard (k) ) {
  612. case '+':
  613. fprintf ( stderr, "\r+++ up +++" );
  614. report (g, a);
  615. change_direction ( a, up );
  616. break;
  617. case '-':
  618. fprintf ( stderr, "\r--- down ---" );
  619. report (g, a);
  620. change_direction ( a, down );
  621. break;
  622. case '\r':
  623. case '\n':
  624. fprintf ( stderr, "\r** change **" );
  625. report (g, a);
  626. change_direction ( a, change );
  627. break;
  628. case 'C'&0x1F:
  629. case 'q':
  630. case 'Q':
  631. case 'x':
  632. case 'X':
  633. fprintf ( stderr, "\rBreak \n\n" );
  634. fflush ( stderr );
  635. return -1;
  636. default:
  637. fprintf ( stderr, "\a" );
  638. break;
  639. case -1:
  640. break;
  641. }
  642. }
  643. fprintf ( stderr, "\rReady \n\n" );
  644. return 0;
  645. }
  646. static void usage ( void )
  647. {
  648. static const char help[] =
  649. "'Absolute Threshold of Hearing' -- Version 0.07 (C) Frank Klemm 2000\n"
  650. "\n"
  651. "usage:\n"
  652. " ath type minfreq maxfreq duration ampl_speed [start_level [earmode] > reportfile\n"
  653. "\n"
  654. " type: linear, logarithm, square, cubic, erb, recip\n"
  655. " minfreq: initial frequency [Hz]\n"
  656. " maxfreq: end frequency [Hz]\n"
  657. " duration: duration of the experiment [s]\n"
  658. " ampl_speed: amplitude slope speed [phon/s]\n"
  659. " start_level: absolute level at startup [0...1]\n"
  660. " earmode: left, right, both, phase90, phase180\n"
  661. "\n"
  662. "example:\n"
  663. " ath erb 700 22000 600 3 0.0001 > result1\n"
  664. " ath erb 1400 16 360 3 0.0001 > result2\n"
  665. "\n"
  666. "handling:\n"
  667. " press '-' once when you start hearing a tone\n"
  668. " press '+' once when you stop hearing a tone\n"
  669. " press 'q' to early leave the program\n"
  670. " on errors the pressed key is ignored\n";
  671. fprintf ( stderr, "%s\n", help );
  672. }
  673. int main ( int argc, char** argv )
  674. {
  675. generator_t g;
  676. amplitude_t a;
  677. soundcard_t s;
  678. keyboard_t k;
  679. genmode_t genmode;
  680. earmode_t earmode;
  681. if ( argc == 1 ) {
  682. usage ();
  683. system ( "./ath erb 700 22000 600 3 0.0001 > result1" );
  684. system ( "./ath erb 1400 16 360 3 0.0001 > result2" );
  685. system ( "xmgr result1 result2 &> /dev/null &" );
  686. return 0;
  687. }
  688. if ( argc < 6 ) {
  689. usage ();
  690. return 1;
  691. }
  692. if ( 0 == strncmp ( argv[1], "li" , 2) ) genmode = linear;
  693. else if ( 0 == strncmp ( argv[1], "lo" , 2) ) genmode = logarithm;
  694. else if ( 0 == strncmp ( argv[1], "sq" , 2) ) genmode = square;
  695. else if ( 0 == strncmp ( argv[1], "cu" , 2) ) genmode = cubic;
  696. else if ( 0 == strncmp ( argv[1], "er" , 2) ) genmode = erb;
  697. else if ( 0 == strncmp ( argv[1], "re" , 2) ) genmode = recip;
  698. else {
  699. usage ();
  700. return 1;
  701. }
  702. if ( argc < 8 ) earmode = both;
  703. else if ( 0 == strncmp ( argv[7], "le" , 2) ) earmode = left;
  704. else if ( 0 == strncmp ( argv[7], "ri" , 2) ) earmode = right;
  705. else if ( 0 == strncmp ( argv[7], "bo" , 2) ) earmode = both;
  706. else if ( 0 == strncmp ( argv[7], "phase9" , 6) ) earmode = phase90;
  707. else if ( 0 == strncmp ( argv[7], "phase1" , 6) ) earmode = phase180;
  708. else {
  709. usage ();
  710. return 1;
  711. }
  712. open_soundcard ( &s, AUDIO_DEVICE, sizeof(stereo_t)/sizeof(sample_t), CHAR_BIT*sizeof(sample_t), 96000.0 );
  713. open_generator ( &g, &s, genmode, atof (argv[4]), atof (argv[2]), atof (argv[3]) );
  714. open_amplifier ( &a, &s, argc > 6 ? atof (argv[6]) : 0.0001, atof (argv[5]) );
  715. open_keyboard ( &k );
  716. report_open ( );
  717. experiment ( &g, &a, &k, &s, earmode );
  718. report_close ( );
  719. close_keyboard ( &k );
  720. close_amplifier( &a );
  721. close_generator( &g );
  722. close_soundcard( &s );
  723. return 0;
  724. }
  725. /* end of ath.c */