home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
misc
/
volume41
/
morse
/
part02
/
beepHP.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-12-19
|
4KB
|
178 lines
/* beepHP.c -- seligman 5/92 */
/*
-- Implementation of beep.h for HP9000s700 with audio hardware.
--
-- If the environment variable SPEAKER begins with "E", the external
-- audio connection is used. If it begins with "I", the internal speaker
-- is used. Otherwise both are used.
--
-- Compile with the math library "-lm".
*/
#include "beep.h"
#include "alarm.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#include <fcntl.h>
#include <malloc.h>
static char *AudioDev;
static int DoBeep();
int BeepInit()
{
char *speaker = getenv("SPEAKER");
int fd;
AudioDev = speaker && toupper(speaker[0])=='E' ? "/dev/audioEL"
: speaker && toupper(speaker[0])=='I' ? "/dev/audioIL"
: "/dev/audioBL";
/*
-- A quick check to ensure that we can open the device.
*/
if ((fd = open(AudioDev, O_WRONLY)) < 0) {
perror("?? Error opening audio device");
return 1;
}
close(fd);
return 0;
}
/*
-- Optimized for the case where volume & pitch don't change (except possibly
-- to zero and back) between successive calls.
*/
int Beep(time, volume, pitch)
int time, volume, pitch;
{
int rc;
AlarmWait();
if (volume != 0 && pitch != 0)
if ((rc = DoBeep(time, volume, pitch)) != 0)
return rc;
AlarmSet(time);
return 0;
}
int BeepWait()
{
AlarmWait();
return 0;
}
int BeepCleanup()
{
return 0;
}
int BeepResume()
{
return 0;
}
/*----------------------------------------*/
#define SamplingRate 8000 /* audio device samples per second */
#define NumRamp (SamplingRate / 200) /* # samples in 5ms ramp up/down */
typedef short int Sample;
#define MaxSample (Sample)0x7FFF
/*
-- Sound a beep.
-- Optimized for the case where volume & pitch don't change between successive
-- calls.
*/
static int DoBeep(time, volume, pitch)
int time, volume, pitch;
{
static int audioDevFD = -1; /* -1 indicates not yet open. */
/* Save sample buffer from call to call, and reuse it when possible. */
static Sample *buf = NULL;
static int bufLen = 0;
static int bufVolume = 0;
static int bufPitch = 0;
Sample rampbuf[NumRamp]; /* Sample buffer for ramp-down. */
/* Are volume and pitch same as previous call? */
int sameVP = (volume == bufVolume && pitch == bufPitch);
int i, j;
int numSamples = SamplingRate * time / 1000;
/*
-- It seems that the first write to the audio device after it's
-- been opened must be the longest.
*/
if (numSamples > bufLen) {
if (audioDevFD >= 0) close(audioDevFD);
audioDevFD = -1;
}
if (audioDevFD < 0) {
if ((audioDevFD = open(AudioDev, O_WRONLY)) < 0) {
perror("?? Error opening audio device");
return 1;
}
}
/*
-- Allocate space for sample buffer. Set "i" to lowest index in
-- need of updating.
*/
i = sameVP ? bufLen : 0;
if (numSamples > bufLen) {
if (sameVP) {
buf = realloc(buf, numSamples * sizeof(Sample));
} else {
if (buf != NULL) free(buf);
bufVolume = volume;
bufPitch = pitch;
buf = malloc(numSamples * sizeof(Sample));
}
if (buf == NULL) {
fprintf(stderr, "?? Buy more memory.\n");
return 1;
}
bufLen = numSamples;
}
/*
-- Update any newly-allocated tail of sample buffer. The ramp-up is
-- handled here (since it always occurs at the same place); the ramp-down
-- is handled later.
*/
while (i < bufLen) {
double rampScale = (i < NumRamp) ? (double) i / NumRamp : 1;
double t = (double) i / SamplingRate;
buf[i++] =
sin(2 * M_PI * pitch * t) * MaxSample * rampScale * volume / 100;
}
/* Sound the beep, except for the ramp-down. */
write(audioDevFD, buf, (numSamples - NumRamp) * sizeof(Sample));
/* Ramp-down */
for (i = 0, j = numSamples-NumRamp; i < NumRamp; i++, j++)
rampbuf[i] = buf[j] * ((double) (NumRamp - i) / NumRamp);
write(audioDevFD, rampbuf, sizeof rampbuf);
return 0;
}