~ubuntu-branches/ubuntu/oneiric/oss4/oneiric-proposed

« back to all changes in this revision

Viewing changes to tutorials/sndkit/morse/morse.c

  • Committer: Bazaar Package Importer
  • Author(s): Stefano Rivera
  • Date: 2011-06-16 20:37:48 UTC
  • mfrom: (5.1.3 sid)
  • Revision ID: james.westby@ubuntu.com-20110616203748-jbrxik6ql33z54co
Tags: 4.2-build2004-1ubuntu1
* Merge from Debian unstable.
  - Supports our current kernel (LP: #746048)
  Remaining changes:
  - debian/oss4-dkms.dkms.in: s/source/build/ in Kernel headers paths.
* ld-as-needed.patch: Re-order CC arguments to enable building with ld
  --as-needed (LP: #770972)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Purpose: Simple audio programming example that plays morse code.
 
3
 * Copyright (C) 4Front Technologies, 2002-2004. Released under GPLv2/CDDL.
 
4
 *
 
5
 * Description:
 
6
 * This program reads stdin and plays the input to an audio device using morse
 
7
 * code. The stdin input is supposed to be originated from a file. This
 
8
 * program is not capable to play live keyboard input.
 
9
 *
 
10
 * This is a great OSS programming example because it shows how simple
 
11
 * audio programming can be with OSS.
 
12
 *
 
13
 * You can use this program as a template. Just replace the
 
14
 * while loop of the main routine by your own code.
 
15
 *
 
16
 * The {!nlink morse2.c} and {!nlink morse3.c} programs are more complex
 
17
 * versions of the same program. They demonstrate how the {!nlink select}
 
18
 * system call can be used for serving the audio device in parallel 
 
19
 * while handling terminal input.
 
20
 *
 
21
 * This program was tuned to be used when practising for the 
 
22
 * finnish morse code test for radio amateurs. It supports the
 
23
 * scandinavian version of the morse code alphabet used in this test.
 
24
 */
 
25
#include <stdio.h>
 
26
#include <unistd.h>
 
27
#include <stdlib.h>
 
28
#include <string.h>
 
29
#include <fcntl.h>
 
30
#include <sys/soundcard.h>
 
31
#include <math.h>
 
32
#include <signal.h>
 
33
#include <sys/time.h>
 
34
#include <sys/types.h>
 
35
 
 
36
#define BUFSZ (16*1024)
 
37
#define SRATE 48000
 
38
#define ATTACK 100
 
39
#define CHARDELAY 3
 
40
 
 
41
int charspeed = 25;
 
42
 
 
43
int dotsize, charsize;
 
44
int audiofd = -1;
 
45
 
 
46
char randomlist[256];
 
47
int nrandom;
 
48
 
 
49
static int ncodes;
 
50
 
 
51
double a, step;
 
52
 
 
53
/*
 
54
 * The genpulse() routine converts generates a single dot, dash or
 
55
 * a pause between the symbols. this is done by generating sine wave 
 
56
 * (using cos()). It's pretty slow but works for us.
 
57
 */
 
58
#include "charlist.h"
 
59
 
 
60
static int
 
61
genpulse (short *buf, int w, int state)
 
62
{
 
63
  int i, l;
 
64
  a = 0.0;
 
65
 
 
66
  l = w * dotsize;
 
67
 
 
68
  for (i = 0; i < ATTACK; i++)
 
69
    {
 
70
      double tmp = 0x7fff * cos (a * M_PI / 180.0);
 
71
      tmp *= (double) (i) / (double) ATTACK;
 
72
 
 
73
      *buf++ = (int) tmp *state;
 
74
 
 
75
      a += step;
 
76
      if (a > 360.0)
 
77
        a -= 360.0;
 
78
    }
 
79
 
 
80
  for (i = ATTACK; i < l - ATTACK; i++)
 
81
    {
 
82
      double tmp = 0x7fff * cos (a * M_PI / 180.0);
 
83
 
 
84
      *buf++ = (int) tmp *state;
 
85
 
 
86
      a += step;
 
87
      if (a > 360.0)
 
88
        a -= 360.0;
 
89
    }
 
90
 
 
91
  for (i = l - ATTACK; i < l; i++)
 
92
    {
 
93
      double tmp = 0x7fff * cos (a * M_PI / 180.0);
 
94
 
 
95
      tmp *= (double) (l - i) / (double) ATTACK;
 
96
 
 
97
      *buf++ = (int) tmp *state;
 
98
 
 
99
      a += step;
 
100
      if (a > 360.0)
 
101
        a -= 360.0;
 
102
    }
 
103
 
 
104
  return l;
 
105
}
 
106
 
 
107
/*
 
108
 * The genmorse() routine converts an ASCII character to the
 
109
 * equivivalent audio morse code signal.
 
110
 */
 
111
static int
 
112
genmorse (short *buf, char c)
 
113
{
 
114
  int l = 0, i;
 
115
  const char *s;
 
116
 
 
117
  //printf("%c", c);
 
118
  //fflush(stdout);
 
119
 
 
120
  if (c == ' ')
 
121
    return genpulse (buf, 4, 0);
 
122
 
 
123
  for (i = 0; i < ncodes; i++)
 
124
    if (Chars[i] == c)
 
125
      {
 
126
        s = Codes[i];
 
127
 
 
128
        while (*s)
 
129
          {
 
130
            if (*s++ == '.')
 
131
              l += genpulse (&buf[l], 1, 1);
 
132
            else
 
133
              l += genpulse (&buf[l], 3, 1);
 
134
 
 
135
            l += genpulse (&buf[l], 1, 0);
 
136
          }
 
137
 
 
138
        l += genpulse (&buf[l], CHARDELAY, 0);
 
139
        return l;
 
140
      }
 
141
 
 
142
  return 0;
 
143
}
 
144
 
 
145
/*
 
146
 * The playchar() routine handles some special characters that are not
 
147
 * included in the international morse aplhabet. Characters are then played by
 
148
 * calling the genmorse() routine.
 
149
 */
 
150
 
 
151
static void
 
152
playchar (char c)
 
153
{
 
154
  short buf[16 * BUFSZ];
 
155
  int l;
 
156
 
 
157
  l = 0;
 
158
 
 
159
  if (c <= 'Z' && c >= 'A')
 
160
    c += 32;
 
161
 
 
162
  switch (c)
 
163
    {
 
164
    case '\n':
 
165
      return;
 
166
      break;
 
167
    case ' ':
 
168
    case '\t':
 
169
      l = genmorse (buf, ' ');
 
170
      break;
 
171
 
 
172
    case '\r':
 
173
      break;
 
174
 
 
175
    case '�':
 
176
      l = genmorse (buf, '�');
 
177
      break;
 
178
    case '�':
 
179
      l = genmorse (buf, '�');
 
180
      break;
 
181
    case '�':
 
182
      l = genmorse (buf, '�');
 
183
      break;
 
184
    case '�':
 
185
      l = genmorse (buf, '�');
 
186
      break;
 
187
 
 
188
    default:
 
189
      l = genmorse (buf, c);
 
190
    }
 
191
 
 
192
  write (audiofd, buf, 2 * l);
 
193
  if (2 * l < charsize)
 
194
    {
 
195
      char tmp[4 * 1024 * 1024];
 
196
      l = charsize - 2 * l;
 
197
      memset (tmp, 0, l);
 
198
      write (audiofd, tmp, l);
 
199
    }
 
200
}
 
201
 
 
202
int
 
203
main (int argc, char *argv[])
 
204
{
 
205
  char *devname = "/dev/dsp";
 
206
  short buf[16 * BUFSZ];
 
207
  char line[1024];
 
208
  int i, parm;
 
209
  int l, speed, charspeed, wpm = 8;
 
210
 
 
211
/*
 
212
 * Charcter rate (CPS/WPS) handling.
 
213
 */
 
214
 
 
215
  if (argc > 1)
 
216
    {
 
217
      wpm = atoi (argv[1]);
 
218
      if (wpm == 0)
 
219
        wpm = 12;
 
220
    }
 
221
 
 
222
  if (argc > 2)
 
223
    charspeed = atoi (argv[2]);
 
224
 
 
225
  speed = wpm;
 
226
  charsize = 60 * SRATE * 2 / charspeed;
 
227
 
 
228
  printf ("Words per minute %d. Characters per minute %d\n", wpm, wpm * 5);
 
229
  printf ("Charrate %d chars/min -> (%d samples)\n", charspeed, charsize);
 
230
  dotsize = SRATE / speed;
 
231
 
 
232
  ncodes = strlen (Chars);
 
233
 
 
234
/*
 
235
 * Open the audio device and set up the parameters.
 
236
 */
 
237
 
 
238
  if ((audiofd = open (devname, O_WRONLY, 0)) == -1)
 
239
    {
 
240
      perror (devname);
 
241
      exit (-1);
 
242
    }
 
243
 
 
244
  parm = AFMT_S16_LE;
 
245
  if (ioctl (audiofd, SNDCTL_DSP_SETFMT, &parm) == -1)
 
246
    {
 
247
      perror ("SETFMT");
 
248
      close (audiofd);
 
249
      exit (-1);
 
250
    }
 
251
 
 
252
  if (parm != AFMT_S16_LE)
 
253
    {
 
254
      printf
 
255
        ("Error: 32/24 bit sample format is not supported by the device\n");
 
256
      printf ("%08x/%08x\n", parm, AFMT_S16_LE);
 
257
      close (audiofd);
 
258
      exit (-1);
 
259
    }
 
260
 
 
261
  parm = SRATE;
 
262
  if (ioctl (audiofd, SNDCTL_DSP_SPEED, &parm) == -1)
 
263
    {
 
264
      perror ("SPEED");
 
265
      close (audiofd);
 
266
      exit (-1);
 
267
    }
 
268
 
 
269
  if (parm != SRATE)
 
270
    {
 
271
      printf
 
272
        ("Error: %d Hz sampling rate is not supported by the device (%d)\n",
 
273
         SRATE, parm);
 
274
      close (audiofd);
 
275
      exit (-1);
 
276
    }
 
277
 
 
278
/*
 
279
 * The setup phase is complete. After this moment we can forget that we are
 
280
 * working on a device. The remainder of this program behaves just like
 
281
 * it's writing to any (disk) file.
 
282
 */
 
283
  a = 0.0;
 
284
 
 
285
  step = 360.0 * 600.0 / parm;
 
286
 
 
287
  l = 0;
 
288
  l += genpulse (&buf[l], 1, 0);
 
289
  write (audiofd, buf, l * 2);
 
290
 
 
291
  /* Some initial delay */
 
292
  memset (buf, 0, 4096);
 
293
  for (l = 0; l < 30; l++)
 
294
    write (audiofd, buf, 4096);
 
295
 
 
296
  while (fgets (line, sizeof (line), stdin) != NULL)
 
297
    {
 
298
 
 
299
      if (*line == '#')
 
300
        continue;
 
301
 
 
302
      for (i = 0; i < strlen (line); i++)
 
303
        {
 
304
          playchar (line[i]);
 
305
        }
 
306
    }
 
307
 
 
308
  /* Some final delay */
 
309
  memset (buf, 0, 4096);
 
310
  for (l = 0; l < 20; l++)
 
311
    write (audiofd, buf, 4096);
 
312
 
 
313
  close (audiofd);
 
314
 
 
315
  exit (0);
 
316
}