' "Grids"
' by David Matthews
' freely distributable
' simple AmigaBasic pgm.
' have fun with sound waveshapes (timbre)
' and amplitude envelopes (ADSR...attack,decay,sustain,release)




WINDOW 2,"TIMBRE",(60,53)-(600,186),6


WINDOW 3,"ADSR" ,(330,0)-(630,49),6
DEFINT a-z
x = 0

REM    your tune here    
FOR t = 1 TO 5 : READ tune(t) : NEXT t
DATA 261.63,293.66,233.47,116.73,174.61

DIM smooth.timbre% (255) 
DIM timbre% (255)
DIM adsr% (40)
DIM smooth.adsr% (40)

WINDOW OUTPUT 1
PRINT "Click left mouse button to draw grid...."
PRINT "Hold left button and drag to draw graph."
PRINT "Drag off right edge to enter data......."
PRINT "Press any key to hear it................"

a$ = "  mouse a graph from left to right "
WINDOW OUTPUT 3
PRINT : PRINT : PRINT
PRINT a$
WINDOW OUTPUT 2
PRINT : PRINT : PRINT
PRINT a$ 
 
 
ON MOUSE GOSUB top

WHILE 1
    GOSUB makeSound
    MOUSE ON
WEND    


top:
 MOUSE OFF 
  IF WINDOW(0) = 2 THEN GOSUB TIMBREtop
  IF WINDOW(0) = 3 THEN GOSUB ADSRtop
  RETURN

  
TIMBREtop:
   WINDOW  2  : CLS
   GOSUB drawTIMBREgrid
   GOSUB initTIMBREarray
   x = MOUSE(1)
   GOSUB TIMBREmouse
   RETURN
     
TIMBREmouse:
   IF MOUSE(0) = 0 THEN TIMBREmouse
   IF MOUSE(0) <> 0 THEN
       IF MOUSE(1) => 10 AND MOUSE(1) <= 521 THEN
           IF MOUSE(2) =< 125 AND MOUSE(2) => 1 THEN  GOSUB TIMBREdot           
       END IF
   END IF
   IF MOUSE(1) < 522 THEN TIMBREmouse
   GOSUB TIMBREread
   RETURN
      
TIMBREdot:
   x = MOUSE(1)  :  y = MOUSE(2)
   n = INT ((x-10)/2 ) 
   timbre(n)=y
   PSET(x,y),3
   RETURN
      
TIMBREread:
   FOR x = 10 TO 521 STEP 2
      y = ((x-10)\2)
      z = timbre(y) * 2 - 128
      IF z = -128 AND y > 0 THEN z = smooth.timbre(y-1)
      smooth.timbre(y) = z   
      PSET (x,129),3
   NEXT x
   WAVE 0,smooth.timbre
   RETURN
   
initTIMBREarray:
  FOR i = 0 TO 255
     timbre(i)=0
  NEXT i
RETURN

drawTIMBREgrid:
x = 0 : y =1 : y1 = 126
FOR i = 2 TO 59
   x = x + 9
   IF i = 31 THEN c = 1 ELSE c = 2
   LINE (x,y)-(x,y1),c
NEXT i
x = 10 : y= 1 : x1 = 521
FOR i = 1 TO  26
   IF i = 13 THEN c = 1 ELSE c = 2
   LINE (x,y)-(x1,y),c
   y = y + 5
NEXT i
RETURN

  
ADSRtop:
   WINDOW  3  : CLS
   GOSUB drawADSRgrid
   GOSUB initADSRarray
   x = MOUSE(1)
   GOSUB ADSRmouse
   RETURN
     
ADSRmouse:
   IF MOUSE(0) = 0 THEN ADSRmouse
   IF MOUSE(0) <> 0 THEN
       IF MOUSE(1) => 20 AND MOUSE(1) <=260 THEN
           IF MOUSE(2) =< 40 AND MOUSE(2) => 1 THEN  GOSUB ADSRdot           
       END IF
   END IF
   IF MOUSE(1) < 261 THEN ADSRmouse
   GOSUB ADSRread
   RETURN
      
ADSRdot:
   x = MOUSE(1)  :  y = MOUSE(2)
   n = INT ((x-20) / 6)
   adsr(n)=y
   PSET(x,y),3
   RETURN
     
ADSRread:
   FOR x = 0 TO 39
      z = 240 - adsr(x) * 6 
      IF z = 240 AND x > 0 THEN z = smooth.adsr(x-1)
      smooth.adsr(x) = z   
      PSET ((x*6)+20,43),3
   NEXT 
   RETURN
   
drawADSRgrid:
x = 10 : y =1 : y1 = 40
FOR i =  1 TO 25
   x = x + 10
   IF i = 1 THEN c = 1 ELSE c = 2
   LINE (x,y)-(x,y1),c
NEXT i
x = 20 : y= 1 : x1 = 260
FOR i = 1 TO  9
   IF i = 9 THEN c = 1 ELSE c = 2
   LINE (x,y)-(x1,y),c
   y = y + 5
NEXT i
  RETURN

initADSRarray:
  FOR i = 0 TO 39
     adsr(i)=0
  NEXT i
RETURN


makeSound:
  IF INKEY$ = "" THEN RETURN
    MOUSE OFF 
    FOR t = 1 TO 5
    n = tune(t)
    FOR i = 0 TO 39    
      SOUND n,.2,(smooth.adsr(i)),0
    NEXT i
    NEXT t
    RETURN

