language-Modula2-0.1: examples/Modula-2_Libraries/PMOS/sources/general/piano.mod
IMPLEMENTATION MODULE Piano;
(********************************************************)
(* *)
(* Play notes from the keyboard *)
(* *)
(* Programmer: P. Moylan *)
(* Last edited: 15 March 1993 *)
(* Status: OK *)
(* *)
(********************************************************)
FROM Keyboard IMPORT
(* proc *) InKey;
FROM Music IMPORT
(* proc *) SetNoteDuration, PlayMusic;
FROM Windows IMPORT
(* type *) Window,
(* proc *) OpenSimpleWindow, CloseWindow, WriteString, WriteLn;
(************************************************************************)
TYPE ZeroToTwenty = [0..20];
KeyTable = ARRAY ["a".."z"] OF ZeroToTwenty;
NoteTable = ARRAY ZeroToTwenty OF ARRAY [0..1] OF CHAR;
CONST
CodeTable = KeyTable (
(* ABCDEFGH *) 2, 0, 0, 5, 0, 7, 9, 11,
(* IJKLMNOP *) 13, 12, 14, 16, 0, 0, 15, 0,
(* QRSTUVWX *) 1, 6, 4, 8, 0, 0, 3, 0,
(* YZ *) 10, 0);
OutTable = NoteTable ( "R ", "C#", "D ", "D#", "E ", "F ", "F#", "G ",
"G#", "A ", "A#", "B ", "C ", "C#", "D ", "D#",
"E ", "F ", "F#", "G ", "G#" );
(************************************************************************)
PROCEDURE Code (ch: CHAR): ZeroToTwenty;
(* Translates a keyboard character into a ZeroToTwenty code. *)
TYPE CharSet = SET OF CHAR;
BEGIN
IF ch IN CharSet {"a".."z"} THEN RETURN CodeTable[ch]
ELSIF ch = ";" THEN RETURN 17
ELSIF ch = "[" THEN RETURN 18
ELSIF ch = "'" THEN RETURN 19
ELSIF ch = "]" THEN RETURN 20
ELSE RETURN 0;
END (*IF*);
END Code;
(************************************************************************)
PROCEDURE PlayPiano;
CONST Esc = CHR(27);
VAR ch: CHAR; note, lastnote: ZeroToTwenty; w: Window;
BEGIN
lastnote := 12;
SetNoteDuration (150);
OpenSimpleWindow (w, 0, 3, 49, 79);
WriteString (w, "Use the Esc key to return the"); WriteLn (w);
WriteString (w, "keyboard to normal operation.");
LOOP
ch := InKey();
IF ch = Esc THEN EXIT(*LOOP*);
ELSIF ch = "b" THEN PlayMusic ("d")
ELSIF ch = "n" THEN PlayMusic ("u")
ELSE
note := Code (ch);
IF note <> 0 THEN
IF INTEGER (note) - INTEGER(lastnote) > 6 THEN
PlayMusic ("u");
ELSIF INTEGER(lastnote) - INTEGER(note) > 6 THEN
PlayMusic ("d");
END (*IF*);
PlayMusic (OutTable[note]);
lastnote := note;
END (*IF*);
END (*IF*);
END (*LOOP*);
CloseWindow (w);
END PlayPiano;
(************************************************************************)
END Piano.