: After more web searching I've found this website which has...
:
......................................................................
:
: Anyone like to take a go at coding this? Let's play the note for 15
: seconds for a simple number.
:
Here's a piece of code which does pretty much what you're looking for except is much more watered down, thus simple:
{ *** Compiler: TP7, works equally with DOSBox or NTVDM *** }
program midi_demo_through_MPU401_chip;
uses crt;
const on=true;
off=false;
octave:shortint=-4; { octave offset }
tempo:word=400; { tempo in msecs }
pc_speaker:boolean=false;{ for testing only }
beat:array[0..9] of real=(
1,2,3,4,0.5,0.333,0.25,0.125,1.333,1.5);
sample_tune:array[1..240] of byte=(
255, 0, 2, 8, 2, 5, 8, 2, 5, 8, 2, 5,
8, 7, 1, 9, 2, 1, 9, 0, 5, 9, 9, 5,
9, 9, 5, 9, 7, 1, 9, 2, 0, 9, 0, 5,
9, 11, 5, 9, 9, 5, 9, 7, 1, 9, 2, 0,
9, 0, 5, 9, 11, 5, 9, 0, 5, 9, 9, 1,
8, 2, 5, 8, 2, 5, 8, 2, 5, 8, 7, 1,
9, 2, 1, 9, 0, 5, 9, 11, 5, 9, 9, 5,
9, 7, 1, 9, 2, 0, 9, 0, 5, 9, 11, 5,
9, 9, 5, 9, 7, 1, 9, 2, 0, 9, 0, 5,
9, 11, 5, 9, 0, 5, 9, 9, 1, 8, 2, 8,
8, 2, 6, 8, 4, 9, 8, 4, 4, 9, 0, 4,
9, 11, 4, 9, 9, 4, 8, 7, 4, 8, 7, 5,
9, 9, 5, 9, 11, 5, 9, 9, 8, 8, 4, 6,
8, 6, 0, 8, 2, 8, 8, 2, 6, 8, 4, 9,
8, 4, 4, 9, 0, 4, 9, 11, 4, 9, 9, 4,
8, 7, 4, 9, 2, 8, 9, 9, 6, 9, 9, 1,
8, 2, 8, 8, 2, 6, 8, 4, 9, 8, 4, 4,
9, 0, 4, 9, 11, 4, 9, 9, 4, 8, 7, 4,
8, 7, 5, 9, 9, 5, 9, 11, 5, 9, 9, 8,
8, 4, 6, 8, 6, 0, 9, 2, 8, 9, 2, 6);
{ Format: octave,note,duration,octave,note,duration,.......
Timing: 0 = beat Octave 0 = -5 Note: C = 0
1 = beat * 2 1 = -4 C# = 1
2 = beat * 3 2 = -3 D = 2
3 = beat * 4 3 = -2 D# = 3
4 = beat / 2 4 = -1 E = 4
5 = beat / 3 5 = 0 F = 5
6 = beat / 4 6 = +1 F# = 6
7 = beat / 8 7 = +2 G = 7
8 = beat / 0.75 8 = +3 G# = 8
9 = beat * 1.5 9 = +4 A = 9
10 = +5 A# = 10
255 = pause B = 11
}
procedure midi_write;assembler;
asm
mov dx,$331
mov cx,ax
sub ax,ax
@1:
dec ah
jz @2
in al,dx
and al,$40
jnz @1
@2:
mov ax,cx
dec dx
out dx,al
end;
procedure midi_reset;assembler;
asm
mov dx,$331
mov al,$ff
out dx,al
mov cx,ax
mov ax,0
@1:
dec ah
jz @2
in al,dx
and al,$80
jnz @1
@2:
mov ax,cx
dec dx
in al,dx
mov al,$3f
inc dx
mov cx,ax
mov ax,0
@3:
dec ah
jz @4
in al,dx
and al,$40
jnz @3
@4:
mov ax,cx
out dx,al
end;
{ Plays a note using the sound card's MPU401 chip }
procedure midi_note(status:boolean;channel,note,volume:byte);assembler;
asm
mov al,channel
add al,$90
mov bl,status
and bl,1
jnz @1
sub al,$10
@1:
call midi_write
mov al,note
call midi_write
mov al,volume
call midi_write
end;
{ Loops a tune, passed down via "t".
Data must be in byte triplets: Octave,Note,Duration format
Single channel only, it is possible to use multiple channels
simultaneously, but w/ timing reworked instead of a simple delay }
procedure loop_tune(var t;l{ength}:word); { length in byte triplets }
var tseg,tofs:word;
i,a,b,c:byte;
ch:char;
ext:boolean;
begin
ext:=false;tseg:=seg(t);tofs:=ofs(t);
repeat for i:=1 to l do begin
a:=mem[tseg:tofs+(i-1)*3];b:=mem[tseg:tofs+(i-1)*3+1];c:=mem[tseg:tofs+(i-1)*3+2];
if a<>255 then
if pc_speaker then sound(100*(a+octave)+b*10) else {<-- freq. is not accurate }
midi_note(on,1,12*(a+octave)+b,127); { channel = 1 , volume = max. }
delay(round(tempo*beat[c]));
if keypressed then if readkey=#27 then begin ext:=true;break;end;
end;until ext;if pc_speaker then nosound;
end;
begin
if not pc_speaker then midi_reset;
writeln('Press: Esc to Quit');
loop_tune(sample_tune,sizeof(sample_tune) div 3);
if not pc_speaker then midi_reset;
end.