unit noiz; { NOIZ.PAS Copyright (c) 1990 DSoft Specialties } interface { Sound routines for the Tandy 1000 and/or PCJr. See NOIZ.SIM } { All I ask is if you use any of these routines in your program please mention DSoft in the docs or in a copyright message } const inturbo: boolean = true; type voices = 0..3; attenuations = 0..15; styles = 1..4; const A1 = 27; A2 = 55; A3 = 110; A4 = 220; A5 = 440; A6 = 880; A7 = 1760; B1 = 31; B2 = 62; B3 = 123; B4 = 247; B5 = 494; B6 = 988; B7 = 1976; C1 = 33; C2 = 65; C3 = 131; C4 = 262; C5 = 523; C6 = 1047; C7 = 2093; D1 = 37; D2 = 74; D3 = 147; D4 = 294; D5 = 588; D6 = 1175; D7 = 2349; E1 = 41; E2 = 83; E3 = 165; E4 = 330; E5 = 660; E6 = 1320; E7 = 2640; F1 = 44; F2 = 88; F3 = 175; F4 = 350; F5 = 700; F6 = 1400; F7 = 2800; G1 = 49; G2 = 98; G3 = 196; G4 = 392; G5 = 784; G6 = 1568; G7 = 3136; A8 = 3520; A9 = 7040; A10 = 14080; B8 = 3952; B9 = 7904; B10 = 15808; C8 = 4160; C9 = 8320; C10 = 16640; D8 = 4704; D9 = 9408; D10 = 18816; E8 = 5280; E9 = 10560; F8 = 5600; F9 = 11200; G8 = 6272; G9 = 12544; AS1 = 29; AS2 = 58; AS3 = 116; AS4 = 231; AS5 = 466; AS6 = 928; AS7 = 1856; CS1 = 34; CS2 = 69; CS3 = 139; CS4 = 277; CS5 = 554; CS6 = 1108;CS7 = 2240; DS1 = 39; DS2 = 78; DS3 = 156; DS4 = 311; DS5 = 622; DS6 = 1244;DS7 = 2496; FS1 = 46; FS2 = 93; FS3 = 185; FS4 = 370; FS5 = 740; FS6 = 1480;FS7 = 2960; GS1 = 26; GS2 = 52; GS3 = 208; GS4 = 415; GS5 = 830; GS6 = 1660;GS7 = 3320; AS8 = 3712; AS9 = 7424; AS10 = 14848; CS8 = 4480; CS9 = 8960; CS10 = 17920; DS8 = 4992; DS9 = 9984; DS10 = 19968; FS8 = 5920; FS9 = 11840; GS8 = 6640; GS9 = 13280; const stacatto: boolean = false; legato: boolean = false; zetto: boolean = false; xetto: boolean = false; dtime: integer = 80; procedure wait(dt: longint); procedure delay(dt: longint); procedure sound(freq: word); procedure nosound; procedure sound_level(voice: voices;atten: attenuations); procedure sound_period(voice: voices;period: integer); procedure sound_pitch(voice: voices;freq: real); procedure sound_off; procedure extsound(freq,dur: integer;level: attenuations;voice: voices); procedure plays(freq,dur: word;attack,decay: integer;voice: voices); procedure chord(freq1,freq2,freq3,dur,level: integer); procedure play(freq,dur: integer;v: voices;style: styles); procedure noise(ch: char;sr,atten,dur: word); procedure note1(freq,dura: word); procedure note4(note,dura: integer); procedure dubend(freq1,freq2,dt: integer); procedure bend(tone,tone1,tonedur,dur,reps: integer); procedure scale(freq1,freq2,freq3: integer;a,b,c,d,e,f,g,aa: integer); procedure scale2(a,b,c,d,e,f,g,z: integer;dtime,attack,decay: integer; v: voices); procedure snd(freq: integer); procedure snd2(freq: integer); procedure nosnd; procedure nosnd2; procedure quiet; function fkey: char; function keyhit: boolean; implementation uses dos; procedure wait(dt: longint); const inturb = 32; indos = 60; var tt,ir,tr: longint; begin if inturbo then tt:=inturb else tt:=indos; for ir:=1 to dt do for tr:=1 to tt do end; procedure delay(dt: longint); begin wait(dt); end; {$F+} procedure sound(freq: word); begin inline( $8B/$5E/$06/$B8/$DD/$34/ $BA/$12/$00/$39/$DA/ $73/$1A/$F7/$F3/$89/$C3/ $E4/$61/$A8/$03/$75/$08/ $0C/$03/$E6/$61/$B0/$B6/ $E6/$43/$88/$D8/$E6/$42/ $88/$F8/$E6/$42); end; {$F-} procedure nosound; begin inline($E4/$61/$24/$FC/$E6/$61); end; procedure sound_level(voice: voices;atten: attenuations); { change the level (atten) of a voice } begin if (atten < 0) then atten:=0 else if (atten > 15) then atten:=15; port[$C0]:=($90 + (voice shl 5) + (atten and $0F)); end; procedure sound_period(voice: voices;period: integer); { change the sound divider (period) of a voice } begin port[$C0]:=($80 + (voice shl 5) + (period and $0F)); { lo 4 bits } port[$C0]:=((period shr 4) and $3F); { hi 6 bits } end; procedure sound_pitch(voice: voices;freq: real); { change the pitch (freq) of a voice } var period: real; function chip_freq(freq: real): word; begin chip_freq:=round(((3.579 * 1000000) / (freq * 32))); end; begin if (freq = 0.0) then period:=0 else period:=chip_freq(freq); if (period <= 1) or (period > $3FF) then period:=1; sound_period(voice,round(period)); end; procedure sound_off; var v: voices; begin for v:=0 to 3 do begin sound_level(v,15); sound_pitch(v,0); end; end; procedure extsound(freq,dur: integer;level: attenuations;voice: voices); begin sound_level(voice,level div 4); if ((freq < A3) or (voice = 3)) then sound(freq) else sound_pitch(voice,freq); wait(dur); end; procedure plays(freq,dur: word;attack,decay: integer;voice: voices); var i,j,k: integer; begin if (dur < 4) then dur:=4; if (freq < A3) then begin sound(freq); wait(dur); end else begin sound_pitch(voice,freq); for i:=attack downto 0 do begin sound_level(voice,i); wait(2); end; wait(dur-(attack-decay)-4); for i:=0 to decay do begin sound_level(voice,i); wait(2); end; end; end; procedure chord(freq1,freq2,freq3,dur,level: integer); var i,j,k: integer; begin if (level > 15) then begin for i:=15 downto (level - 15) do begin extsound(freq1,dur div 2,i,0); extsound(freq2,dur div 2,i,1); extsound(freq3,dur div 2,i,2); end; extsound(freq1,dur,level,0); extsound(freq2,dur,level,1); extsound(freq3,dur,level,2); wait(dur); exit; end else for i:=1 to level do begin extsound(freq1,dur div 2,i,0); extsound(freq2,dur div 2,i,1); extsound(freq3,dur div 2,i,2); end; extsound(freq1,dur,level,0); extsound(freq2,dur,level,1); extsound(freq3,dur,level,2); wait(dur); end; procedure play(freq,dur: integer;v: voices;style: styles); var zz,z,x,xx,i: integer; begin x:=dur div 3; xx:=dur div 2; z:=xx-x; zz:=x div 2; case style of 1: begin extsound(freq,z,3,v); for i:=15 downto 1 do extsound(freq,zz,i,v); for i:=1 to 13 do extsound(freq,zz,i,v); extsound(freq,xx,2,v); exit; end; 2: begin extsound(freq,xx+z,4,v); for i:=1 to 15 do begin extsound(freq,zz,5 xor i,v); if (v >= 2) then extsound(freq,zz,i,v-1) else extsound(freq,zz,i,v+1); end; exit; end; 3: begin for i:=15 downto 1 do begin extsound(freq*2,1,i,v); if (v >=2) then extsound(freq,zz,i,v-1) else extsound(freq,zz,i,v+1); end; extsound(freq,zz,10,v); for i:=15 downto 7 do extsound(freq,zz,i,v); extsound(freq,xx,2,v); exit; end; 4: begin for i:=0 to 15 do extsound(freq,1,i,v); for i:=15 downto 0 do begin if (v >= 2) then extsound(freq*2,zz,i,v-1) else extsound(freq*2,zz,i,v+1); end; for i:=7 to 15 do extsound(freq,zz,i,v); extsound(freq,xx,10,v); exit; end; end; end; procedure noise(ch: char;sr,atten,dur: word); var portpass1: integer; begin portpass1:=224; if (ch in ['W','w']) then portpass1:=portpass1 + 4; case sr of 10: portpass1:=portpass1 + 1; 20: portpass1:=portpass1 + 2; end; port[$C0]:=240+atten; port[$C0]:=portpass1; wait(dur); end; procedure note1(freq,dura: word); var x: integer; begin if keyhit then begin quiet; exit; end; if (legato=true) then begin sound(freq); wait(dura-7); sound(freq); wait(7); end else if (stacatto=true) then begin sound(freq); wait(dura-11); nosound; wait(11); end else if (zetto=true) then begin x:=dura div 3; sound(freq); wait(x); nosound; wait(x*2); end else if (xetto=true) then begin x:=dura div 5; sound(freq); wait(x); nosound; wait(x*4); end else begin sound(freq); wait(dura); nosound; end; end; procedure note4(note,dura: integer); var x: integer; begin if keyhit then begin quiet; exit; end; if (legato=true) then begin extsound(note,dura-7,0,0); extsound(note,7,0,0); end else if (stacatto=true) then begin extsound(note,dura-11,0,0); sound_level(1,15); wait(11); end else if (zetto=true) then begin x:=dura div 3; extsound(note,x,0,0); sound_level(1,15); wait(x*2); end else if (xetto=true) then begin x:=dura div 5; extsound(note,x,0,0); sound_level(1,15); wait(x*4); end else begin extsound(note,dura,0,0); sound_level(1,15); end; end; procedure dubend(freq1,freq2,dt: integer); var i: integer; begin for i:=freq1 to freq2 do extsound(i,dt,1,0); sound_level(0,15); end; procedure bend(tone,tone1,tonedur,dur,reps: integer); var i,j: integer; begin if (tone1 > tone) then begin for i:=1 to reps do begin extsound(tone1,tonedur,1,0); dubend(tone,tone1,dur); sound_level(0,15); wait(10); end; end else if (tone > tone1) then begin for i:=1 to reps do begin for j:=tone downto tone1 do extsound(j,dur,1,0); extsound(tone1,tonedur,1,0); end; sound_level(0,15); end; end; procedure scale(freq1,freq2,freq3: integer;a,b,c,d,e,f,g,aa: integer); begin chord(freq1,freq2,freq3,1,5); if (freq1 >= A3) then begin note1(a,dtime); note1(b,dtime); note1(c,dtime); note1(d,dtime); note1(e,dtime); note1(f,dtime); note1(g,dtime); note1(aa,dtime); end else if (freq1 < A3) then begin note4(a,dtime); note4(b,dtime); note4(c,dtime); note4(d,dtime); note4(e,dtime); note4(f,dtime); note4(g,dtime); note4(aa,dtime); end; quiet; end; procedure scale2(a,b,c,d,e,f,g,z: integer;dtime,attack,decay: integer; v: voices); begin plays(a,dtime,attack,decay,v); plays(b,dtime,attack,decay,v); plays(c,dtime,attack,decay,v); plays(d,dtime,attack,decay,v); plays(e,dtime,attack,decay,v); plays(f,dtime,attack,decay,v); plays(g,dtime,attack,decay,v); plays(z,dtime,attack,decay,v); end; procedure snd(Freq: integer); var Count: integer; begin Count:=$1B1AAA div Freq; Port[$C0]:=$A5; port[$C0]:=$15; port[$C0]:=$A0; port[$C0]:=$A5; port[$C0]:=hi(count); port[$C0]:=$A0; end; procedure snd2(Freq: integer); var Count: integer; begin Count:=$1B1AAA div Freq; Port[$C0]:=$C5; port[$C0]:=$15; port[$C0]:=$C0; port[$C0]:=$C5; port[$C0]:=hi(count); port[$C0]:=$C0; end; procedure Nosnd; var sport: Byte; begin SPort:=Port[$C0]; port[$C0]:=$BF; end; procedure Nosnd2; var sport: Byte; begin SPort:=Port[$C0]; port[$C0]:=$DF; port[$C0]:=$BF; end; procedure quiet; begin nosound; nosnd; nosnd2; sound_off; port[$C0]:=$9F; end; function fkey: char; var regs: registers; begin regs.AH:=0; intr($16,regs); if regs.AL=0 then fkey:=chr(regs.AH+128) else fkey:=chr(regs.AL) end; function keyhit: boolean; var regs: registers; begin regs.AH:=1; intr($16,regs); keyhit:=(regs.flags and 64)=0; end; end.