packages feed

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.