Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F137763823
D35772.id108020.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
9 KB
Referenced Files
None
Subscribers
None
D35772.id108020.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D35772: beep(1): Add support for rendering text and numbers as audio.
Attached
Detach File
Event Timeline
Log In to Comment