1
/* beepOSS.c -- Jacek M. Holeczek 3/2000 */
2
/* A lot of code taken from the beepSun.c */
5
Implementation of beep for the Open Sound System /dev/dsp device.
10
#include <sys/ioctl.h>
12
#include <sys/soundcard.h>
17
#define DEVICE_NAME "/dev/dsp"
18
#define RATE (8000) /* 8 K samples = 1 second */
19
#define RAMP (RATE * 5 / 1000) /* 5 millisecond ramp */
20
#define MAXTIME (2 * RATE) /* 2 seconds max tone time */
23
static int channels = 0; /* 1=mono, 2=stereo */
24
static unsigned char silence[2*MAXTIME];
25
static unsigned char soundbuf[2*(MAXTIME - RAMP)];
26
static unsigned char ramp_down[2*RAMP];
33
* Initialize the sound of silence
35
for (i = 0; i < 2*MAXTIME; i++)
38
audio = open(DEVICE_NAME, O_WRONLY, 0);
41
return 1; /* not o.k. */
44
i = 0x00ff0008; /* 255 fragments, 256 bytes each */
45
if (ioctl(audio, SNDCTL_DSP_SETFRAGMENT, &i))
47
fprintf(stderr, "SNDCTL_DSP_SETFRAGMENT error : 0x%08x\n", i);
51
channels = 1; /* 1 channel = mono */
52
if (ioctl(audio, SNDCTL_DSP_CHANNELS, &channels)==-1)
54
fprintf(stderr, "SNDCTL_DSP_CHANNELS error : %i\n", channels);
59
channels = 2; /* 2 channels = stereo */
60
if (ioctl(audio, SNDCTL_DSP_CHANNELS, &channels)==-1)
62
fprintf(stderr, "SNDCTL_DSP_CHANNELS error : %i\n", channels);
66
if (!(channels == 1 || channels == 2))
68
fprintf(stderr, "Neither mono nor stereo mode could be set.\n");
72
i = AFMT_U8; /* standard unsigned 8 bit audio encoding */
73
if (ioctl(audio, SNDCTL_DSP_SETFMT, &i)==-1)
75
fprintf(stderr, "SNDCTL_DSP_SETFMT error : %i\n", i);
79
i = RATE; /* sampling rate RATE */
80
if (ioctl(audio, SNDCTL_DSP_SPEED, &i)==-1)
82
fprintf(stderr, "SNDCTL_DSP_SPEED error : %i\n", i);
86
write (audio, silence, channels*2);
92
int Beep (int time, int volume, int pitch)
94
static int last_pitch = -1, last_n = -1, last_volume = -1;
95
int i, n, first_len, down_len, cycle;
99
* Finagle the number of samples
101
n = (time / 1000.) * RATE; /* Number samples in tone time */
102
n = n < MAXTIME ? n : MAXTIME; /* clip to buffer size */
103
n = n < 2 * RAMP ? 2 * RAMP : n; /* leave room for ramps */
113
write (audio, silence, channels*n);
119
* (Of course this means that if you ask for too high a frequency you
120
* just get silence, since you sample all the zero-crossings of the
123
pitch = pitch < RATE / 2 ? pitch : RATE / 2;
124
cycle = ((RATE + 1.e-6) / pitch); /* samples per cycle */
126
if (cycle > MAXTIME / 2)
129
/* round down length of (rampup + mesa top) to integral cycle */
130
first_len = ((n - RAMP) / cycle) * cycle;
131
if (first_len < cycle)
133
if (first_len > MAXTIME - RAMP)
134
first_len = MAXTIME - RAMP;
136
/* round down length of (rampdown) to integral cycle */
137
down_len = ((RAMP) / cycle) * cycle;
138
if (down_len < cycle)
144
* Can we just reuse what we had before?
146
if (pitch != last_pitch || n > last_n || volume != last_volume)
150
last_volume = volume;
152
dt = 2. * M_PI / cycle; /* sine scale factor */
154
/* Ramp up; begin with silence */
156
for (i = 0; i < RAMP; i++)
158
soundbuf[i*channels] = rint( 128. +
159
((float) i / RAMP) * (volume * 1.26) * sin (i * dt)
162
soundbuf[i*channels+1] = soundbuf[i*channels];
166
for (i = RAMP; i < first_len; i++)
168
soundbuf[i*channels] = rint( 128. +
169
1. * (volume * 1.26) * sin (i * dt)
172
soundbuf[i*channels+1] = soundbuf[i*channels];
175
/* Ramp down; end with silence */
176
for (i = 0; i < down_len; i++)
178
ramp_down[i*channels] = rint( 128. +
179
(1. - (float) (i + 1) / down_len) * (volume * 1.26) * sin (i * dt)
182
ramp_down[i*channels+1] = ramp_down[i*channels];
186
write (audio, soundbuf, channels*first_len);
187
write (audio, ramp_down, channels*down_len);
195
ioctl (audio, SNDCTL_DSP_SYNC, 0);
199
int BeepCleanup (void)
204
int BeepResume (void)