2
* Purpose: Simple audio programming example that plays morse code.
3
* Copyright (C) 4Front Technologies, 2002-2004. Released under GPLv2/CDDL.
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.
10
* This is a great OSS programming example because it shows how simple
11
* audio programming can be with OSS.
13
* You can use this program as a template. Just replace the
14
* while loop of the main routine by your own code.
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.
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.
30
#include <sys/soundcard.h>
34
#include <sys/types.h>
36
#define BUFSZ (16*1024)
43
int dotsize, charsize;
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.
61
genpulse (short *buf, int w, int state)
68
for (i = 0; i < ATTACK; i++)
70
double tmp = 0x7fff * cos (a * M_PI / 180.0);
71
tmp *= (double) (i) / (double) ATTACK;
73
*buf++ = (int) tmp *state;
80
for (i = ATTACK; i < l - ATTACK; i++)
82
double tmp = 0x7fff * cos (a * M_PI / 180.0);
84
*buf++ = (int) tmp *state;
91
for (i = l - ATTACK; i < l; i++)
93
double tmp = 0x7fff * cos (a * M_PI / 180.0);
95
tmp *= (double) (l - i) / (double) ATTACK;
97
*buf++ = (int) tmp *state;
108
* The genmorse() routine converts an ASCII character to the
109
* equivivalent audio morse code signal.
112
genmorse (short *buf, char c)
121
return genpulse (buf, 4, 0);
123
for (i = 0; i < ncodes; i++)
131
l += genpulse (&buf[l], 1, 1);
133
l += genpulse (&buf[l], 3, 1);
135
l += genpulse (&buf[l], 1, 0);
138
l += genpulse (&buf[l], CHARDELAY, 0);
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.
154
short buf[16 * BUFSZ];
159
if (c <= 'Z' && c >= 'A')
169
l = genmorse (buf, ' ');
176
l = genmorse (buf, '�');
179
l = genmorse (buf, '�');
182
l = genmorse (buf, '�');
185
l = genmorse (buf, '�');
189
l = genmorse (buf, c);
192
write (audiofd, buf, 2 * l);
193
if (2 * l < charsize)
195
char tmp[4 * 1024 * 1024];
196
l = charsize - 2 * l;
198
write (audiofd, tmp, l);
203
main (int argc, char *argv[])
205
char *devname = "/dev/dsp";
206
short buf[16 * BUFSZ];
209
int l, speed, charspeed, wpm = 8;
212
* Charcter rate (CPS/WPS) handling.
217
wpm = atoi (argv[1]);
223
charspeed = atoi (argv[2]);
226
charsize = 60 * SRATE * 2 / charspeed;
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;
232
ncodes = strlen (Chars);
235
* Open the audio device and set up the parameters.
238
if ((audiofd = open (devname, O_WRONLY, 0)) == -1)
245
if (ioctl (audiofd, SNDCTL_DSP_SETFMT, &parm) == -1)
252
if (parm != AFMT_S16_LE)
255
("Error: 32/24 bit sample format is not supported by the device\n");
256
printf ("%08x/%08x\n", parm, AFMT_S16_LE);
262
if (ioctl (audiofd, SNDCTL_DSP_SPEED, &parm) == -1)
272
("Error: %d Hz sampling rate is not supported by the device (%d)\n",
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.
285
step = 360.0 * 600.0 / parm;
288
l += genpulse (&buf[l], 1, 0);
289
write (audiofd, buf, l * 2);
291
/* Some initial delay */
292
memset (buf, 0, 4096);
293
for (l = 0; l < 30; l++)
294
write (audiofd, buf, 4096);
296
while (fgets (line, sizeof (line), stdin) != NULL)
302
for (i = 0; i < strlen (line); i++)
308
/* Some final delay */
309
memset (buf, 0, 4096);
310
for (l = 0; l < 20; l++)
311
write (audiofd, buf, 4096);