~ubuntu-branches/ubuntu/edgy/morse/edgy

« back to all changes in this revision

Viewing changes to morse.d/beepOSS.c

  • Committer: Bazaar Package Importer
  • Author(s): Joop Stakenborg
  • Date: 2006-03-18 09:47:15 UTC
  • Revision ID: james.westby@ubuntu.com-20060318094715-h2sjf5b7iufaz9ov
Tags: upstream-2.1
ImportĀ upstreamĀ versionĀ 2.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* beepOSS.c -- Jacek M. Holeczek 3/2000 */
 
2
/* A lot of code taken from the beepSun.c */
 
3
 
 
4
/*
 
5
  Implementation of beep for the Open Sound System /dev/dsp device.
 
6
*/
 
7
 
 
8
#include <stdio.h>
 
9
#include <unistd.h>
 
10
#include <sys/ioctl.h>
 
11
#include <fcntl.h>
 
12
#include <sys/soundcard.h>
 
13
#include <math.h>
 
14
 
 
15
#include "beep.h"
 
16
 
 
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 */
 
21
 
 
22
static int audio = 0;
 
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];
 
27
 
 
28
int BeepInit (void)
 
29
{
 
30
  int i;
 
31
  
 
32
  /*
 
33
   * Initialize the sound of silence
 
34
   */
 
35
  for (i = 0; i < 2*MAXTIME; i++)
 
36
    silence[i] = 128;
 
37
  
 
38
  audio = open(DEVICE_NAME, O_WRONLY, 0);
 
39
  if (audio < 0)
 
40
    {
 
41
      return 1; /* not o.k. */
 
42
    } else {
 
43
      
 
44
      i = 0x00ff0008; /* 255 fragments, 256 bytes each */
 
45
      if (ioctl(audio, SNDCTL_DSP_SETFRAGMENT, &i))
 
46
        {
 
47
          fprintf(stderr, "SNDCTL_DSP_SETFRAGMENT error : 0x%08x\n", i);
 
48
          return 2;
 
49
        }
 
50
      
 
51
      channels = 1; /* 1 channel = mono */
 
52
      if (ioctl(audio, SNDCTL_DSP_CHANNELS, &channels)==-1)
 
53
        {
 
54
          fprintf(stderr, "SNDCTL_DSP_CHANNELS error : %i\n", channels);
 
55
          return 3;
 
56
        }
 
57
      if (channels != 1)
 
58
        {
 
59
          channels = 2; /* 2 channels = stereo */
 
60
          if (ioctl(audio, SNDCTL_DSP_CHANNELS, &channels)==-1)
 
61
            {
 
62
              fprintf(stderr, "SNDCTL_DSP_CHANNELS error : %i\n", channels);
 
63
              return 4;
 
64
            }
 
65
        }
 
66
      if (!(channels == 1 || channels == 2))
 
67
        {
 
68
          fprintf(stderr, "Neither mono nor stereo mode could be set.\n");
 
69
          return 5;
 
70
        }
 
71
      
 
72
      i = AFMT_U8; /* standard unsigned 8 bit audio encoding */
 
73
      if (ioctl(audio, SNDCTL_DSP_SETFMT, &i)==-1)
 
74
        {
 
75
          fprintf(stderr, "SNDCTL_DSP_SETFMT error : %i\n", i);
 
76
          return 6;
 
77
        }
 
78
      
 
79
      i = RATE; /* sampling rate RATE */
 
80
      if (ioctl(audio, SNDCTL_DSP_SPEED, &i)==-1)
 
81
        {
 
82
          fprintf(stderr, "SNDCTL_DSP_SPEED error : %i\n", i);
 
83
          return 7;
 
84
        }
 
85
      
 
86
      write (audio, silence, channels*2);
 
87
      BeepWait();
 
88
      return 0; /* o.k. */
 
89
    }
 
90
}
 
91
 
 
92
int Beep (int time, int volume, int pitch)
 
93
{
 
94
  static int      last_pitch = -1, last_n = -1, last_volume = -1;
 
95
  int             i, n, first_len, down_len, cycle;
 
96
  double          dt;
 
97
  
 
98
  /*
 
99
   * Finagle the number of samples
 
100
   */
 
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 */
 
104
  
 
105
  /*
 
106
   * Catch stupidity
 
107
   */
 
108
  if (pitch <= 0)
 
109
    volume = 0;
 
110
  
 
111
  if (volume <= 0)
 
112
    {
 
113
      write (audio, silence, channels*n);
 
114
    }
 
115
  else
 
116
    {
 
117
      /*
 
118
       * clip to Nyquist
 
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
 
121
       * sine wave.)
 
122
       */
 
123
      pitch = pitch < RATE / 2 ? pitch : RATE / 2;
 
124
      cycle = ((RATE + 1.e-6) / pitch); /* samples per cycle */
 
125
      
 
126
      if (cycle > MAXTIME / 2)
 
127
        cycle = MAXTIME / 2;
 
128
      
 
129
      /* round down length of (rampup + mesa top) to integral cycle */
 
130
      first_len = ((n - RAMP) / cycle) * cycle;
 
131
      if (first_len < cycle)
 
132
        first_len = cycle;
 
133
      if (first_len > MAXTIME - RAMP)
 
134
        first_len = MAXTIME - RAMP;
 
135
      
 
136
      /* round down length of (rampdown) to integral cycle */
 
137
      down_len = ((RAMP) / cycle) * cycle;
 
138
      if (down_len < cycle)
 
139
        down_len = cycle;
 
140
      if (down_len > RAMP)
 
141
        down_len = RAMP;
 
142
      
 
143
      /*
 
144
       * Can we just reuse what we had before?
 
145
       */
 
146
      if (pitch != last_pitch || n > last_n || volume != last_volume)
 
147
        {
 
148
          last_pitch = pitch;
 
149
          last_n = n;
 
150
          last_volume = volume;
 
151
          
 
152
          dt = 2. * M_PI / cycle;       /* sine scale factor */
 
153
          
 
154
          /* Ramp up; begin with silence */
 
155
          
 
156
          for (i = 0; i < RAMP; i++)
 
157
            {
 
158
              soundbuf[i*channels] = rint( 128. +
 
159
                                           ((float) i / RAMP) * (volume * 1.26) * sin (i * dt)
 
160
                                           );
 
161
              if (channels == 2)
 
162
                soundbuf[i*channels+1] = soundbuf[i*channels];
 
163
            }
 
164
          
 
165
          /* Mesa top */
 
166
          for (i = RAMP; i < first_len; i++)
 
167
            {
 
168
              soundbuf[i*channels] = rint( 128. +
 
169
                                           1. * (volume * 1.26) * sin (i * dt)
 
170
                                           );
 
171
              if (channels == 2)
 
172
                soundbuf[i*channels+1] = soundbuf[i*channels];
 
173
            }
 
174
          
 
175
          /* Ramp down; end with silence */
 
176
          for (i = 0; i < down_len; i++)
 
177
            {
 
178
              ramp_down[i*channels] = rint( 128. +
 
179
                                            (1. - (float) (i + 1) / down_len) * (volume * 1.26) * sin (i * dt)
 
180
                                            );
 
181
              if (channels == 2)
 
182
                ramp_down[i*channels+1] = ramp_down[i*channels];
 
183
            }
 
184
        }
 
185
      
 
186
      write (audio, soundbuf, channels*first_len);
 
187
      write (audio, ramp_down, channels*down_len);
 
188
    }
 
189
  
 
190
  return 0;
 
191
}
 
192
 
 
193
int BeepWait (void)
 
194
{
 
195
  ioctl (audio, SNDCTL_DSP_SYNC, 0);
 
196
  return 0;
 
197
}
 
198
 
 
199
int BeepCleanup (void)
 
200
{
 
201
  return 0;
 
202
}
 
203
 
 
204
int BeepResume (void)
 
205
{
 
206
  return 0;
 
207
}