home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / listings / v_01_02 / clune.exe / SOUND.C < prev    next >
Text File  |  1989-08-23  |  6KB  |  274 lines

  1.  
  2. /* read_timer() added 1/89 by T Clune.  read_timer() returns the time in */
  3. /* 1/100ths seconds (WARNING: precision more like 1/10 sec), for use in */
  4. /* measuring elapsed time to less than the C library 1-sec intervals. */
  5. /* The read_timer() return value is an unsigned long int. */
  6.  
  7. /* sound.c has six public functions: sound(), which makes a sound on the */
  8. /* IBM PC speaker at a given frequency for a specified number of seconds, */
  9. /* beep_beep(), which makes two beeps for a positive reinforcement signal, */
  10. /* blaat(), which makes a long, low negative reinforcement signal, */
  11. /* ready_beep(), which makes a single beep followed by a delay and is */
  12. /* used to alert patients that a stimulus is about to be presented to them */
  13. /* pause(), which generates a delay of user-specifiable duration, and */
  14. /* error_msg(), which is a generic "Invalid entry" function w/ sound effects */
  15. /* Written by Thomas Clune, 1/88.  Copyright 1988, Eye Research Institute */
  16. /* 20 Staniford St., Boston, MA 02114.  All Rights Reserved */
  17.  
  18.  
  19. #include <stdio.h>
  20. #include <conio.h>  /* inp(), outp() declarations */
  21. #include <dos.h>    /* intdos() declaration */
  22. #include "sound.h"      /* declarations for the public functions of sound.c */
  23.  
  24.     /* the local functions declarations */
  25.  
  26. static int get_time(), get_clock_edge();
  27.  
  28.  
  29. /* alternate_warning_sound() is a function for producing a warning that */
  30. /* sounds different from the mouse_warning_sound().  The various warning */
  31. /* sounds are collected in this file instead of being spread out over the */
  32. /* calling functions and just using sound() so that I can maintain control */
  33. /* over what frequencies have been used for various effects.  This sound */
  34. /* is being used with the SLO to signal a patient that (s)he is holding */
  35. /* down the patient response button at an inappropriate time */
  36.  
  37. void alternate_warning_sound()
  38. {
  39.     sound(600,0.1);
  40.  
  41. }
  42.  
  43.  
  44. /* beep_beep() is intended for use as the "correct answer" beep */
  45.  
  46. void beep_beep()
  47. {
  48.     sound(900,0.1);
  49.     pause(0.2);
  50.     sound(900,0.1);
  51.  
  52. }
  53.  
  54.  
  55.  
  56.  
  57. /* blaat() is intended for use as a "wrong answer" beep */
  58.  
  59. void blaat()
  60. {
  61.     sound(100,0.4);
  62. }
  63.  
  64.  
  65.  
  66.  
  67.  
  68.  
  69.  
  70.  
  71. /* error_msg() is the generic "wrong entry" function */
  72.  
  73. void error_msg()
  74. {
  75.     sound(200, 0.4);
  76.     printf("Not a valid entry\n");
  77. }
  78.  
  79.  
  80.  
  81.  
  82.  
  83. /* mouse_warning_sound() is the error sound for holding down a mouse button */
  84. /* when it should be free */
  85.  
  86. void mouse_warning_sound()
  87. {
  88.     sound(1200, 0.1);
  89. }
  90.  
  91.  
  92.  
  93.  
  94.  
  95.  
  96. /* pause() waits DURATION seconds (resolvable to 1/18.2 sec increments) */
  97.  
  98. void pause(duration)
  99. double duration;
  100. {
  101.     int time;
  102.     int dur_int;    /* duration as an integer */
  103.     int count=0;
  104.  
  105.     dur_int=(int)((duration*18.2)+0.5);
  106.  
  107.     if(dur_int<1)
  108.     dur_int=1;
  109.  
  110.     do
  111.     {
  112.     time = get_time();
  113.     while(get_time() == time)
  114.         ;
  115.     count++;
  116.     }while(count<dur_int);
  117.  
  118. }
  119.  
  120.  
  121.  
  122.  
  123.  
  124.  
  125. /* read_timer() reads the IBM timer to .05 seconds.  Value returned is hundredths */
  126. /* of seconds. Added 1/89 by T Clune. */
  127.  
  128. unsigned long int read_timer()
  129. {
  130.  
  131.     union REGS inregs, outregs;     /* as per dos.h */
  132.     unsigned long int ret_time;
  133.  
  134.     inregs.h.ah = 0X2C;     /* function call specifies read DOS clock */
  135.     intdos(&inregs, &outregs); /* call time of day interrupt */
  136.  
  137.     ret_time=outregs.h.ch*360000L+outregs.h.cl*6000+outregs.h.dh*100+outregs.h.dl;
  138.     return ret_time;
  139.  
  140. }
  141.  
  142.  
  143.  
  144.  
  145.  
  146.  
  147.  
  148.  
  149. /* ready_beep() provides an alerting signal to the patient that a stimulus */
  150. /* is about to be presented */
  151.  
  152. void ready_beep(on_time, pause_time)
  153. double on_time, pause_time;
  154. {
  155.     sound(800, on_time);
  156.     pause(pause_time);
  157.  
  158. }
  159.  
  160.  
  161.  
  162.  
  163.  
  164.  
  165. /* sound() is the basic function for producing a sound of given freq & duration */
  166.  
  167.  
  168. void sound(freq, persistance)
  169. unsigned int freq;
  170. double persistance;
  171. {
  172.     unsigned char reading;  /* value of 8255 PIA register before enabling 8253 */
  173.     unsigned long int base_freq=1190000; /* clock freq of AT counter */
  174.  
  175.     union               /* bytes/int conversion union.  Port expects bytes */
  176.     {                   /* and count is calculated as an INT */
  177.     struct
  178.     {
  179.         unsigned char low;
  180.         unsigned char high;
  181.     } byte;
  182.  
  183.     int val;
  184.  
  185.     } count;
  186.  
  187.     count.val=base_freq/freq; /* timer count to achieve the freq */
  188.  
  189.  
  190.     /* port b of the 8255 enables and disables access to the 8253 */
  191.     /* counter timer, which generates the square wave output for the */
  192.     /* speaker using channel 2.  See Programmer's Problem Solver, p. 46-48 */
  193.     /* and p.72-73.  Program is based on the low-level routine */
  194.     /* on pages 72 and 73. */
  195.  
  196.     reading=inp(0x61); /* read contents of 8255 PIA */
  197.     outp(0x61, (reading|3)); /* the 2 low bits ON allow access to the 8253 */
  198.  
  199.         /* hex 43 is the command register of the 8253 */
  200.     outp(0x43, 0xb6);   /* 2-byte data, reload from load, binary data */
  201.             /* see p. 48 for bit significances */
  202.  
  203.         /* hex 42 is the data register for chan 2 of the 8253 */
  204.     outp(0x42,count.byte.low);
  205.     outp(0x42,count.byte.high);
  206.  
  207.     pause(persistance);
  208.  
  209.     reading=inp(0x61);
  210.     outp(0x61, (reading & 0xfc));    /* just turn off 2 lsbs */
  211.  
  212.  
  213. }
  214.  
  215.  
  216.  
  217.  
  218.  
  219.  
  220. /* get_clock_edge() is like get_time(), only it waits for a clock tick to return */
  221.  
  222. static int get_clock_edge()
  223.  
  224. {
  225.  
  226.     union REGS inregs, outregs;     /* as per dos.h */
  227.     int ret_time;
  228.  
  229.     inregs.h.ah = 0X2C;     /* function call specifies read DOS clock */
  230.  
  231.     intdos(&inregs, &outregs); /* call time of day interrupt */
  232.  
  233.     ret_time=outregs.h.dl;  /* mark current reading */
  234.  
  235.         /* wait for it to change */
  236.     do
  237.     {
  238.         intdos(&inregs, &outregs); /* call time of day interrupt */
  239.     }while(ret_time==outregs.h.dl);
  240.  
  241.     ret_time=outregs.h.dh*100+outregs.h.dl;
  242.     return ret_time;
  243.  
  244. }
  245.  
  246.  
  247.  
  248.  
  249.  
  250.  
  251.  
  252.  
  253. /* get_time() is the local basic clock-reading software INT. */
  254. /* It just reads seconds and 100ths of seconds, and returns the count */
  255. /* of hundredths of seconds+seconds of the current time (max 5999) */
  256.  
  257.  
  258. static int get_time()
  259.  
  260. {
  261.  
  262.     union REGS inregs, outregs;     /* as per dos.h */
  263.     int ret_time;
  264.  
  265.     inregs.h.ah = 0X2C;     /* function call specifies read DOS clock */
  266.     intdos(&inregs, &outregs); /* call time of day interrupt */
  267.  
  268.     ret_time=outregs.h.dh*100+outregs.h.dl;
  269.     return ret_time;
  270.  
  271. }
  272.  
  273.  
  274.