home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume41 / morse / part01 / beepSun.c next >
Encoding:
C/C++ Source or Header  |  1993-12-19  |  4.2 KB  |  202 lines

  1. /*
  2.  * If the audio library or audio include files are missing, you need
  3.  * to get /usr/demo/SOUND off the Sun OS tapes or CD.
  4.  *
  5.  * If FULLVOLUME is defined this routine will turn your audio device up to
  6.  * full volume; it will not attempt to reset the current speaker / jack choice.
  7.  *
  8.  * The sun speaker has a residual "click" each time it switches from
  9.  * silence to tone that I am unable to rid it of. The loudness of the "click"
  10.  * varies from one sun model to another.
  11.  */
  12.  
  13. /* beepSun.c -- seligman 6/92 */
  14.  
  15. /*
  16. -- Implementation of beep.h for Sun.
  17. -- Rick to Joe to Scott to Joe.
  18. */
  19.  
  20. /* Date: Fri, 2 Aug 91 08:26:08 PDT */
  21. /* From: rick@st.unocal.com (Richard Ottolini) */
  22.  
  23. /* Revised: Joe Dellinger */
  24. /* Sat Nov 28 02:30:32 HST 1992 */
  25.  
  26. #include "beep.h"
  27. #include <sun/audioio.h>
  28. #include </usr/demo/SOUND/multimedia/libaudio.h>
  29. #include </usr/demo/SOUND/multimedia/ulaw2linear.h>
  30. #include <stropts.h>
  31. #include <math.h>
  32. #include <fcntl.h>
  33.  
  34.  
  35. #define RATE    (8000)    /* 8 K samples = 1 second */
  36. #define RAMP    (RATE * 10 / 1000)    /* 10 millisecond ramp */
  37. #define MAXTIME    (2 * RATE)    /* 2 seconds max tone time */
  38.  
  39. static int      audio;
  40. static audio_info_t audio_stat;
  41.  
  42. int
  43. BeepInit ()
  44. {
  45.     audio = open ("/dev/audio", O_WRONLY);
  46.  
  47.     if (audio < 0)
  48.     /* Uh oh! */
  49.     return 1;
  50.     else
  51.     {
  52. #ifdef FULLVOLUME
  53.     /*
  54.      * Turn the speaker (or headphone, whichever the user has it set to)
  55.      * up to full volume.
  56.      */
  57.     ioctl (audio, AUDIO_GETINFO, &audio_stat);
  58.     audio_stat.play.gain = AUDIO_MAX_GAIN;
  59.     ioctl (audio, AUDIO_SETINFO, &audio_stat);
  60. #endif
  61.  
  62.     return 0;
  63.     }
  64. }
  65.  
  66.  
  67. int
  68. Beep (time, volume, pitch)
  69.     int             time, volume, pitch;
  70. {
  71. static unsigned char silence[MAXTIME];
  72. static unsigned char soundbuf[MAXTIME - RAMP];
  73. static unsigned char ramp_down[RAMP];
  74. static int      last_pitch = -1, last_n = -1, last_volume = -1;
  75. static int      first_time = 1;
  76.  
  77. int             i, n, first_len, down_len, cycle;
  78. double          dt;
  79.  
  80. /*
  81.  * Initialize the sound of silence
  82.  */
  83.     if (first_time == 1)
  84.     {
  85.     for (i = 0; i < MAXTIME; i++)
  86.         silence[i] = (unsigned char) 0;
  87.     first_time = 0;
  88.     }
  89.  
  90.  
  91. /*
  92.  * Finagle the number of samples
  93.  */
  94.     n = (time / 1000.) * RATE;    /* Number samples in tone time */
  95.     n = n < MAXTIME ? n : MAXTIME;    /* clip to buffer size */
  96.     n = n < 2 * RAMP ? 2 * RAMP : n;    /* leave room for ramps */
  97.  
  98. /*
  99.  * Catch stupidity
  100.  */
  101.     if (pitch <= 0)
  102.     volume = 0;
  103.  
  104.  
  105.     if (volume <= 0)
  106.     {
  107.     write (audio, silence, n);
  108.     }
  109.     else
  110.     {
  111. /*
  112.  * clip to Nyquist
  113.  * (Of course this means that if you ask for too high a frequency you
  114.  * just get silence, since you sample all the zero-crossings of the
  115.  * sine wave.)
  116.  */
  117.     pitch = pitch < RATE / 2 ? pitch : RATE / 2;
  118.     cycle = ((RATE + 1.e-6) / pitch);    /* samples per cycle */
  119.  
  120.     if (cycle > MAXTIME / 2)
  121.         cycle = MAXTIME / 2;
  122.  
  123.     /* round down length of (rampup + mesa top) to integral cycle */
  124.     first_len = ((n - RAMP) / cycle) * cycle;
  125.     if (first_len < cycle)
  126.         first_len = cycle;
  127.     if (first_len > MAXTIME - RAMP)
  128.         first_len = MAXTIME - RAMP;
  129.  
  130.     /* round down length of (rampdown) to integral cycle */
  131.     down_len = ((RAMP) / cycle) * cycle;
  132.     if (down_len < cycle)
  133.         down_len = cycle;
  134.     if (down_len > RAMP)
  135.         down_len = RAMP;
  136.  
  137. /*
  138.  * Can we just reuse what we had before?
  139.  */
  140.     if (pitch != last_pitch || n > last_n || volume != last_volume)
  141.     {
  142.         last_pitch = pitch;
  143.         last_n = n;
  144.         last_volume = volume;
  145.  
  146.         dt = 2. * M_PI / cycle;    /* sine scale factor */
  147.  
  148. /* Ramp up; begin with silence */
  149.  
  150.         for (i = 0; i < RAMP; i++)
  151.         {
  152.         soundbuf[i] = audio_l2u (audio_d2l (
  153.              ((float) i / RAMP) * (volume / 100.) * sin (i * dt)
  154.                             ));
  155.         }
  156.  
  157. /* Mesa top */
  158.         for (i = RAMP; i < first_len; i++)
  159.         {
  160.         soundbuf[i] = audio_l2u (audio_d2l (
  161.                      1. * (volume / 100.) * sin (i * dt)
  162.                             ));
  163.         }
  164.  
  165. /* Ramp down; end with silence */
  166.         for (i = 0; i < down_len; i++)
  167.         {
  168.         ramp_down[i] = audio_l2u (audio_d2l (
  169.                              (1. - (float) (i + 1) / down_len) * (volume / 100.) * sin (i * dt)
  170.                              ));
  171.         }
  172.     }
  173.  
  174.     write (audio, soundbuf, first_len);
  175.     write (audio, ramp_down, down_len);
  176.     }
  177.  
  178.     return 0;
  179. }
  180.  
  181.  
  182. int
  183. BeepWait ()
  184. {
  185.     ioctl (audio, AUDIO_DRAIN);
  186.     return 0;
  187. }
  188.  
  189.  
  190. int
  191. BeepCleanup ()
  192. {
  193.     return 0;
  194. }
  195.  
  196.  
  197. int
  198. BeepResume ()
  199. {
  200.     return 0;
  201. }
  202.