#include #include #include #include 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; }