#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
const char * UsageLines [] = {
"Usage: swwritecw (cycles per word) (samples per word) (# of words)",
"Writes a headerless sound file, .sw, to standard output consisting",
"of a constant pitch note, morse-code keyed with random content.",
"",
"The text used will be output on standard error.",
"",
"The pitch will depend on the playback speed, and is given by:",
"(playback speed in samples/sec) x (cycles per word) / (samples per word)",
"",
"The sending speed will also depend on the playback speed, and is",
"(playback speed in samples/sec) x (60 sec/min) / (samples per word)",
"",
"example of use:",
"swwritecw 2333 25000 25 > sound.sw 2> key.txt",
"sox sound.sw sound.wav (will use default 8000 samples per sec)",
"",
"Will use a pitch of 700 Hz and send 18 wpm",
"",
"(Number of words is also used as a random key)",
"May 22, 2019. Latest is at
gopher://sdf.org/0/users/julianbr",
"",
};
const int NumUsageLines = sizeof UsageLines / sizeof (UsageLines [0] );
const static struct {
char letter;
char * code;
} Elements [] = {
{ 'a', ".-" },
{ 'b', "-..." },
{ 'c', "-.-." },
{ 'd', "-.." },
{ 'e', "." },
{ 'f', "..-." },
{ 'g', "-.." },
{ 'h', "...." },
{ 'i', ".." },
{ 'j', ".---" },
{ 'k', "-.-" },
{ 'l', ".-.." },
{ 'm', "--" },
{ 'n', "-." },
{ 'o', "---" },
{ 'p', ".--." },
{ 'q', "--.-" },
{ 'r', ".-." },
{ 's', "..." },
{ 't', "-" },
{ 'u', "..-" },
{ 'v', "...-" },
{ 'w', ".--" },
{ 'x', "-..-" },
{ 'y', "-.--" },
{ 'z', "--.." },
{ '.', ".-.-.-" },
{ ',', "--..--" },
{ '?', "..--.." },
{ '/', "-..-." },
{ '1', ".----" },
{ '2', "..---" },
{ '3', "...--" },
{ '4', "....-" },
{ '5', "....." },
{ '6', "-...." },
{ '7', "--..." },
{ '8', "---.." },
{ '9', "----." },
{ '0', "-----" },
{ 'e', "." },
{ 'e', "." },
{ 'e', "." },
{ 'e', "." },
{ 'e', "." },
{ 'e', "." },
{ 't', "-" },
{ 't', "-" },
{ 't', "-" },
{ 'i', ".." },
{ 'i', ".." },
{ 'i', ".." },
{ 'a', ".-" },
{ 'n', "-." },
{ 's', "..." },
};
#define NumElements sizeof Elements / sizeof (Elements [0] )
int main (int argc, char * * argv)
{
unsigned long int CyclesPerWord, SamplesPerWord, NumWords;
unsigned long int a, r, m, mmax, n;
char letter, * code;
int element, LenWord, i, j, k;
char c;
if (argc < 2) {
for (i = 0; i < NumUsageLines; i++)
printf ("%s\n", UsageLines [i] );
}
if (argc != 4
|| sscanf (argv [1], "%lu%c", & CyclesPerWord, & c) != 1
|| sscanf (argv [2], "%lu%c", & SamplesPerWord, & c) != 1
|| sscanf (argv [3], "%lu%c", & NumWords, & c) != 1
) {
fprintf (stderr, "Usage: %s (Cycles Per Word)", argv [0] );
fprintf (stderr, " (Samples Per Word)");
fprintf (stderr, " (number of words).\n");
return 0;
}
srand (NumWords);
n = 0;
for (i = 0; i < NumWords; i++) {
r = rand ()/113;
LenWord = 1 + r%8;
m = 0;
/* silence at beginning of word */
mmax = 16*SamplesPerWord;
while (m < mmax) {
n = (n + CyclesPerWord)%SamplesPerWord;
if (n + n < SamplesPerWord)
a = 32768;
else
a = 32767;
putchar (a%256);
putchar ((a/256)^128);
m += 400;
}
m -= mmax;
for (j = 0; j < LenWord; j++) {
r = rand ()/1113;
element = r%NumElements;
letter = Elements [element].letter;
code = Elements [element].code;
/* silence at beginning of letter */
mmax = 8*SamplesPerWord;
while (m < mmax) {
n = (n + CyclesPerWord)%SamplesPerWord;
if (n + n < SamplesPerWord)
a = 32768;
else
a = 32767;
putchar (a%256);
putchar ((a/256)^128);
m += 400;
}
m -= mmax;
k = 0;
c = code [k];
while (c != '\0') {
/* silence at beginning of component */
mmax = 3*SamplesPerWord;
while (m < mmax) {
n = (n + CyclesPerWord)%SamplesPerWord;
if (n + n < SamplesPerWord)
a = 32768;
else
a = 32767;
putchar (a%256);
putchar ((a/256)^128);
m += 400;
}
m -= mmax;
/* component rise time */
mmax = 2*SamplesPerWord;
while (m < mmax) {
n = (n + CyclesPerWord)%SamplesPerWord;
if (n + n < SamplesPerWord)
a = 32768 + 20000*sin(M_PI*(n + n)/SamplesPerWord)*m/mmax;
else
a = 32767 - 20000*sin(M_PI*(n + n - SamplesPerWord)/SamplesPerWord)*m/mmax;
putchar (a%256);
putchar ((a/256)^128);
m += 400;
}
m -= mmax;
/* component dwell time */
mmax = 6*SamplesPerWord;
if (c == '-')
mmax = 22*SamplesPerWord;
while (m < mmax) {
n = (n + CyclesPerWord)%SamplesPerWord;
if (n + n < SamplesPerWord)
a = 32768 + 20000*sin (M_PI*(n + n)/SamplesPerWord);
else
a = 32767 - 20000*sin (M_PI*(n + n - SamplesPerWord)/SamplesPerWord);
putchar (a%256);
putchar ((a/256)^128);
m += 400;
}
m -= mmax;
/* component fall time */
mmax = 2*SamplesPerWord;
while (m < mmax) {
n = (n + CyclesPerWord)%SamplesPerWord;
if (n + n < SamplesPerWord)
a = 32768 + 20000*sin(M_PI*(n + n)/SamplesPerWord)*(mmax - m)/mmax;
else
a = 32767 - 20000*sin(M_PI*(n + n - SamplesPerWord)/SamplesPerWord)*(mmax - m)/mmax;
putchar (a%256);
putchar ((a/256)^128);
m += 400;
}
m -= mmax;
/* silence at end of component */
mmax = 3*SamplesPerWord;
while (m < mmax) {
n = (n + CyclesPerWord)%SamplesPerWord;
if (n + n < SamplesPerWord)
a = 32768;
else
a = 32767;
putchar (a%256);
putchar ((a/256)^128);
m += 400;
}
m -= mmax;
k++;
c = code [k];
}
fprintf (stderr, "%c", letter);
/* silence at end of letter */
mmax = 8*SamplesPerWord;
while (m < mmax) {
n = (n + CyclesPerWord)%SamplesPerWord;
if (n + n < SamplesPerWord)
a = 32768;
else
a = 32767;
putchar (a%256);
putchar ((a/256)^128);
m += 400;
}
m -= mmax;
}
fprintf (stderr, " ");
/* silence at end of word */
mmax = 16*SamplesPerWord;
while (m < mmax) {
n = (n + CyclesPerWord)%SamplesPerWord;
if (n + n < SamplesPerWord)
a = 32768;
else
a = 32767;
putchar (a%256);
putchar ((a/256)^128);
m += 400;
}
m -= mmax;
}
fprintf (stderr, "\n");
fprintf (stderr, "\n");
return 0;
}