'===========================================================================
' Subject: PC PIANO                           Date: 04-18-97 (00:17)       
'  Author: Denis Boyles                       Code: QB, QBasic, PDS        
'  Origin: FidoNet QUIK_BAS Echo            Packet: SOUND.ABC
'===========================================================================
'-=[PC-PIANO.BAS]=- v2.00 Public Domain (pd) by Denis Boyles
'
' Microsoft QBASIC v1.1
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
' A simple 3 octave piano program; PC-Speaker version. Note frequencies are
' from the Commodore 64C system guide; page 177; APPENDIX J - SOUND AND MUSIC.
'
' The SID oscillator frequencies used within the program are from the middle
' C octave. Which is the initial "default" octave (#2) used when the program
' is run.
'
' The SID oscillator frequency is multiplied by SIDHZ to convert the value into
' a real frequency. Which is used to program the PIT controller to generate a
' sound. (Yes, one could use SOUND, but I wanted to try direct)
'
DECLARE SUB pause (sTime!)
DECLARE SUB GenSound (iFreq%, sTime!)
DECLARE SUB PlayNote (Note$, iOctave%, sTime!)

CONST SIDHZ = .059604645#
CONST PITHZ = 1193181

CLS
PRINT "PC-PIANO II - (PC Speaker Version)": PRINT
PRINT "ESC"; CHR$(9); "Quit Program"
PRINT "TAB"; CHR$(9); "Change Octave"
PRINT "cdefgab"; CHR$(9); "play regular notes"
PRINT "CD FGA"; CHR$(9); "play sharp notes"

iOctave% = 2
WHILE key$ <> CHR$(27)
  key$ = INKEY$
  IF key$ = CHR$(9) THEN
    IF iOctave% = 3 THEN
      iOctave% = 1
    ELSE
      iOctave% = iOctave% + 1
    END IF
  ELSE
    PlayNote key$, iOctave%, .25
  END IF
WEND

SUB GenSound (iFreq%, sTime!)
  OUT &H43, &HB6
  OUT &H42, PITHZ \ iFreq% MOD 256
  OUT &H42, PITHZ \ iFreq% \ 256

  OUT &H61, INP(&H61) OR 3
  pause sTime!
  OUT &H61, INP(&H61) AND &HFC
END SUB

SUB pause (sTime!)
  sStop! = sTime! + TIMER
  WHILE TIMER < sStop!: WEND
END SUB

SUB PlayNote (Note$, iOctave%, sTime!)
  IF Note$ >= "a" AND Note$ <= "g" OR Note$ >= "A" AND Note$ <= "G" THEN

    SELECT CASE Note$
      CASE "c"
        iSIDOscFreq% = 4197
      CASE "C"
        iSIDOscFreq% = 4448
      CASE "d"
        iSIDOscFreq% = 4712
      CASE "D"
        iSIDOscFreq% = 4992
      CASE "e"
        iSIDOscFreq% = 5289
      CASE "E"
        EXIT SUB
      CASE "f"
        iSIDOscFreq% = 5603
      CASE "F"
        iSIDOscFreq% = 5937
      CASE "g"
        iSIDOscFreq% = 6290
      CASE "G"
        iSIDOscFreq% = 6664
      CASE "a"
        iSIDOscFreq% = 7060
      CASE "A"
        iSIDOscFreq% = 7481
      CASE "b"
        iSIDOscFreq% = 7925
      CASE "B"
        EXIT SUB
    END SELECT

    SELECT CASE iOctave%
      CASE 1
        iSIDOscFreq% = iSIDOscFreq% \ 2
      CASE 3
        iSIDOscFreq% = iSIDOscFreq% * 2
    END SELECT

    GenSound iSIDOscFreq% * SIDHZ, sTime!
  END IF
END SUB
