home *** CD-ROM | disk | FTP | other *** search
- { (c) 1984 by Neil J. Rubenking }
- program IBMPiano;
- type
- NoteRecord = record
- C,CS,D,DS,E,F,FS,G,GS,A,AS,B: integer;
- end;
- Locations = array[39..122] of byte;
- FiledNote = record
- Octave, Note, Duration : integer;
- end;
- Score = ^item;
- item = record
- Note : FiledNote;
- next : Score;
- end;
- Const
- Notes: NoteRecord =
- (C:1;CS:2;D:3;DS:4;E:5;F:6;FS:7;G:8;GS:9;A:10;AS:11;B:12);
- var
- ToggleByte : byte absolute $0040:$0017;
- done, recording,
- VeryFirst : boolean;
- octave, duration,
- NoteNum : integer;
- XLoci, YLoci : Locations;
- ScreenSeg : integer;
- LastKey : char;
- style : byte;
- MusicFile : file of FiledNote;
- List, Pointer,
- EndPointer : Score;
- LastTime : real;
- {«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«}
- procedure DisposeAll(var List : Score);
- begin
- if List <> nil then
- begin
- DisposeAll(List^.next);
- dispose(List);
- end;
- List := nil;
- LastTime := 0;
- end;
- {«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«}
- procedure Attribute(row,startx,endx,att:byte);
- var
- LocationCode : integer;
- N : byte;
- begin
- for N := startx to endx do
- begin
- LocationCode := (N-1)*2 + (row-1)*160;
- Mem[ScreenSeg:locationCode+1] := att;
- end;
- end;
- {«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«}
- function time: real;
- type
- regpack = record
- ax,bx,cx,dx,bp,di,si,ds,es,flags: integer;
- end;
-
- var
- recpack: regpack; {assign record}
- ah,al,ch,cl,dh: byte;
- hour,min,sec,hund : byte;
-
- begin
- ah := $2c; {initialize correct registers}
- with recpack do
- begin
- ax := ah shl 8 + al;
- end;
- intr($21,recpack); {call interrupt}
- with recpack do
- begin
- hour := cx shr 8;
- min := cx mod 256;
- sec := dx shr 8;
- hund := dx mod 256;
- end;
- time := hund/100 + sec + 60*min;
- end;
- {«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«}
- procedure recorder(AnOctave,ANote : integer);
- var
- ThisDur, ThisTime : real;
- NoteToAdd : FiledNote;
- {----------------------------------------------------}
- procedure AddNote(ItemToAdd:FiledNote);
- begin
- if VeryFirst then
- begin
- new(List);
- List^.Note := ItemToAdd;
- List^.next := nil;
- EndPointer := List;
- VeryFirst := false;
- end
- else
- begin
- new(EndPointer^.next);
- EndPointer := EndPointer^.next;
- EndPointer^.Note := ItemToAdd;
- EndPointer^.next := nil;
- end;
- end;
- {----------------------------------------------------}
- begin
- ThisTime := time;
- ThisDur := ThisTime - LastTime;
- ThisDur := ThisDur * 500;
- if NoteNum > 1 then
- begin
- with NoteToAdd do
- begin
- Octave := AnOctave;
- note := ANote;
- Duration := trunc(ThisDur);
- end;
- AddNote(NoteToAdd);
- end;
- NoteNum := NoteNum + 1;
- Attribute(4,60,62,112);
- LastTime := ThisTime;
- end;
- {«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«}
- procedure Play(Octave,Note,Duration: integer);
- var
- Frequency: real;
- I: integer;
- begin
- if ToggleByte and 16 = 16 then duration := 0;
- Frequency:=32.625;
- for I:=1 to Octave do Frequency:=Frequency*2;
- for I:=1 to Note-1 do Frequency:=Frequency*1.059463094;
- if Duration<>0 then
- begin
- Sound(Round(Frequency));
- Delay(Duration);
- NoSound;
- end else Sound(Round(Frequency));
- end;
- {«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«}
- procedure PlayBack;
- begin
- Pointer := List;
- while Pointer <> nil do
- begin
- with Pointer^.Note do
- play(Octave,Note,Duration);
- Pointer := Pointer^.next;
- end;
- NoSound;
- end;
- {«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«}
- procedure convert(Letter : char;var note, AnOctave : integer);
- begin
- note := 0;
- AnOctave := octave;
- with notes do
- begin
- case Letter of
- 'q': note := Notes.C;
- 'w': note := Notes.D;
- 'e': note := Notes.E;
- 'r': note := Notes.F;
- 't': note := Notes.G;
- 'y': note := Notes.A;
- 'u': note := Notes.B;
- 'i': begin
- note := Notes.C;
- AnOctave := AnOctave + 1;
- end;
- 'o': begin
- note := Notes.D;
- AnOctave := AnOctave + 1;
- end;
- 'p': begin
- note := Notes.E;
- AnOctave := AnOctave + 1;
- end;
- '[': begin
- note := Notes.F;
- AnOctave := AnOctave + 1;
- end;
- ']': begin
- note := Notes.G;
- AnOctave := AnOctave + 1;
- end;
- '2': note := Notes.CS;
- '3': note := Notes.DS;
- '5': note := Notes.FS;
- '6': note := Notes.GS;
- '7': note := Notes.AS;
- '9': begin
- note := Notes.CS;
- AnOctave := AnOctave + 1;
- end;
- '0': begin
- note := Notes.DS;
- AnOctave := AnOctave + 1;
- end;
- '=': begin
- note := Notes.FS;
- AnOctave := AnOctave + 1;
- end;
- '\': begin
- note := Notes.F;
- AnOctave := AnOctave - 2
- end;
- 'z': begin
- note := Notes.G;
- AnOctave := AnOctave - 2
- end;
- 'x': begin
- note := Notes.A;
- AnOctave := AnOctave - 2
- end;
- 'c': begin
- note := Notes.B;
- AnOctave := AnOctave - 2
- end;
- 'v': begin
- note := Notes.C;
- AnOctave := AnOctave - 1;
- end;
- 'b': begin
- note := Notes.D;
- AnOctave := AnOctave - 1;
- end;
- 'n': begin
- note := Notes.E;
- AnOctave := AnOctave - 1;
- end;
- 'm': begin
- note := Notes.F;
- AnOctave := AnOctave - 1;
- end;
- ',': begin
- note := Notes.G;
- AnOctave := AnOctave - 1;
- end;
- '.': begin
- note := Notes.A;
- AnOctave := AnOctave - 1;
- end;
- '/': begin
- note := Notes.B;
- AnOctave := AnOctave - 1;
- end;
- 'a': begin
- note := Notes.FS;
- AnOctave := AnOctave - 2;
- end;
- 's': begin
- note := Notes.GS;
- AnOctave := AnOctave - 2;
- end;
- 'd': begin
- note := Notes.AS;
- AnOctave := AnOctave - 2;
- end;
- 'g': begin
- note := Notes.CS;
- AnOctave := AnOctave - 1;
- end;
- 'h': begin
- note := Notes.DS;
- AnOctave := AnOctave - 1;
- end;
- 'k': begin
- note := Notes.FS;
- AnOctave := AnOctave - 1;
- end;
- 'l': begin
- note := Notes.GS;
- AnOctave := AnOctave - 1;
- end;
- ';': begin
- note := Notes.AS;
- AnOctave := AnOctave - 1;
- end;
- end; {case}
- end; {with notes}
- end; {procedure}
- {«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«}
- procedure LightUp(Letter:char);
- var
- LocationCode : integer;
- begin
- if (Xloci[Ord(Letter)] > 1) then
- begin
- LocationCode := (Xloci[ord(Letter)]-1)*2 + (Yloci[Ord(Letter)]-1)*160;
- Mem[ScreenSeg:locationCode+1] := 112;
- end;
- LocationCode := (Xloci[ord(LastKey)]-1)*2 + (Yloci[Ord(LastKey)]-1)*160;
- Mem[ScreenSeg:locationCode+1] := 15;
- end;
- {«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«}
- procedure ShowLegato(On: boolean);
- var
- col, row, M : byte;
- LocationCode : integer;
- word : string[6];
- begin
- row := 2;
- if On then M := 112 else M := 15;
- if On then word := 'legato' else word := ' ';
- for col := 1 to 6 do
- begin
- LocationCode := (col + 66)*2 + (row-1)*160;
- Mem[ScreenSeg:LocationCode] := ord(word[col]);
- Mem[ScreenSeg:LocationCode+1] := M;
- end;
- end;
- {«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«}
- procedure GetKeys;
- var
- C, D : char;
- legato : boolean;
- oldToggle : byte;
- ThisNote, ThisOctave : integer;
- begin
- OldToggle := ToggleByte;
- repeat until keypressed;
- read(Kbd,C);
- if C = chr(27) then
- begin
- read(Kbd,D);
- case D of
- 'H': Octave := Octave + 1;{up arrow}
- 'P': Octave := Octave - 1;{down arrow}
- 'M': duration := duration + 10; {left arrow}
- 'K': if duration > 10 then duration := duration - 10; {right}
- 'O': done := true; {end}
- 'G': begin
- if recording then
- begin
- convert(LastKey,ThisNote,ThisOctave);
- recorder(ThisOctave,ThisNote);
- LastTime := 0;
- NoteNum := 0;
- end;
- recording := recording xor true;
- end;
- 'R': begin
- Attribute(10,57,60,112);
- PlayBack;
- Attribute(10,57,60,15);
- end;
- 'S': begin
- disposeAll(List);
- VeryFirst := true;
- end;
- end;
- end
- else
- begin
- LightUp(C);
- convert(C,ThisNote,ThisOctave);
- if ThisNote <> 0 then
- play(ThisOctave,ThisNote,duration);
- if recording then convert(LastKey,ThisNote,ThisOctave);
- LastKey := C;
- end;
- if ToggleByte and 16 = 16 then legato := true else legato := false;
- if recording then
- begin
- recorder(ThisOctave,ThisNote);
- end
- else
- begin
- Attribute(4,60,62,15);
- end;
- ShowLegato(legato);
- gotoXY(1,26);
- end;
- {«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«}
- procedure SetLocations;
- var
- N : byte;
- begin
- for N := 39 to 122 do
- begin
- Xloci[N] := 1;
- Yloci[N] := 1;
- end;
- Yloci[50] := 2; Xloci[50] := 11;
- Yloci[51] := 2; Xloci[51] := 15;
- Yloci[53] := 2; Xloci[53] := 23;
- Yloci[54] := 2; Xloci[54] := 27;
- Yloci[55] := 2; Xloci[55] := 31;
- Yloci[57] := 2; Xloci[57] := 39;
- Yloci[48] := 2; Xloci[48] := 43;
- Yloci[61] := 2; Xloci[61] := 51;
- Yloci[113] := 4; Xloci[113] := 8;
- Yloci[119] := 4; Xloci[119] := 12;
- Yloci[101] := 4; Xloci[101] := 16;
- Yloci[114] := 4; Xloci[114] := 20;
- Yloci[116] := 4; Xloci[116] := 24;
- Yloci[121] := 4; Xloci[121] := 28;
- Yloci[117] := 4; Xloci[117] := 32;
- Yloci[105] := 4; Xloci[105] := 36;
- Yloci[111] := 4; Xloci[111] := 40;
- Yloci[112] := 4; Xloci[112] := 44;
- Yloci[91] := 4; Xloci[91] := 48;
- Yloci[93] := 4; Xloci[93] := 52;
- Yloci[97] := 6; Xloci[97] := 9;
- Yloci[115] := 6; Xloci[115] := 13;
- Yloci[100] := 6; Xloci[100] := 17;
- Yloci[103] := 6; Xloci[103] := 25;
- Yloci[104] := 6; Xloci[104] := 29;
- Yloci[107] := 6; Xloci[107] := 37;
- Yloci[108] := 6; Xloci[108] := 41;
- Yloci[59] := 6; Xloci[59] := 45;
- Yloci[92] := 8; Xloci[92] := 8;
- Yloci[122] := 8; Xloci[122] := 12;
- Yloci[120] := 8; Xloci[120] := 16;
- Yloci[99] := 8; Xloci[99] := 20;
- Yloci[118] := 8; Xloci[118] := 24;
- Yloci[98] := 8; Xloci[98] := 28;
- Yloci[110] := 8; Xloci[110] := 32;
- Yloci[109] := 8; Xloci[109] := 36;
- Yloci[44] := 8; Xloci[44] := 40;
- Yloci[46] := 8; Xloci[46] := 44;
- Yloci[47] := 8; Xloci[47] := 48;
- end;
- {«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«}
- procedure DrawKeyboard;
- begin
- WriteLn('╔═══╤═══╤═══╤═══╤═══╤═══╤═══╤═══╤═══╤═══╤═══╤═══╤═══╤═════╤═══════╤═══════╗');
- WriteLn('║ │ │ C#│ D#│ │ F#│ G#│ A#│ │ C#│ D#│ │ F#│ │ │ ║');
- WriteLn('╟───┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴─┬───┼───┬───┼───┬───╢');
- WriteLn('║ │ C │ D │ E │ F │ G │ A │ B │ C │ D │ E │ F │ G │ │Rec│ ',chr(24),' │ │ ║');
- WriteLn('╟────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬───┤ ├───┼───┼───┼───╢');
- WriteLn('║ │ F#│ G#│ A#│ │ C#│ D#│ │ F#│ G#│ A#│ │ │ │ ',chr(27),' │ │ ',chr(26),' │ ║');
- WriteLn('╟────┬┴──┬┴──┬┴──┬┴──┬┴──┬┴──┬┴──┬┴──┬┴──┬┴──┬┴──┬┴───┼───┼───┼───┼───┤ ║');
- WriteLn('║ │ F │ G │ A │ B │ C │ D │ E │ F │ G │ A │ B │ │ │End│ ',chr(25),' │ │ ║');
- WriteLn('╟────┴──┬┴───┴───┴───┴───┴───┴───┴───┴───┴───┴──┬┴────┼───┴───┼───┴───┤ ║');
- WriteLn('║ │ │ │ Play │ Erase │ ║');
- WriteLn('╚═══════╧═══════════════════════════════════════╧═════╧═══════╧═══════╧═══╝');
- WriteLn;
- WriteLn('Up and Down arrows control the octave.');
- WriteLn;
- WriteLn('Right and Left arrows control note duration--right is shorter.');
- WriteLn;
- WriteLn('The Scroll Lock turns legato on and off. The change takes effect');
- WriteLn(' on the NEXT note.');
- WriteLn;
- WriteLn('Home turns recording on and off, Ins plays back, and Del erases.');
- WriteLn;
- WriteLn('Press <End> to end');
- end;
- {«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«}
- procedure initialize;
- begin
- IF (Mem[0000:1040] AND 48) <> 48 THEN ScreenSeg := $B800
- ELSE ScreenSeg := $B000;
- Octave := 3;
- LastTime := 0;
- duration := 50;
- done := false;
- recording := false;
- VeryFirst := true;
- NoteNum := 0;
- style := 0;
- SetLocations;
- DrawKeyboard;
- List := nil;
- LastTime := 0;
- end;
- {«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«}
- begin
- initialize;
- repeat GetKeys until done;
- NoSound;
- ClrScr;
- end.