122 lines
3.2 KiB
ObjectPascal
122 lines
3.2 KiB
ObjectPascal
{$mode delphi}
|
|
PROGRAM cw;
|
|
// Output a string as Morse code and CW.
|
|
// Cross-platform PCM audio uses OpenAL
|
|
USES OpenAL, HRTimer;
|
|
|
|
// Intl. Morse codes in ASCII order
|
|
CONST Morse: ARRAY [32..95] OF STRING = (' ','-.-.--','.-..-.','#','...-..-','%','.-...','.----.','-.--.','-.--.-','*','.-.-.','--..--','-....-','.-.-.-','-..-.','-----','.----','..---','...--','....-','.....','-....','--...','---..','----.','---...','-.-.-.','>','-...-','<','..--..','.--.-.','.-','-...','-.-.','-..','.','..-.','--.','....','..','.---','-.-','.-..','--','-.','---','.--.','--.-','.-.','...','-','..-','...-','.--','-..-','-.--','--..','-.--.','\','-.--.-','~','..--.-');
|
|
// lengthen dah by this fraction of dit:
|
|
// best = 0.4; also lengthens pauses
|
|
doh = 0.4;
|
|
// an 0.05 sec dit is around 26 wpm
|
|
dit = 0.05;
|
|
dah = 3 * dit + doh * dit;
|
|
|
|
VAR // OpenAL variables
|
|
buffer : TALuint;
|
|
source : TALuint;
|
|
sourcepos: ARRAY [0..2] OF TALfloat= ( 0.0, 0.0, 0.0 );
|
|
sourcevel: ARRAY [0..2] OF TALfloat= ( 0.0, 0.0, 0.0 );
|
|
|
|
argv: ARRAY OF PalByte;
|
|
format: TALEnum;
|
|
size: TALSizei;
|
|
freq: TALSizei;
|
|
loop: TALInt;
|
|
data: TALVoid;
|
|
|
|
// rewinding has an effect on the output:
|
|
// <with> and <without> sound rather different
|
|
rewind : BOOLEAN = FALSE;
|
|
// the high-res timer is from Wolfgang Ehrhardt
|
|
// http://www.wolfgang-ehrhardt.de/misc_en.html
|
|
t : THRTimer;
|
|
msg : STRING = 'the quick brown fox jumps over the lazy dog.';
|
|
|
|
|
|
PROCEDURE PlayS(s: Extended);
|
|
BEGIN
|
|
StartTimer(t);
|
|
AlSourcePlay(source);
|
|
WHILE readseconds(t) < s DO BEGIN END;
|
|
IF rewind THEN AlSourceRewind(source);
|
|
AlSourceStop(source);
|
|
END;
|
|
|
|
PROCEDURE Pause(s: Extended);
|
|
BEGIN
|
|
StartTimer(t);
|
|
WHILE readseconds(t) < s DO BEGIN END;
|
|
END;
|
|
|
|
PROCEDURE doDit;
|
|
BEGIN
|
|
PlayS(dit);
|
|
Pause(dit);
|
|
END;
|
|
|
|
PROCEDURE doDah;
|
|
BEGIN
|
|
PlayS(dah);
|
|
Pause(dit);
|
|
END;
|
|
|
|
// ASCII char to Morse CW
|
|
FUNCTION AtoM(ch: CHAR): STRING;
|
|
VAR i: Integer;
|
|
u: CHAR;
|
|
BEGIN
|
|
u := ch;
|
|
IF ch IN ['a'..'z'] THEN u := chr(ord(ch) AND $5F);
|
|
result := Morse[ord(u)];
|
|
FOR i := 1 TO Length(result) DO
|
|
CASE result[i] OF
|
|
'.': BEGIN doDit; Write('. ') END;
|
|
'-': BEGIN doDah; Write('_ ') END;
|
|
END;
|
|
Pause(dah);
|
|
Write(' ');
|
|
IF u = ' ' THEN Write(' ');
|
|
END;
|
|
|
|
// ASCII string to Morse CW
|
|
PROCEDURE StoM(s: STRING);
|
|
VAR i: Integer;
|
|
BEGIN
|
|
FOR i := 1 TO Length(s) DO AtoM(s[i]);
|
|
END;
|
|
|
|
BEGIN
|
|
// OpenAL preparation
|
|
InitOpenAL;
|
|
AlutInit(nil,argv);
|
|
|
|
AlGenBuffers(1, @buffer);
|
|
// load the 500 Hz 1 sec sine-wave file
|
|
// get it from http://audiocheck.net
|
|
AlutLoadWavFile('audiocheck.net_sin_500Hz_-3dBFS_1s.wav', format, data, size, freq, loop);
|
|
AlBufferData(buffer, format, data, size, freq);
|
|
AlutUnloadWav(format, data, size, freq);
|
|
|
|
AlGenSources(1, @source);
|
|
AlSourcei ( source, AL_BUFFER, buffer);
|
|
AlSourcef ( source, AL_PITCH, 1.0 );
|
|
AlSourcef ( source, AL_GAIN, 1.0 );
|
|
AlSourcefv ( source, AL_POSITION, @sourcepos);
|
|
AlSourcefv ( source, AL_VELOCITY, @sourcevel);
|
|
AlSourcei ( source, AL_LOOPING, AL_TRUE);
|
|
|
|
// Sound and print the Morse
|
|
StoM(msg);
|
|
Pause(1.0);
|
|
|
|
AlSourceRewind(source);
|
|
AlSourceStop(source);
|
|
|
|
// Clean up
|
|
AlDeleteBuffers(1, @buffer);
|
|
AlDeleteSources(1, @source);
|
|
AlutExit();
|
|
END.
|