;********************************
;       MUSIK IN ACTION!
;
; PETER FINZEL               1995
;********************************

DEFINE B2 ="255",
       C3 ="242", CIS3="229",
       D3 ="216", DIS3="204",
       E3 ="193",
       F3 ="182", FIS3="172",
       G3 ="162", GIS3="153", 
       A3 ="145", AIS3="137", 
       B3 ="129",
       C4 ="122", CIS4="115", 
       D4 ="108", DIS4="102",
       E4 = "97", 
       F4 = "91", FIS4= "86",
       G4 = "81", GIS4= "77", 
       A4 = "72", AIS4= "68", 
       B4 = "65", 
       C5 = "61", CIS5= "58", 
       D5 = "54", DIS5= "51", 
       E5 = "48",
       F5 = "46", FIS5= "43", 
       G5 = "41", GIS5= "38", 
       A5 = "36", AIS5= "34", 
       B5 = "32"

DEFINE HA="120", VI="60",
       AC= "30", SE="15", 
       HP="180", VP="90",
       AP= "45",  
       PA=  "0", EN= "1"
 
DEFINE Pause="0", Attack ="1", 
       Decay="2", Sustain="3" 

;================================
;Ab hier stehen die Noten 
;================================
;
;MENUETT NR.2 
;

BYTE ARRAY N1=[
C4:VI G4:VI G4:AC F4:AC
E4:VI D4:AC E4:AC C4:VI
A4:AC G4:AC F4:AC E4:AC D4:AC C4:AC
B3:VI A3:AC B3:AC G3:VI
F4:VI F4:VI F4:VI
E4:VI E4:VI E4:VI
E4:VI G4:AC F4:AC E4:AC D4:AC
C4:HP

E4:AC C4:AC G4:AC C4:AC E4:AC C4:AC
D4:AC B3:AC G4:AC B3:AC D4:AC B3:AC
C4:AC D4:AC C4:AC B3:AC A3:AC G3:AC
FIS3:VI E3:AC FIS3:AC D3:VI
C4:VI C4:VI C4:VI
B3:VI B3:VI B3:VI
B3:VI D4:AC C4:AC B3:AC A3:AC
G3:HP EN:0 ]
 
BYTE ARRAY N2=[
C3:VI C3:VI C3:VI
C3:HP
F3:VI D3:VI F3:VI
G3:VI D3:VI G3:VI
D4:VI D4:VI D4:VI
C4:VI C4:VI C4:VI 
C3:VI E3:VI G3:VI
C4:VI G3:VI C3:VI 

C4:VI G3:VI C4:VI 

B3:VI G3:VI B3:VI
A3:VI E3:VI C3:VI
D3:VI PA:VI PA:VI 
A3:VI D3:VI D3:VI
G3:VI D3:VI D3:VI
G3:HA D3:VI
G3:AC A3:AC G3:AC F3:AC E3:AC D3:AC
EN:0 ]

BYTE ARRAY N3=[
EN:0 ] 

BYTE ARRAY N4=[
EN:0 ] 

BYTE ARRAY
;KANAL   -1- -2- -3- -4-
Att(4)=[ 070 030 000 000 ],
Dec(4)=[ 008 004 000 000 ],
Sus(4)=[ 040 032 000 000 ],
Max(4)=[ 200 140 000 000 ],
Dis(4)=[ 010 010 010 008 ],
Off(4)=[ 000 000 000 000 ]

BYTE TEMPO=[ 125 ]

;*********************************** 
;Interne Variable 
;*********************************** 
BYTE         SKCTL =$D20F, 
             AUDCTL=$D208 
CARD ARRAY   NOTENZ(4)
BYTE ARRAY   DAUER (4), LAUT (4), 
             FREQ  (4), HKFlg(4) 
BYTE ARRAY   AUDF(8)=$D200, 
             AUDC(8)=$D201 
BYTE         ENDE
BYTE POINTER N_Ptr


;***********************************
;Vorbereitungsprogramm 
;
;Initialisierung der Notenzeiger 
;***********************************

PROC Vorbereitung()
  BYTE i
  NOTENZ(0)=N1 NOTENZ(1)=N2
  NOTENZ(2)=N3 NOTENZ(3)=N4

  FOR i=0 TO 3
    DO
    Dauer(i)=0
    Freq(i)=0
    LAUT(i)=0
  OD 
  SKCTL =3
  AUDCTL=0
RETURN 

;***********************************
;Eintragen in Hardware-Register
;
;Die Werte Laut(i), Freq(i) und 
;Dis(i) werden verknuepft und in
;die Audio-Register eingetragen 
;***********************************

PROC Hardware(BYTE i)
  BYTE j,d

  j=i LSH 1
  d=Dis(i) LSH 4
  AUDC(j)=(Laut(i) RSH 4) % d
  AUDF(j)=Freq(i)
RETURN 

;**********************************
;Befehle zur Tonaenderung
;
;Pausen und der Befehl zum Beenden
;einer Stimme werden hier bearbeitet
;*********************************** 

PROC Befehl (BYTE i,f,d)

  IF f=PA THEN      ;Pause 
    Dauer(i)=d 
    Laut(i) =0 
    Freq(i) =0 
    NotenZ(i)==+2 
    HKFlg(i)=Pause 
  ELSEIF f=EN THEN  ;Ende 
    Laut(i)=0 
    Freq(i)=0 
    HKFlg(i)=Pause 
    ENDE==-1  
  FI 
RETURN 

;************************************
;Spielen einer Stimme
;
;Besorgt Frequenz und Timing einer 
;Note eines Kanales 
;************************************ 

PROC STIMME(BYTE i) 
  BYTE f,d 

  IF Dauer(i)>1 THEN 
    Dauer(i)==-1      ;Note dauert an 
  ELSE
    f=N_ptr^          ;neue Frequenz 
    N_Ptr==+1         ;und Dauer 
    d= N_ptr^ 

    IF f<=1 THEN
      Befehl(i,f,d)
    ELSE
      Freq(i)  =f
      Dauer(i) =d
      Laut(i)  =0 
      HKFlg(i) =Attack 
      NotenZ(i)==+2
      Freq(i)  ==+Off(i)
    FI
  FI 
RETURN  

;***********************************
;Huellkurve bearbeiten
;Berechnet die Huellkurve nach dem 
;ADS-Verfahren(Attac/Decay/Sustain)
;***********************************
PROC Huelle(BYTE i)
  INT l

  l=Laut(i)
  IF HKFlg(i)=Attack THEN
    l==+Att(i)
    IF l>Max(i) THEN
      l=Max(i)
      HKFlg(i)=Decay
    FI 
  ELSEIF HKFlg(i)=Decay THEN
    l==-Dec(i)
    IF l<Sus(i) THEN 
      l=Sus(i)
      HKFlg(i)=Sustain 
    FI
  ELSEIF HKFlg(i)=Sustain THEN 
    ;dann passiert nichts! 
  ELSEIF HKFlg(i)=Pause THEN 
    l=0
  FI
  Laut(i)=l
RETURN

;***********************************
;Alle vier Stimmen spielen
;
;Der Notenzeiger wird auf das zu be-
;arbeitende Array gerichtet.
;Stimme() gibt die Frequenz des 
;Tongenerators i vor, waehrend
;Huelle(i) die momentane Lautstaerke
;berechnet. Hardware(i) schreibt
;die berechneten Werte in die
;Audio-Register
;***********************************

PROC Alle_4()
  BYTE i

  FOR i=0 TO 3
    DO
    N_Ptr=NotenZ(i)
    Stimme(i)
    Huelle(i)
    Hardware(i)
  OD
RETURN

;***********************************
;Ganzes Musikstueck spielen
;
;Dies ist das Hauptmodul und wird 
;nach RUN angesprungen. Das Musik-
;stueck wird vollstaendig durch-
;gespielt und widerholt. Abbruch
;mit <RESET>
;***********************************

PROC Musik()
  CARD i

  DO
  Vorbereitung()
    DO
      ENDE=4
      Alle_4()
      FOR i=0 TO TEMPO DO OD
     UNTIL (ENDE = 0)
    OD
  OD
RETURN