From: Simon Schubert Date: Sun, 22 Apr 2007 10:22:32 +0000 (+0000) Subject: Pull morse(6) into the new millenium and teach it to use sound(4). X-Git-Tag: v2.0.1~3195 X-Git-Url: https://gitweb.dragonflybsd.org/dragonfly.git/commitdiff_plain/7c098eb5a59b7894dd1636c61a53df4507679825 Pull morse(6) into the new millenium and teach it to use sound(4). Feedback-by: swildner@ --- diff --git a/games/morse/Makefile b/games/morse/Makefile index 9a6ad06863..148e2e4851 100644 --- a/games/morse/Makefile +++ b/games/morse/Makefile @@ -1,12 +1,10 @@ # @(#)Makefile 8.1 (Berkeley) 5/31/93 # $FreeBSD: src/games/morse/Makefile,v 1.4.6.5 2001/04/25 09:28:58 ru Exp $ -# $DragonFly: src/games/morse/Makefile,v 1.4 2006/10/08 16:22:36 pavalos Exp $ +# $DragonFly: src/games/morse/Makefile,v 1.5 2007/04/22 10:22:32 corecode Exp $ PROG= morse MAN= morse.6 - -.if ${MACHINE_ARCH} == "i386" -CFLAGS += -DSPEAKER=\"/dev/speaker\" -.endif +LDADD= -lm +DPADD= ${LIBM} .include diff --git a/games/morse/morse.6 b/games/morse/morse.6 index ed4e1951e8..698b9f3475 100644 --- a/games/morse/morse.6 +++ b/games/morse/morse.6 @@ -32,9 +32,9 @@ .\" .\" @(#)bcd.6 8.1 (Berkeley) 5/31/93 .\" $FreeBSD: src/games/morse/morse.6,v 1.4.2.7 2003/01/26 02:57:27 keramida Exp $ -.\" $DragonFly: src/games/morse/morse.6,v 1.3 2006/02/17 19:33:31 swildner Exp $ +.\" $DragonFly: src/games/morse/morse.6,v 1.4 2007/04/22 10:22:32 corecode Exp $ .\" -.Dd December 7, 2000 +.Dd April 22, 2007 .Dt MORSE 6 .Os .Sh NAME @@ -43,6 +43,7 @@ .Sh SYNOPSIS .Nm .Op Fl p +.Op Fl P Ar dspdevice .Op Fl d Ar device .Op Fl e .Op Fl w Ar speed @@ -63,8 +64,11 @@ The option produces dots and dashes rather than words. .It Fl p Send morse the real way. This only works if your system has -.Xr speaker 4 +.Xr sound 4 support. +.It Fl P Ar dspdevice +Select a different dsp device from the default +.Pa /dev/dsp . .It Fl w Ar speed Set the sending speed in words per minute. If not specified the default speed of 20 WPM is used. @@ -148,18 +152,17 @@ they are interpreted as belonging to the .Ql ISO-8859-1 character set. -.Sh FILES -.Bl -tag -width /dev/speaker -compact -.It Pa /dev/speaker -speaker device file -.El .Sh SEE ALSO -.Xr speaker 4 +.Xr sound 4 .Sh HISTORY Sound support for .Nm added by -.An Lyndon Nerenberg (VE7TCP/VE6BBM) Aq lyndon@orthanc.com . +.An Lyndon Nerenberg (VE7TCP/VE6BBM) Aq lyndon@orthanc.com +and later converted to use +.Xr sound +by +.An Simon 'corecode' Schubert Aq corecode@fs.ei.tum.de . .Pp Ability to key an external device added by .An J\(:org Wunsch diff --git a/games/morse/morse.c b/games/morse/morse.c index 07a82d90dd..a0fa4767ce 100644 --- a/games/morse/morse.c +++ b/games/morse/morse.c @@ -33,7 +33,7 @@ * @(#) Copyright (c) 1988, 1993 The Regents of the University of California. All rights reserved. * @(#)morse.c 8.1 (Berkeley) 5/31/93 * $FreeBSD: src/games/morse/morse.c,v 1.12.2.2 2002/03/12 17:45:15 phantom Exp $ - * $DragonFly: src/games/morse/morse.c,v 1.3 2005/04/25 16:10:24 liamfoy Exp $ + * $DragonFly: src/games/morse/morse.c,v 1.4 2007/04/22 10:22:32 corecode Exp $ */ /* @@ -42,11 +42,14 @@ */ #include +#include #include +#include #include #include #include +#include #include #include #include @@ -54,10 +57,6 @@ #include #include -#ifdef SPEAKER -#include -#endif - struct morsetab { char inchar; const char *morse; @@ -189,13 +188,19 @@ static const struct morsetab koi8rtab[] = { {'\0', ""} }; +struct tone_data { + int16_t *data; + size_t len; +}; + +void alloc_soundbuf(struct tone_data *, double, int); void show(const char *), play(const char *), morse(char); void ttyout(const char *); void sighandler(int); -#define GETOPTOPTS "d:ef:sw:" +#define GETOPTOPTS "d:ef:pP:sw:" #define USAGE \ -"usage: morse [-s] [-e] [-d device] [-w speed] [-f frequency] [string ...]\n" +"usage: morse [-s] [-e] [-p] [-P device] [-d device] [-w speed] [-f frequency] [string ...]\n" static int pflag, sflag, eflag; static int wpm = 20; /* words per minute */ @@ -203,23 +208,18 @@ static int wpm = 20; /* words per minute */ static int freq = FREQUENCY; static char *device; /* for tty-controlled generator */ +static struct tone_data tone_dot, tone_dash, tone_silence; +#define DSP_RATE 44100 +static const char *snddev = "/dev/dsp"; + #define DASH_LEN 3 #define CHAR_SPACE 3 -#define WORD_SPACE (7 - CHAR_SPACE - 1) +#define WORD_SPACE (7 - CHAR_SPACE) static float dot_clock; int spkr, line; struct termios otty, ntty; int olflags; -#ifdef SPEAKER -tone_t sound; -#undef GETOPTOPTS -#define GETOPTOPTS "d:ef:psw:" -#undef USAGE -#define USAGE \ -"usage: morse [-s] [-p] [-e] [-d device] [-w speed] [-f frequency] [string ...]\n" -#endif - static const struct morsetab *hightab; int @@ -240,11 +240,12 @@ main(int argc, char **argv) case 'f': freq = atoi(optarg); break; -#ifdef SPEAKER case 'p': pflag = 1; break; -#endif + case 'P': + snddev = optarg; + break; case 's': sflag = 1; break; @@ -266,15 +267,28 @@ main(int argc, char **argv) } if ((pflag || device) && (freq == 0)) freq = FREQUENCY; + if (pflag || device) { + dot_clock = wpm / 2.4; /* dots/sec */ + dot_clock = 1 / dot_clock; /* duration of a dot */ + dot_clock = dot_clock / 2; /* dot_clock runs at twice */ + /* the dot rate */ + } -#ifdef SPEAKER if (pflag) { - if ((spkr = open(SPEAKER, O_WRONLY, 0)) == -1) { - perror(SPEAKER); - exit(1); - } + snd_chan_param param; + + if ((spkr = open(snddev, O_WRONLY, 0)) == -1) + err(1, "%s", snddev); + param.play_rate = DSP_RATE; + param.play_format = AFMT_S16_NE; + param.rec_rate = 0; + param.rec_format = 0; + if (ioctl(spkr, AIOSFMT, ¶m) != 0) + err(1, "%s: set format", snddev); + alloc_soundbuf(&tone_dot, dot_clock, 1); + alloc_soundbuf(&tone_dash, DASH_LEN * dot_clock, 1); + alloc_soundbuf(&tone_silence, dot_clock, 0); } else -#endif if (device) { if ((line = open(device, O_WRONLY | O_NONBLOCK)) == -1) { perror("open tty line"); @@ -299,13 +313,6 @@ main(int argc, char **argv) (void)signal(SIGQUIT, sighandler); (void)signal(SIGTERM, sighandler); } - if (pflag || device) { - dot_clock = wpm / 2.4; /* dots/sec */ - dot_clock = 1 / dot_clock; /* duration of a dot */ - dot_clock = dot_clock / 2; /* dot_clock runs at twice */ - /* the dot rate */ - dot_clock = dot_clock * 100; /* scale for ioctl */ - } argc -= optind; argv += optind; @@ -342,6 +349,56 @@ main(int argc, char **argv) exit(0); } +void +alloc_soundbuf(struct tone_data *tone, double len, int on) +{ + int samples, i; + + samples = DSP_RATE * len; + tone->len = samples * sizeof(*tone->data); + tone->data = malloc(tone->len); + if (tone->data == NULL) + err(1, NULL); + if (!on) { + bzero(tone->data, tone->len); + return; + } + + /* + * We create a sinus with the specified frequency and smooth + * the edges to reduce key clicks. + */ + for (i = 0; i < samples; i++) { + double filter = 1; + +#define FILTER_SAMPLES 100 + if (i < FILTER_SAMPLES || i > samples - FILTER_SAMPLES) { + /* + * Gauss window + */ +#if 0 + int fi = i; + + if (i > FILTER_SAMPLES) + fi = samples - i; + filter = exp(-0.5 * + pow((double)(fi - FILTER_SAMPLES) / + (0.4 * FILTER_SAMPLES), 2)); +#else + /* + * Triangle window + */ + if (i < FILTER_SAMPLES) + filter = (double)i / FILTER_SAMPLES; + else + filter = (double)(samples - i) / FILTER_SAMPLES; +#endif + } + tone->data[i] = 32767 * sin((double)i / samples * len * freq * 2 * M_PI) * + filter; + } +} + void morse(char c) { @@ -391,43 +448,37 @@ show(const char *s) void play(const char *s) { -#ifdef SPEAKER const char *c; + int duration; + struct tone_data *tone; + /* + * We don't need to usleep() here, as the sound device blocks. + */ for (c = s; *c != '\0'; c++) { switch (*c) { case '.': - sound.frequency = freq; - sound.duration = dot_clock; + duration = 1; + tone = &tone_dot; break; case '-': - sound.frequency = freq; - sound.duration = dot_clock * DASH_LEN; + duration = 1; + tone = &tone_dash; break; case ' ': - sound.frequency = 0; - sound.duration = dot_clock * WORD_SPACE; + duration = WORD_SPACE; + tone = &tone_silence; break; default: - sound.duration = 0; - } - if (sound.duration) { - if (ioctl(spkr, SPKRTONE, &sound) == -1) { - perror("ioctl play"); - exit(1); - } - } - sound.frequency = 0; - sound.duration = dot_clock; - if (ioctl(spkr, SPKRTONE, &sound) == -1) { - perror("ioctl rest"); - exit(1); + errx(1, "invalid morse digit"); } + while (duration-- > 0) + write(spkr, tone->data, tone->len); + write(spkr, tone_silence.data, tone_silence.len); } - sound.frequency = 0; - sound.duration = dot_clock * CHAR_SPACE; - ioctl(spkr, SPKRTONE, &sound); -#endif + duration = CHAR_SPACE - 1; /* we already waited 1 after the last symbol */ + while (duration-- > 0) + write(spkr, tone_silence.data, tone_silence.len); } void @@ -459,16 +510,16 @@ ttyout(const char *s) lflags |= TIOCM_RTS; ioctl(line, TIOCMSET, &lflags); } - duration *= 10000; + duration *= 1000000; if (duration) usleep(duration); ioctl(line, TIOCMGET, &lflags); lflags &= ~TIOCM_RTS; ioctl(line, TIOCMSET, &lflags); - duration = dot_clock * 10000; + duration = dot_clock * 1000000; usleep(duration); } - duration = dot_clock * CHAR_SPACE * 10000; + duration = dot_clock * CHAR_SPACE * 1000000; usleep(duration); }