packages feed

language-Modula2-0.1: examples/Modula-2_Libraries/PMOS/sources/util/playmake.mod

MODULE PlayMake;

	(********************************************************)
	(*							*)
	(*	Program to make some tables needed for		*)
	(*	playing music.  The data file produced		*)
	(*	by this program can be incorporated into	*)
	(*	an assembly language source file.		*)
	(*							*)
	(*  Programmer:		P. Moylan			*)
	(*  Last edited:	15 March 1995			*)
	(*  Status:		Working				*)
	(*							*)
	(********************************************************)

FROM FileSys IMPORT
    (* type *)	File,
    (* proc *)	OpenFile, CloseFile, WriteRecord;

FROM IOErrorCodes IMPORT
    (* type *)	ErrorCode,
    (* proc *)	TranslateErrorCode;

FROM Conversions IMPORT
    (* proc *)	ShortCardToString, CardinalToString;

FROM Windows IMPORT
    (* type *)	Window, Colour, FrameType, DividerType,
    (* proc *)	OpenWindow, CloseWindow, WriteString, WriteLn,
		ReadChar, PressAnyKey;

FROM MATHLIB IMPORT
    (* proc *)	Exp, Log, Sin;

(************************************************************************)

TYPE Note = SHORTCARD [0..63];

VAR
    log: Window;
    linecount: CARDINAL;
    CRLF: ARRAY [0..1] OF CHAR;

(************************************************************************)

PROCEDURE SendByteToFile (f: File;  value: SHORTCARD);

    (* Writes one value to the file, with a new line every eight values.*)

    VAR buffer: ARRAY [0..31] OF CHAR;
	status: ErrorCode;

    BEGIN
	status := OK;
	IF linecount = 8 THEN
	    buffer := "   db ";
	    buffer[0] := CHR(13);  buffer[1] := CHR(10);
	    buffer[2] := CHR(9);  buffer[5] := CHR(9);
	    status := WriteRecord (f, ADR(buffer), 6);
	    linecount := 0;
	ELSE
	    buffer := ",";
	    status := WriteRecord (f, ADR(buffer), 1);
	END (*IF*);
	IF status = OK THEN
	    ShortCardToString (value, buffer, 4);
	    status := WriteRecord (f, ADR(buffer), 4);
	END (*IF*);
	INC (linecount);
	IF status <> OK THEN
	    TranslateErrorCode (status, buffer);
	    WriteString (log, buffer);
	END (*IF*);
    END SendByteToFile;

(************************************************************************)

PROCEDURE SendWordToFile (f: File;  value: CARDINAL);

    (* Writes one value to the file, with a new line every eight values.*)


    VAR buffer: ARRAY [0..31] OF CHAR;
	status: ErrorCode;

    BEGIN
	status := OK;
	IF linecount = 8 THEN
	    buffer := "   dw ";
	    buffer[0] := CHR(13);  buffer[1] := CHR(10);
	    buffer[2] := CHR(9);  buffer[5] := CHR(9);
	    status := WriteRecord (f, ADR(buffer), 6);
	    linecount := 0;
	ELSE
	    buffer := ",";
	    status := WriteRecord (f, ADR(buffer), 1);
	END (*IF*);
	IF status = OK THEN
	    CardinalToString (value, buffer, 6);
	    status := WriteRecord (f, ADR(buffer), 6);
	END (*IF*);
	INC (linecount);
	IF status <> OK THEN
	    TranslateErrorCode (status, buffer);
	    WriteString (log, buffer);
	END (*IF*);
    END SendWordToFile;

(************************************************************************)

PROCEDURE MakeDataFile;

    (* Initialises the global data. *)

    CONST PI =  3.141592653589793240;

    VAR step, scale: LONGREAL;
	j, value: SHORTCARD;  note: Note;
	ch: CHAR;
	f: File;  status: ErrorCode;
	buffer: ARRAY [0..31] OF CHAR;

    BEGIN
	(* Open the data file. *)

	status := OpenFile (f, "PLAYDATA.TXT", TRUE);
	IF status = DuplicateFileName THEN
	    WriteString (log, "PLAYDATA.TXT already exists.  Overwrite? ");
	    ReadChar (log, ch);
	    WriteLn (log);
	    IF CAP(ch) = 'Y' THEN
		status := OpenFile (f, "PLAYDATA.TXT", FALSE);
	    END (*IF*);
	END (*IF*);
	IF status <> OK THEN
	    TranslateErrorCode (status, buffer);
	    WriteString (log, buffer);
	    PressAnyKey (log);
	    RETURN;
	END (*IF*);

	(* Create the note-to-interval map. *)

	buffer := "    StepTable:";
	status := WriteRecord (f, ADR(buffer), 14);
	IF status <> OK THEN
	    TranslateErrorCode (status, buffer);
	    WriteString (log, buffer);
	    PressAnyKey (log);
	    RETURN;
	END (*IF*);

	linecount := 8;

	scale := Exp(Log(2.0)/12.0);
	step := 110.0;
	SendWordToFile (f, 0);
	FOR note := 1 TO MAX(Note) DO
	    SendWordToFile (f, VAL(CARDINAL, step));
	    step := step*scale;
	END (*FOR*);

	(* Create the waveform array. *)

	status := WriteRecord (f, ADR(CRLF), 2);
	IF status = OK THEN
	    status := WriteRecord (f, ADR(CRLF), 2);
	END (*IF*);
	IF status = OK THEN
	    buffer := "    Wave:";
	    status := WriteRecord (f, ADR(buffer), 9);
	END (*IF*);
	IF status <> OK THEN
	    TranslateErrorCode (status, buffer);
	    WriteString (log, buffer);
	    PressAnyKey (log);
	    RETURN;
	END (*IF*);

	linecount := 8;

	FOR j := 0 TO 255 DO
	    value := VAL(SHORTCARD,
			42.0*(1.0 + Sin(VAL(LONGREAL,j)*PI/128.0)));
	    SendByteToFile (f, value);
	END (*FOR*);
	status := WriteRecord (f, ADR(CRLF), 2);

	CloseFile (f);

    END MakeDataFile;

(************************************************************************)

BEGIN
    CRLF[0] := CHR(13);  CRLF[1] := CHR(10);
    OpenWindow (log, blue, cyan, 2,22, 2,77, simpleframe, nodivider);
    MakeDataFile;
    CloseWindow (log);
END PlayMake.