Page MenuHomeFreeBSD

D35772.id108020.diff
No OneTemporary

D35772.id108020.diff

diff --git a/usr.bin/beep/beep.1 b/usr.bin/beep/beep.1
--- a/usr.bin/beep/beep.1
+++ b/usr.bin/beep/beep.1
@@ -1,5 +1,5 @@
.\"-
-.\" Copyright (c) 2021 Hans Petter Selasky <hselasky@FreeBSD.org>
+.\" Copyright (c) 2021-2022 Hans Petter Selasky <hselasky@FreeBSD.org>
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
@@ -23,7 +23,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd November 4, 2021
+.Dd July 11, 2022
.Dt beep 1
.Os
.Sh NAME
@@ -36,6 +36,10 @@
.Op Fl r Ar sample_rate_hz
.Op Fl d Ar oss_device
.Op Fl g Ar gain
+.Op Fl t Ar UTF-8-text
+.Op Fl b Ar 8-bit-number
+.Op Fl s Ar 16-bit-number
+.Op Fl i Ar 32-bit-number
.Op Fl B
.Op Fl h
.Sh DESCRIPTION
@@ -60,6 +64,20 @@
.It Fl g
Sets the waveform gain, between 0 and 100 inclusively.
The default is 75.
+.It Fl t
+Render the given UTF-8 text starting at the least significant bit, similarly to Braille.
+Each full character is output separately, meaning either 8-, 12-, 17- or 22-bits will be output.
+A small pause separate each character.
+This option can also be combined with other options, like duration and frequency.
+.It Fl b
+Render the given number as a 8-bit number, starting at the least significant bit.
+This option can also be combined with other options, like duration and frequency.
+.It Fl s
+Render the given number as a 16-bit number, starting at the least significant bit.
+This option can also be combined with other options, like duration and frequency.
+.It Fl i
+Render the given number as a 32-bit number, starting at the least significant bit.
+This option can also be combined with other options, like duration and frequency.
.It Fl B
Runs the
.Nm
diff --git a/usr.bin/beep/beep.c b/usr.bin/beep/beep.c
--- a/usr.bin/beep/beep.c
+++ b/usr.bin/beep/beep.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2021 Hans Petter Selasky <hselasky@freebsd.org>
+ * Copyright (c) 2021-2022 Hans Petter Selasky <hselasky@freebsd.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -36,6 +36,7 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#include <assert.h>
#define SAMPLE_RATE_DEF 48000 /* hz */
#define SAMPLE_RATE_MAX 48000 /* hz */
@@ -61,6 +62,10 @@
static int gain = GAIN_DEF;
static const char *oss_dev = DEFAULT_DEVICE;
static bool background;
+static const uint8_t *text;
+static const uint8_t *number;
+static uint32_t number_parsed;
+static uint8_t number_bits;
/*
* wave_function_16
@@ -129,6 +134,135 @@
return (retval);
}
+static void
+render_beep(int32_t *buffer, size_t size, float amp)
+{
+ size_t slope;
+ size_t off; /* buffer offset */
+ float p; /* phase */
+ float d; /* delta phase */
+
+ /* compute slope duration in samples */
+ slope = (DURATION_MIN * sample_rate) / 2000;
+
+ /* set initial phase and delta */
+ p = 0;
+ d = (float)frequency / (float)sample_rate;
+
+ /* compute wave */
+ for (p = off = 0; off != size; off++, p += d) {
+ float sample;
+
+ p = p - floorf(p);
+ sample = amp * wave_function_16(p, WAVE_POWER);
+
+ if (off < slope)
+ sample = sample * off / (float)slope;
+ else if (off > (size - slope))
+ sample = sample * (size - off - 1) / (float)slope;
+
+ buffer[off] = sample * 0x7fffff00;
+ }
+}
+
+static void
+render_silence(int32_t *buffer, size_t size)
+{
+ for (size_t x = 0; x != size; x++)
+ buffer[x] = 0;
+}
+
+static uint32_t
+get_unicode_char(const uint8_t **pptr, uint8_t *bits)
+{
+ const uint8_t *p8;
+ uint32_t ch;
+
+ p8 = *pptr;
+
+ if ((*p8 & 0xc0) == 0xc0) {
+ p8++;
+ while ((*p8 & 0xc0) == 0x80)
+ p8++;
+ switch (p8 - *pptr) {
+ case 1: /* 12-bit */
+ ch = (*pptr)[0] & 0x3f;
+ ch <<= 6;
+ ch |= (*pptr)[1] & 0x3f;
+
+ *pptr = p8;
+ *bits = 12;
+ goto done;
+ case 2: /* 17-bit */
+ ch = (*pptr)[0] & 0x1f;
+ ch <<= 6;
+ ch |= (*pptr)[1] & 0x3f;
+ ch <<= 6;
+ ch |= (*pptr)[2] & 0x3f;
+
+ *pptr = p8;
+ *bits = 17;
+ goto done;
+ case 3: /* 22-bit */
+ ch = (*pptr)[0] & 0x0f;
+ ch <<= 6;
+ ch |= (*pptr)[1] & 0x3f;
+ ch <<= 6;
+ ch |= (*pptr)[2] & 0x3f;
+ ch <<= 6;
+ ch |= (*pptr)[3] & 0x3f;
+
+ *pptr = p8;
+ *bits = 22;
+ goto done;
+ default:
+ break;
+ }
+ }
+ /* not UTF-8 */
+ ch = **pptr;
+ (*pptr) ++;
+ *bits = 8;
+done:
+ return (ch);
+}
+
+static size_t
+text_length_in_units(const uint8_t *ptr)
+{
+ size_t units = 0;
+ uint32_t ch;
+ uint8_t bits;
+
+ while (*ptr) {
+ ch = get_unicode_char(&ptr, &bits);
+
+ for (uint8_t x = 0; x != bits; x++) {
+ if ((ch >> x) & 1)
+ units += 2;
+ else
+ units += 4;
+ }
+
+ units += 4;
+ }
+ return (units);
+}
+
+static size_t
+number_length_in_units(uint32_t num, uint8_t max)
+{
+ size_t units = 0;
+
+ for (uint8_t x = 0; x != max; x++) {
+ if ((num >> x) & 1)
+ units += 2;
+ else
+ units += 4;
+ }
+ return (units);
+}
+
static void
usage(void)
{
@@ -138,6 +272,10 @@
"\t" "-r <sample rate in HZ, from %d Hz to %d Hz, default %d Hz>\n"
"\t" "-d <OSS device (default %s)>\n"
"\t" "-g <gain from %d to %d, default %d>\n"
+ "\t" "-t <render given UTF-8 based text>\n"
+ "\t" "-b <render given 8-bit number>\n"
+ "\t" "-s <render given 16-bit number>\n"
+ "\t" "-i <render given 32-bit number>\n"
"\t" "-B Run in background\n"
"\t" "-h Show usage\n",
getprogname(),
@@ -153,16 +291,16 @@
main(int argc, char **argv)
{
int32_t *buffer;
- size_t slope;
+ int32_t *buffer_short;
+ int32_t *buffer_long;
size_t size;
+ size_t units;
size_t off;
float a;
- float d;
- float p;
int c;
int f;
- while ((c = getopt(argc, argv, "BF:D:r:g:d:h")) != -1) {
+ while ((c = getopt(argc, argv, "BF:D:r:b:s:i:t:g:d:h")) != -1) {
switch (c) {
case 'F':
frequency = strtol(optarg, NULL, 10);
@@ -191,12 +329,30 @@
case 'B':
background = true;
break;
+ case 'b':
+ number = optarg;
+ number_bits = 8;
+ break;
+ case 's':
+ number = optarg;
+ number_bits = 16;
+ break;
+ case 'i':
+ number = optarg;
+ number_bits = 32;
+ break;
+ case 't':
+ text = optarg;
+ break;
default:
usage();
break;
}
}
+ if (text != NULL && number != NULL)
+ errx(1, "-t and -s options are mutually exclusive");
+
if (background && daemon(0, 0) != 0)
errx(1, "daemon(0,0) failed");
@@ -224,38 +380,84 @@
if (ioctl(f, SNDCTL_DSP_GETODELAY, &c) != 0)
errx(1, "ioctl SNDCTL_DSP_GETODELAY failed");
+ if (number != NULL) {
+ number_parsed = strtoul(number, NULL, 0);
+ units = number_length_in_units(number_parsed, number_bits);
+ } else if (text != NULL) {
+ units = text_length_in_units(text);
+ } else {
+ units = 1;
+ }
+
size = ((sample_rate * duration_ms) + 999) / 1000;
- buffer = malloc(sizeof(buffer[0]) * size);
+ buffer = malloc(sizeof(buffer[0]) * size * units);
if (buffer == NULL)
errx(1, "out of memory");
- /* compute slope duration in samples */
- slope = (DURATION_MIN * sample_rate) / 2000;
-
/* compute base gain */
a = powf(65536.0f, (float)gain / (float)GAIN_MAX) / 65536.0f;
- /* set initial phase and delta */
- p = 0;
- d = (float)frequency / (float)sample_rate;
-
- /* compute wave */
- for (p = off = 0; off != size; off++, p += d) {
- float sample;
-
- p = p - floorf(p);
- sample = a * wave_function_16(p, WAVE_POWER);
-
- if (off < slope)
- sample = sample * off / (float)slope;
- else if (off > (size - slope))
- sample = sample * (size - off - 1) / (float)slope;
+ if (text != NULL || number != NULL) {
+ buffer_short = malloc(sizeof(buffer[0]) * size * 2);
+ if (buffer_short == NULL)
+ errx(1, "out of memory");
+ buffer_long = malloc(sizeof(buffer[0]) * size * 4);
+ if (buffer_long == NULL)
+ errx(1, "out of memory");
+
+ render_beep(buffer_short, size, a);
+ render_silence(buffer_short + size, size);
+
+ render_beep(buffer_long, 3 * size, a);
+ render_silence(buffer_long + 3 * size, size);
+ } else {
+ buffer_short = NULL;
+ buffer_long = NULL;
+ }
- buffer[off] = sample * 0x7fffff00;
+ if (number != NULL) {
+ off = 0;
+
+ for (uint8_t x = 0; x != number_bits; x++) {
+ if ((number_parsed >> x) & 1) {
+ memcpy(buffer + off, buffer_short, 2 * size * sizeof(buffer[0]));
+ off += 2 * size;
+ } else {
+ memcpy(buffer + off, buffer_long, 4 * size * sizeof(buffer[0]));
+ off += 4 * size;
+ }
+ }
+ assert(off == (size * units));
+ } else if (text != NULL) {
+ for (off = 0; *text != 0; ) {
+ uint8_t bits;
+ uint32_t ch;
+
+ ch = get_unicode_char(&text, &bits);
+
+ for (uint8_t x = 0; x != bits; x++) {
+ if ((ch >> x) & 1) {
+ memcpy(buffer + off, buffer_short, 2 * size * sizeof(buffer[0]));
+ off += 2 * size;
+ } else {
+ memcpy(buffer + off, buffer_long, 4 * size * sizeof(buffer[0]));
+ off += 4 * size;
+ }
+ }
+
+ render_silence(buffer + off, 4 * size);
+ off += 4 * size;
+ }
+ assert(off == (size * units));
+ } else {
+ render_beep(buffer, size, a);
}
- if (write(f, buffer, size * sizeof(buffer[0])) !=
- (ssize_t)(size * sizeof(buffer[0])))
+ free(buffer_short);
+ free(buffer_long);
+
+ if (write(f, buffer, size * units * sizeof(buffer[0])) !=
+ (ssize_t)(size * units * sizeof(buffer[0])))
errx(1, "failed writing to DSP device(%s)", oss_dev);
free(buffer);

File Metadata

Mime Type
text/plain
Expires
Wed, Nov 26, 2:58 PM (15 h, 9 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
26216592
Default Alt Text
D35772.id108020.diff (9 KB)

Event Timeline