home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume41 / morse / part02 / beepHP.c < prev    next >
C/C++ Source or Header  |  1993-12-19  |  4KB  |  178 lines

  1. /* beepHP.c -- seligman 5/92 */
  2.  
  3. /*
  4. -- Implementation of beep.h for HP9000s700 with audio hardware.
  5. --
  6. -- If the environment variable SPEAKER begins with "E", the external
  7. -- audio connection is used.  If it begins with "I", the internal speaker
  8. -- is used.  Otherwise both are used.
  9. --
  10. -- Compile with the math library "-lm".
  11. */
  12.  
  13. #include "beep.h"
  14. #include "alarm.h"
  15. #include <stdlib.h>
  16. #include <stdio.h>
  17. #include <string.h>
  18. #include <ctype.h>
  19. #include <math.h>
  20. #include <fcntl.h>
  21. #include <malloc.h>
  22.  
  23.  
  24. static char *AudioDev;
  25.  
  26. static int DoBeep();
  27.  
  28.  
  29. int BeepInit()
  30. {
  31.     char *speaker = getenv("SPEAKER");
  32.     int fd;
  33.  
  34.     AudioDev =   speaker && toupper(speaker[0])=='E'  ?  "/dev/audioEL"
  35.            : speaker && toupper(speaker[0])=='I'  ?  "/dev/audioIL"
  36.            :                     "/dev/audioBL";
  37.  
  38.     /*
  39.     -- A quick check to ensure that we can open the device.
  40.     */
  41.     if ((fd = open(AudioDev, O_WRONLY)) < 0) {
  42.     perror("?? Error opening audio device");
  43.     return 1;
  44.     }
  45.     close(fd);
  46.     return 0;
  47. }
  48.  
  49.  
  50. /*
  51. -- Optimized for the case where volume & pitch don't change (except possibly
  52. -- to zero and back) between successive calls.
  53. */
  54. int Beep(time, volume, pitch)
  55.     int time, volume, pitch;
  56. {
  57.     int rc;
  58.  
  59.     AlarmWait();
  60.     if (volume != 0  &&  pitch != 0)
  61.     if ((rc = DoBeep(time, volume, pitch))  !=  0)
  62.         return rc;
  63.     AlarmSet(time);
  64.     return 0;
  65. }
  66.  
  67.  
  68. int BeepWait()
  69. {
  70.     AlarmWait();
  71.     return 0;
  72. }
  73.  
  74.  
  75. int BeepCleanup()
  76. {
  77.     return 0;
  78. }
  79.  
  80.  
  81. int BeepResume()
  82. {
  83.     return 0;
  84. }
  85.  
  86.  
  87. /*----------------------------------------*/
  88.  
  89. #define SamplingRate 8000        /* audio device samples per second */
  90. #define NumRamp (SamplingRate / 200)    /* # samples in 5ms ramp up/down */
  91.  
  92. typedef short int Sample;
  93. #define MaxSample (Sample)0x7FFF
  94.  
  95.  
  96. /*
  97. -- Sound a beep.
  98. -- Optimized for the case where volume & pitch don't change between successive
  99. -- calls.
  100. */
  101. static int DoBeep(time, volume, pitch)
  102.     int time, volume, pitch;
  103. {
  104.     static int audioDevFD = -1;  /* -1 indicates not yet open. */
  105.  
  106.     /* Save sample buffer from call to call, and reuse it when possible. */
  107.     static Sample *buf = NULL;
  108.     static int bufLen    = 0;
  109.     static int bufVolume = 0;
  110.     static int bufPitch  = 0;
  111.  
  112.     Sample rampbuf[NumRamp];  /* Sample buffer for ramp-down. */
  113.  
  114.     /* Are volume and pitch same as previous call? */
  115.     int sameVP  =  (volume == bufVolume  &&  pitch == bufPitch);
  116.  
  117.     int i, j;
  118.     int numSamples = SamplingRate * time / 1000;
  119.  
  120.     /*
  121.     -- It seems that the first write to the audio device after it's
  122.     -- been opened must be the longest.
  123.     */
  124.     if (numSamples > bufLen) {
  125.     if (audioDevFD >= 0) close(audioDevFD);
  126.     audioDevFD = -1;
  127.     }
  128.     if (audioDevFD < 0) {
  129.     if ((audioDevFD = open(AudioDev, O_WRONLY)) < 0) {
  130.         perror("?? Error opening audio device");
  131.         return 1;
  132.     }
  133.     }
  134.  
  135.     /*
  136.     -- Allocate space for sample buffer.  Set "i" to lowest index in
  137.     -- need of updating.
  138.     */
  139.     i = sameVP ? bufLen : 0;
  140.     if (numSamples > bufLen) {
  141.     if (sameVP) {
  142.         buf = realloc(buf, numSamples * sizeof(Sample));
  143.     } else {
  144.         if (buf != NULL) free(buf);
  145.         bufVolume = volume;
  146.         bufPitch  = pitch;
  147.         buf = malloc(numSamples * sizeof(Sample));
  148.     }
  149.     if (buf == NULL) {
  150.         fprintf(stderr, "?? Buy more memory.\n");
  151.         return 1;
  152.     }
  153.     bufLen = numSamples;
  154.     }
  155.  
  156.     /*
  157.     -- Update any newly-allocated tail of sample buffer.  The ramp-up is
  158.     -- handled here (since it always occurs at the same place); the ramp-down
  159.     -- is handled later.
  160.     */
  161.     while (i < bufLen) {
  162.     double rampScale  =  (i < NumRamp)  ?  (double) i / NumRamp  :  1;
  163.     double t = (double) i / SamplingRate;
  164.     buf[i++] =
  165.         sin(2 * M_PI * pitch * t) * MaxSample * rampScale * volume / 100;
  166.     }
  167.  
  168.     /* Sound the beep, except for the ramp-down. */
  169.     write(audioDevFD, buf, (numSamples - NumRamp) * sizeof(Sample));
  170.  
  171.     /* Ramp-down */
  172.     for (i = 0, j = numSamples-NumRamp;  i < NumRamp;  i++, j++)
  173.     rampbuf[i] = buf[j] * ((double) (NumRamp - i) / NumRamp);
  174.     write(audioDevFD, rampbuf, sizeof rampbuf);
  175.  
  176.     return 0;
  177. }
  178.