home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
AMOS PD CD
/
amospdcd.iso
/
601-625
/
apd615
/
source.asc
< prev
Wrap
Text File
|
1986-08-03
|
38KB
|
1,491 lines
' ************************* ALEX'S COOL, FLASHY MIDI PROG *******************
' Version C is the tidied up fixed verion
' Version D displays no messages
' Version E has complete rewrite of graph routine which was too messy
' making it run too slow. + intro built in to start
' Version f has vu_meters routine (v. crappy)
' Version g has vel vs pitch routine with rainbow. realy nice!
' Version h has dodgy picture viewer
' Version i has new picture viewer and ravey circles
' version j has ghost player piano taken out the crappy vu_meters
' verison k has music score routine completed
' version l has verical bars routine (v1)
' **************** INITIALISE, SETUP SCREEN AND VARIABLES *******************
' Dimention arrays
Dim CHANEL_MESSAGE$(113)
Dim COMMON_MESSAGE$(7)
Dim REAL_TIME_MESSAGE$(15)
Dim NOEON(2)
Dim EBONY_N_IVORY$(12),EBONY_N_IVORY(12)
Dim PITCH_2KEY_CONVERSION_TABLE(24)
Dim GRAPHX_OLD(16)
Dim GRAPHY_OLD(16)
Dim PY(85)
Dim SCR(2)
Dim CX(360)
Dim SPRYT(110)
Dim MSCORE_YCORD(46),MSCORE_SHAPE(46)
Dim SCRDATA(5),CHANEL_COLOURS(16)
Dim HORIS_SLIDERX(16),OLD_HORIS_SLIDERX(16)
' Allow these variables to be used throughout all procedures
Global CHANEL_MESSAGE$(),COMMON_MESSAGE$(),REAL_TIME_MESSAGE$(),X,PITCH,VEL
Global BEEN_TO_NOTE_ON,NOEON(),EBONY_N_IVORY$(),EBONY_N_IVORY(),NOE,COUNT,KOUNT
Global PITCH_2KEY_CONVERSION_TABLE(),CHANEL,NEED_A_ROUTINE,CHANGEIT,S
Global GRAPHX,GRAPHX_OLD(),GRAPHY,GRAPHX_MAX,GRAPHX_MIN,GRAPHY_MIN,GRAPH_SPACE
Global GRAPHY_OLD(),FILTER,ALREADY_PULSED,OLD_TIME,TIME
Global ROUTINE_COUNTER,CYCLE_PIANO_SKY_CHANGE,CYCLE_PIANO_SKY_CHANGE_MAX
Global VUHEIGHT,VUHEIGTMAX,VUWIDTH,VUY
Global PY(),EX_ROUTINE
Global OLDPIC
Global CX()
Global SPRYT(),SPRY_NUMBER
Global MSCORE_YCORD(),MSCORE_SHAPE(),MSCOREX,MSCOREY,MSCOREX_MAX,MSCOREX_MIN
Global MSCORE_SPACE,MSCORE_TOP_OR_BOTTOM_OFFSET,MSCORE_TOP_OR_BOTTOM
Global SCRDATA(),CHANEL_COLOURS()
Global HORIS_SLIDERX(),OLD_HORIS_SLIDERX(),LISTEN_TO
' Turn off disk operating system and text editor
Close Workbench : Close Editor
' Do the intro and initialise main program
Proc FLOATING_NOTES_INTRO
Proc INIT
Proc SLIDER_PREFS
' Turn off external interupts (eg. test for mouse movement)
Dreg(0)=Execall(-132)
' Make a beep when ready to start
Play 60,1
' * * * * * * * * * * * * M A I N L O O P * * * * * * * * * * *
Do
Proc FETCHMIDI
Proc ANALYSE_MIDI
If BEEN_TO_NOTE_ON=1 Then Proc PICK_OUTPUT_ROUTINE
Loop
Proc _CLOSEDOWN
End
' ************************** E N D O F P R O G R A M ***************
' ----------------------------------------------------------------------
' ----------------------------------------------------------------------
' ***************************** P R O C E D U R E S ********************
' ***--- MIDI DECODING/TRANSLATION ROUTINES ---***
Procedure INIT
Screen Open 0,360,256,2,Lowres
Cls 0
'Set up Serial Port
Serial Open 1,0,0,0,0
Serial Speed 1,31250
Serial Bits 1,8,1
Serial Parity 1,-1
Serial Buf 1,2048
' Set up messages for text output
CHANEL_MESSAGE$(0)="Note off"
CHANEL_MESSAGE$(16)="Note on message"
CHANEL_MESSAGE$(32)="Poly key pressure"
CHANEL_MESSAGE$(48)="Control change"
CHANEL_MESSAGE$(64)="Program change"
CHANEL_MESSAGE$(80)="Channel pressure"
CHANEL_MESSAGE$(96)="Pitch bend"
CHANEL_MESSAGE$(112)="System message"
COMMON_MESSAGE$(0)="System exclusive"
COMMON_MESSAGE$(1)="MIDI Time code"
COMMON_MESSAGE$(2)="Song position pointer"
COMMON_MESSAGE$(3)="Song select"
COMMON_MESSAGE$(4)="Undefined com message1"
COMMON_MESSAGE$(5)="Undefined com message2"
COMMON_MESSAGE$(6)="Tune request"
COMMON_MESSAGE$(7)="End of system exclusive"
'REAL_TIME_MESSAGE$(0)="Timing Clock"
REAL_TIME_MESSAGE$(1)="Undefined Real Time message1"
REAL_TIME_MESSAGE$(2)="Start"
REAL_TIME_MESSAGE$(3)="Continue"
REAL_TIME_MESSAGE$(4)="Stop"
REAL_TIME_MESSAGE$(5)="Undefined Real Time message2"
REAL_TIME_MESSAGE$(6)="Active sensing"
REAL_TIME_MESSAGE$(7)="System reset"
' Keys data for Player_piano_routine
For LOUP=1 To 12
Read EBONY_N_IVORY$(LOUP)
Next LOUP
Data "C","#","D","#","E","C","#","D","#","D","#","E"
For LOUP=1 To 12
Read EBONY_N_IVORY(LOUP)
Next LOUP
Data 0,5,13,21,27,40,44,53,59,65,74,78
' Get the cycle_piano routine ready for imediate use
Proc CYCLE_PIANO_SETUP
' Set up graph variables ready for imediate use
Proc GRAPH_SETUP
' set up defalt prefs
Restore PREFS
For LOUP=8 To 1 Step -1
Read HORIS_SLIDERX(LOUP)
Next LOUP
PREFS:
Data 98,24,99,104,103,102,101,100
' Reset routine counter
ROUTINE_COUNTER=101
Proc ROUTINE_SWAP
' set up vel_vs_pitch_vector_graph for use.
Proc VEL_VS_PITCH_SETUP
' set up picture screen for use
Proc PIC_VIEWER_SETUP
' set up player_piano for use
Proc PIANO_PLAYER_SETUP
' set up music score maker for use
Proc MSCORE_SETUP
End Proc
Procedure FETCHMIDI
'Read SERIALPort
Repeat
FETCH_DATA[X]
If FILTER=False and X=$FE Then Proc CLOCK_PULSE
Until X<>$FE and X<>$F8
' Not all routines need all data therefore do filtering other wise
' recognise a midi clock pulse and go no further.
End Proc
Procedure ANALYSE_MIDI
'CHECK BIT 7 To SEE WHAT TYPE OF MESSAGE : STATUS or Data
If(X and $80) Then Proc STATUS_BYTE Else Proc DAT_BYTE
End Proc
Procedure FETCH_DATA[X]
' Read data procedure. Ignores -1 (no data found)
Repeat
X=Serial Get(1)
Until X<>-1
End Proc[X]
' *STATUS BYTE ROUTINES*
Procedure STATUS_BYTE
' Test and go to appropriate proc
If(X<$F0) Then Proc CHANEL_MESSAGE Else Proc SYS_MESSAGE
End Proc
Procedure CHANEL_MESSAGE
CHANEL=(X and $F)+1
STATUS=(X and $70)
' The print statement below for debugging only.
' Print CHANEL_MESSAGE$(STATUS);" on channel ";CHANEL
' if PROGRAM CHANGE message occurs (64) then this may be voice 99 to change
' the output routine.
If STATUS=64 Then CHANGEIT=True : Proc ROUTINE_CHANGE
' Ignore pitch bend data (this is part of note on messages and is not required.)
If STATUS=96 Then BEEN_TO_NOTE_ON=0 : Pop Proc
' If STATUS=16 and BEEN_TO_NOTE_ON=0 Then BEEN_TO_NOTE_ON=0 : Proc NOE_ON
' *** (resets the been_to_note_on flag. A diffent sys message has)
' *** (been encountered that is not going to be pitch or velocity.)
If STATUS=16 Then BEEN_TO_NOTE_ON=0 : Proc NOE_ON
If STATUS=0 Then BEEN_TO_NOTE_ON=0 : Proc NOE_OFF
End Proc
Procedure SYS_MESSAGE
BEEN_TO_NOTE_ON=0
If(X and $8) Then Proc REAL_TIME_MESSAGE Else Proc COMMON_MESSAGE
End Proc
' (messages taken out, these are now empty routines!) proc then endproc!
Procedure REAL_TIME_MESSAGE
' THE BELOW MESSAGE Not NEEDED ANYMORE
' If(X and 7)<>0 Then Print REAL_TIME_MESSAGE$(X and 7)
End Proc
Procedure COMMON_MESSAGE
' Print "COMMON routine"
' Print REAL_TIME_MESSAGE$(X and $7)
End Proc
' *DATA BYTE ROUTINES*
Procedure DAT_BYTE
If BEEN_TO_NOTE_ON=1 Then Proc NOE_ON : Rem Else Print "DATA ignored"
' ^^^^^ message taken out
' ***********************
' *** ( if the program has just been to the note on procedure)
' *** ( Then the data is still pitch and velocity data)
End Proc
Procedure NOE_ON
' Read PITCH
If BEEN_TO_NOTE_ON=0 Then FETCH_DATA[X] : PITCH=X
If BEEN_TO_NOTE_ON=1 Then PITCH=X : Rem (Don't have to read pitch again.)
' (the x variable is data which is pitch)
' Read Velocity
FETCH_DATA[X]
VEL=X
' Output results
' Print "Note ";PITCH;
If VEL>0 Then NOE=1 Else NOE=0
' Put results into a form suitable to be passed to the gfx routines
' a nice, neat array containing pitch and note on/off status.
NOEON(1)=PITCH
NOEON(2)=NOE
' Set been_to_note_on flag as 1 so if NOE_ON proc is called again straight
' away the procedure will remember not to read the serial port again as
' the data in the x variable is the pitch.
BEEN_TO_NOTE_ON=1
End Proc
Procedure NOE_OFF
'Say "Note off. HELP! help. help!"
' Read PITCH
If BEEN_TO_NOTE_ON=0 Then FETCH_DATA[X] : PITCH=X
If BEEN_TO_NOTE_ON=1 Then PITCH=X : Rem (Don't have to read pitch again.)
' (the x variable is data which is pitch)
' Output results
' Print "Note ";PITCH;
NOE=0
' Put results into a form suitable to be passed to the gfx routines
' a nice, neat array containing pitch and note on/off status.
NOEON(1)=PITCH
NOEON(2)=NOE
' Set been_to_note_on flag as 1 so if NOE_ON proc is called again straight
' away the procedure will remember not to read the serial port again as
' the data in the x variable is the pitch.
BEEN_TO_NOTE_ON=1
End Proc
Procedure _CLOSEDOWN
'Dreg(0)=Execall(-138)
Play 60,1
End Proc
' ***********************************************************************
' ***--- GRAPHICAL OUTPUT ROTINES (THE FLASHY STUFF!) ---***
' Pick a routine from all the below
Procedure ROUTINE_CHANGE
Proc FETCH_DATA[X]
'check the 8 horis_slider variables incase a change of routine is called for
For LOUP=1 To 8
If X=HORIS_SLIDERX(LOUP) Then Proc ROUTINE_SWAP
Next LOUP
End Proc
Procedure ROUTINE_SWAP
ROUTINE_COUNTER=X
' Closedown old routines if necessary
If EX_ROUTINE=4 Then Proc VEL_VS_PITCH_DISAPPEAR
If EX_ROUTINE=3 Then Proc PIANO_PLAYER_DISAPPEAR
If EX_ROUTINE=-1 Then Proc VERTICAL_BARS_DISAPPEAR
' Set up screens for the new routines
If ROUTINE_COUNTER=HORIS_SLIDERX(1) Then Proc GRAPH_APPEAR
If ROUTINE_COUNTER=HORIS_SLIDERX(2) Then Proc CYCLE_PIANO_APPEAR
If ROUTINE_COUNTER=HORIS_SLIDERX(3) Then Proc PIANO_PLAYER_APPEAR
If ROUTINE_COUNTER=HORIS_SLIDERX(4) Then Proc VEL_VS_PITCH_APPEAR
If ROUTINE_COUNTER=HORIS_SLIDERX(5) Then Proc PIC_VIEWER_APPEAR
If ROUTINE_COUNTER=HORIS_SLIDERX(7) Then Proc MSCORE_APPEAR
If ROUTINE_COUNTER=HORIS_SLIDERX(8) Then Proc VERTICAL_BARS_APPEAR
End Proc
Procedure PICK_OUTPUT_ROUTINE
' routine currently tested
' ROUTINE_COUNTER=5
' Proc TXT_DISPLAY
' Pop Proc
' Proc PITCHNO_2_KEY
If ROUTINE_COUNTER=HORIS_SLIDERX(1) Then Proc GRAPH
If ROUTINE_COUNTER=HORIS_SLIDERX(2) Then Proc CYCLE_PIANO
If ROUTINE_COUNTER=HORIS_SLIDERX(3) Then Proc PIANO_PLAYER
If ROUTINE_COUNTER=HORIS_SLIDERX(4) Then Proc VEL_VS_PITCH
If ROUTINE_COUNTER=HORIS_SLIDERX(5) Then Proc PIC_VIEWER
If ROUTINE_COUNTER=HORIS_SLIDERX(6) Then Proc CIRC
If ROUTINE_COUNTER=HORIS_SLIDERX(7) Then Proc MSCORE
If ROUTINE_COUNTER=HORIS_SLIDERX(8) Then Proc VERTICAL_BARS
End Proc
Procedure CLOCK_PULSE
' what to do if pitch vs time graph is running
If ROUTINE_COUNTER=1 and ALREADY_PULSED=False Then Proc _INCREMENT_GRAPHX : Proc _INCREMENT_GRAPHX
' what to do if velocity vs pitch graph is running
If ROUTINE_COUNTER=4 Then Proc VECTOR_PTS_DECREASE_YET[1]
ALREADY_PULSED=True
End Proc
' *****TEXT OUTPUT ROUTINES*****
' Mainly for debuging and testing ideas
Procedure TXT_DISPLAY
S=Screen
If S<>0 Then Bell : Screen Open 0,320,250,2,LORES : Screen To Front 0 : Screen 0
Print "Pitch =";NOEON(1);PITCH
If NOEON(2)=0 Then Print " off!" Else Print " on!" : Play 1,PITCH,0
End Proc
Procedure PITCHNO_2_KEY
Screen To Front 0
Screen 0
' This procedure is used to work out from the pitch, the key that is played
' ie. pitch=32 might be the key C#. This information is useful to the
' player_piano routine.
' NOTES: PITCH24 IS LOWEST C
PRESSED=PITCH
Add PRESSED,1
' get pressed between 1 and 12
While PRESSED>12
Add PRESSED,-12
Wend
Bell
Print EBONY_N_IVORY$(PRESSED),PRESSED,PITCH,
If NOE=1 Then Print "on" Else Print "off"
End Proc
Procedure FLOATING_NOTES_INTRO
Degree
Dim XC(4),YC(4),XIC(4),YIC(4)
Hide On
No Mask : For F=1 To 3 : Make Mask F : Next F
BUBBLE$=" R: L R1=Z(2)+1; A 1,(R1,1); L R0=Z(6)+1; L Y=296; L: L Y=Y-R0; I Y<0 J R; P; J L;"
BUBBLE2$=" R: L Y=1; P; L: L Y=Y+2; I Y>256 J R; P; J L;"
Unpack 5 To 0
Unpack 7 To 1
Palette 0,0
Wait Vbl : Dual Playfield 0,1
Screen 0
For F=8 To 15 : Sprite F,((F-8)*40)+128,1,1 : Channel F To Sprite F : Amal F,BUBBLE$ : Next F
Channel 1 To Screen Offset 1 : Amal 1,BUBBLE2$ : Amal On
Fade 3,0,4072,3490,3202,$400,$600,$EEE,$A50,0,$FFF,$FFF,$FFF,$FFF,$FFF,$FFF,$FFF,$FFF,$FFF,$FFF,$FFF,$FFF,$FFF,$FFF,$FFF,$FFF,$FFF,$FFF,$FFF,$FFF,$FFF,$FFF,$FFF
Repeat
Until Mouse Key=1 or Joy(1)=16
Fade 3 : Wait 45
For F=8 To 15 : Amal Off F : Sprite Off F : Next F
Amal Off 1 : Screen Close 1
End Proc
' *****CYCLE_PIANO_ROUTINES!*******
' The futuristic keyboard. Keys flashed by colour cycling technique
' (ie changing the palette colours)
Procedure CYCLE_PIANO
'*******************************************************************
'
' C Y C L E P I A N O N O T E S.
'
'
' If get a better cycle piano routine (ie full 5 octaves) then make
' the original screen back to like in demo. Don't bother about
' drawing out the extra black notes that arn't there realy.
' and don't worry about acuracy. just have it as a flashy routine. Not
' accurate.
' Make it so that keys just flash black then fade out. dont have
' red until the right noe off message recived. this will halve
' the amount of processing! (no noe offs)
' do this by having a sepearate proc fade_keys to do the keys
'and a pop proc if noe=0.
'********************************************************************
'Count how many times the procedure has been run and change the sky colour!
Add COUNT,1,1 To 200
If COUNT=199 Then Proc CYCLE_PIANO_CHANGE_SKY
' Flash keys
Proc CYCLE_PIANO_KEYS_FLASH
End Proc
Procedure CYCLE_PIANO_SETUP
Unpack 8 To 1
Screen Hide 1
' pitch to key conversion table'
Restore CONV_TABLE
For LOUP=0 To 24
Read PITCH_2KEY_CONVERSION_TABLE(LOUP)
Next LOUP
CYCLE_PIANO_SKY_CHANGE_MAX=4
' ********* conversion table ***********
CONV_TABLE:
Data 0,-1,1,-1,2,3,-1,4,-1,5,-1,6,7,-1,8,-1,9,10,-1,11,-1,5,-1,6,7
' ***************************************
End Proc
Procedure CYCLE_PIANO_APPEAR
' hide old screen
S=Screen
Screen Hide S
' Display cycle_piano screen
Screen Show 1
Screen To Front 1
Screen 1
'turn the read data filter on
FILTER=True
CYCLE_PIANO_SKY_CHANGE=1
End Proc
Procedure CYCLE_PIANO_KEYS_FLASH
' Change pitch (a value between about 1 and 70) to pressed
' (a value between 1 and 12)
PRESSED=PITCH
' Decrese pitch to a value between 1 and 24 (covers the 1 and a bit octaves of keyboard)
While PRESSED>23
Add PRESSED,-24
Wend
' Convert key PRESSED to screen palette colour number
PRESSED=PITCH_2KEY_CONVERSION_TABLE(PRESSED)
' Ignore the black keys
' Quit the procedure now if key PRESSED is a black key (-1)
If PRESSED=-1 Then Pop Proc
' first colour in palette is no 20 so add 20
Add PRESSED,20
' Change colours
If NOE=0 Then Colour PRESSED,$FFF Else Colour PRESSED,$F00
End Proc
Procedure CYCLE_PIANO_CHANGE_SKY
' Change the colour of the sky!
'Add CYCLE_PIANO_SKY_CHANGE,1,1 To CYCLE_PIANO_SKY_CHANGE_MAX
Add KOUNT,1,1 To 3
If KOUNT=3 Then C=$EEF : D=$221 : Rem BLUE!
If KOUNT=2 Then C=$EFE : D=$212 : Rem GREEN!
If KOUNT=1 Then C=$FEE : D=$122 : Rem RED!
For LOUP=1 To 7 : Rem Go through the 7 colours used in the sky and change 'em
Add C,-D
Colour LOUP,C
' Wait until the next video blank
' Slows down the colouring so looks more like a nice fade
' rather than a sudden change
Wait Vbl
Next LOUP
End Proc
' ****** MUSICAL SCORE ROUTINES! ***********
'****** this was tricky! ****************
Procedure MSCORE
Proc _INCREMENT_MSCOREX
If NOE=0
ALREADY_PULSED=False
Pop Proc
Else
Proc STICK_NOTES_DOWN
ALREADY_PULSED=False
End If
End Proc
Procedure MSCORE_SETUP
' set up variables
MSCOREX_MIN=60
MSCOREX_MAX=600
MSCORE_SPACE=5
' read in notes data
Restore MSCORE_DATA
For LOUP=1 To 46
Read MSCORE_YCORD(LOUP)
Read MSCORE_SHAPE(LOUP)
Next LOUP
Make Icon Mask
' Comma separated variable data statement in the format
' Data y-coordinate,sprite(ie note shape)number
' ****************************************************************************
' b a# a g# g f# f e d# d c# c b a#
MSCORE_DATA:
Data 11,7,11,16,15,9,14,12,18,5,17,12,21,5,25,5,25,12,29,5,28,12,32,5,13,6,16,13
' a g# g f# f e d# d c# c b
Data 16,6,20,13,20,6,23,13,23,6,27,6,30,13,30,6,36,17,36,10,65,5
' a# a g# g f# f e d# d c# c b a#
Data 65,12,69,5,68,12,72,5,72,12,76,5,79,5,59,13,59,6,63,13,63,6,66,6,70,13
' a g# g f# f e d# d
Data 70,6,74,13,74,6,77,13,77,6,82,10,86,15,86,8
'*******************************************************************************
End Proc
Procedure MSCORE_APPEAR
' hide last screen
S=Screen
Screen Hide S
' create screen and Load in background screen
Screen Open 0,640,256,2,Hires
Load Iff "ram:pics/music_sheet"
'turn read data filter on
FILTER=True
End Proc
Procedure _INCREMENT_MSCOREX
Proc TIMECHECK
TIME=Param
' time is set to value returned by timecheck procedure (parameter passing)
MOVEUP=Abs(OLD_TIME-TIME)
If MOVEUP<MSCORE_SPACE Then Pop Proc : Rem only move up if its worth it
' increment mscorex by incrementing moveup like this rather than
' "Add mscorex,moveup*3"
' because that Add instruction works very much faster than the multiplying
' operator. ----
EXTRA=MOVEUP
Add MOVEUP,MOVEUP
'Add MOVEUP,EXTRA
' moveup is now moveup*3
Add MSCOREX,MOVEUP,MSCOREX_MIN To MSCOREX_MAX
OLD_TIME=TIME
If MSCOREX=MSCOREX_MIN Then Proc MSCORE_CLEAR_SCREEN
End Proc
Procedure STICK_NOTES_DOWN
'This is the procedure that puts notes onto the paper'
' decrease pitch to a value between 1 and 46
' (because thats the range of note we can put on screen)
PRESSED=96-PITCH
If PRESSED>46 or PRESSED<1 Then Pop Proc
' Set up y-coordinate according to which sheet to print the notes on
' top sheet or the bottom sheet
MSCORE_Y=MSCORE_YCORD(PRESSED)+MSCORE_TOP_OR_BOTTOM_OFFSET
' Decrese pitch to a value between 1 and 12 (to check if a black note was played)
BLK_OR_WHITE=PITCH+1
While BLK_OR_WHITE>12
Add BLK_OR_WHITE,-12
Wend
' Use the ebony_n_ivory array (set up in initailisation proc) to check
' if the PRESSED key is a "#" sharp ie black key and take that into
' account when working out x,y co-ords
If EBONY_N_IVORY$(BLK_OR_WHITE)="#"
' move up the x-coord to make room for the # sign
Add MSCOREX,10,MSCOREX_MIN To MSCOREX_MAX
OLD_TIME=TIME
If MSCOREX=MSCOREX_MIN
Proc MSCORE_CLEAR_SCREEN
End If
Paste Icon MSCOREX,MSCORE_Y,MSCORE_SHAPE(PRESSED)
Else
' Put the right shaped note at the right coordinate on the screen
Paste Icon MSCOREX,MSCORE_Y,MSCORE_SHAPE(PRESSED)
End If
End Proc
Procedure MSCORE_CLEAR_SCREEN
If MSCORE_TOP_OR_BOTTOM=0
' Overlay blank graph background picture that has been saved in main memory
Load Iff "ram:pics/music_sheet"
'reset the top_or_bottom_y-coordinat offset
MSCORE_TOP_OR_BOTTOM_OFFSET=0
Else
MSCORE_TOP_OR_BOTTOM_OFFSET=118
End If
' reset time axis base
Proc TIMECHECK
OLD_TIME=Param
' reverse the top or bottom flag
Add MSCORE_TOP_OR_BOTTOM,1,0 To 1
End Proc
' ******* PITCH vs TIME GRAPH
' V2 after complete re-write (got too messy and slow)
Procedure GRAPH
Proc _INCREMENT_GRAPHX
If NOE=0
ALREADY_PULSED=False
Pop Proc
Else
Proc GRAPH_PLOT
ALREADY_PULSED=False
End If
End Proc
Procedure GRAPH_SETUP
'set up screen
Hide : Flash Off : Curs Off
Unpack 4 To 3
Save Iff "ram:graph_background.iff"
Screen Hide 3
' set up variables
GRAPHY_MIN=250
GRAPHX_MIN=10
GRAPHX_MAX=310
GRAPH_SPACE=5
'reset graph coords to start position
For LOUP=1 To 16
GRAPHY_OLD(LOUP)=GRAPHY_MIN/2 : Rem set graph y to mid position
GRAPHX_OLD(LOUP)=GRAPHX_MIN
Next LOUP
End Proc
Procedure GRAPH_APPEAR
' hide last screen
S=Screen
Screen Hide S
GRAPHX=GRAPHX_MIN
Screen Show 3
Screen To Front 3
Screen 3
Proc GRAPH_CLEAR_SCREEN
FILTER=False
End Proc
Procedure _INCREMENT_GRAPHX
Proc TIMECHECK
TIME=Param
' time is set to value returned by timecheck procedure (parameter passing)
MOVEUP=Abs(OLD_TIME-TIME)
If MOVEUP<GRAPH_SPACE Then Pop Proc : Rem only move up if its worth it
Add GRAPHX,MOVEUP,GRAPHX_MIN To GRAPHX_MAX
OLD_TIME=TIME
If GRAPHX=GRAPHX_MIN Then Proc GRAPH_CLEAR_SCREEN
' Add GRAPHX,GRAPH_SPACE,GRAPHX_MIN To GRAPHX_MAX
' If GRAPHX=GRAPHX_MIN Then Proc GRAPH_CLEAR_SCREEN
End Proc
Procedure GRAPH_CLEAR_SCREEN
' Overlay blank graph background picture that has been saved in main memory
Load Iff "ram:graph_background.iff"
' reset x_old variables
For LOUP=1 To 16
GRAPHX_OLD(LOUP)=GRAPHX_MIN
Next LOUP
' reset time axis base
Proc TIMECHECK
OLD_TIME=Param
End Proc
Procedure GRAPH_PLOT
GRAPHY=GRAPHY_MIN-(PITCH-20)*3
If GRAPHX_OLD(CHANEL)=-1 Then GRAPHX_OLD(CHANEL)=GRAPHX
Ink CHANEL
' only colours 0 to 15, there is no colour 16 so..
If CHANEL=16 Then Ink 15
Draw GRAPHX_OLD(CHANEL),GRAPHY_OLD(CHANEL) To GRAPHX,GRAPHY
GRAPHY_OLD(CHANEL)=GRAPHY
GRAPHX_OLD(CHANEL)=GRAPHX
End Proc
Procedure TIMECHECK
N$=Space$(12) : N=Varptr(N$) : Dreg(1)=N
C=Doscall(-192)
TIME=Leek(N+8)
End Proc[TIME]
Procedure VEL_VS_PITCH
If NOE=1 Then Proc VEL_VS_PITCH_NEW
End Proc
Procedure VEL_VS_PITCH_NEW
' decrease vector_pts if enough time has elapsed but DONT redraw yet [0]
' because going to redraw anyway
Proc VECTOR_PTS_DECREASE_YET[0]
PY(PITCH-23)=200-(VEL*2)
Proc VECTOR_PTS_REDRAW
End Proc
Procedure VEL_VS_PITCH_NOTES
' workout new vector point after a note on message
PY(PITCH)=200-VEL
'workout new polygon points and decrease all the old polygon points
' For LOUP=1 To 16
' Add PY(LOUP),-1 : If PY(LOUP)<BASE Then PY(LOUP)=BASE
' Next LOUP
'New polly point after a note on
'PY(CHANEL)=VEL*10
'Polygon 0,PY(1) To 20,PY(2) To 40,PY(3) To 60,PY(4) To 80,PY(5) To 100,PY(6) To 120,PY(7) To 140,PY(8) To 160,PY(1)
'Screen Swap : Wait Vbl
'Cls 0
End Proc
Procedure VECTOR_PTS_DECREASE_YET[YET]
' check on the time and pass parameter into this routine
Proc TIMECHECK
TIME=Param
If TIME_PAST-TIME<-5 Then Proc VECTOR_PTS_DECREASE : If YET=1 Then Proc VECTOR_PTS_REDRAW
TIME_PAST=TIME
End Proc
Procedure VECTOR_PTS_DECREASE
' after time elapsed since last decrease is enough
' decrement all vector_pts (as this is the y-axis which has min=200 then add 1
For LOUP=1 To 85
If PY(LOUP)<200 Then Add PY(LOUP),10 : If PY(LOUP)>200 Then PY(LOUP)=200
Next
End Proc
Procedure VECTOR_PTS_REDRAW
' redraw the vector points in the background and then swap screens
Ink 1
' plot first point
Plot 0,200
' draw the rest of the points that arn't 0 (ie worth plotting)
For LOUP=1 To 85
If PY(LOUP)<200 Then Draw To 4*LOUP,PY(LOUP)
Next LOUP
' draw to last dot
Draw To 360,200
Screen Swap : Wait Vbl
Cls 0
End Proc
Procedure VEL_VS_PITCH_SETUP
Screen Open 2,360,256,2,Lowres : Flash Off : Curs Off : Cls 0 : Hide On
Palette $0,$FFF
'Screen Display 2,10,0,,
Screen 2 : Double Buffer : Autoback 0
' setup initial values for vector points
For LOUP=1 To 60
PY(LOUP)=200
Next LOUP
End Proc
Procedure VEL_VS_PITCH_APPEAR
' hide old screen
S=Screen
Screen Hide S
' show screen for this routine
Screen Show 2
Cls 0
Screen To Front 2
Screen 2
FILTER=False : Rem DONT ignore clock pulses (important to this routine
'because used to slowly decrease the points)
' Make rainbow background
Restore RDATA
Set Rainbow 0,1,180,"","",""
Rainbow 0,80,93,200
For F=0 To 178 Step 2
Read R : Rain(0,F)=R : Rain(0,F+1)=R
Next F
Rainbow 0,80,93,200
RDATA:
Data $F00,$F10,$F20,$F30,$F40,$F50,$F60,$F70,$F80,$F90,$FA0,$FB0,$FC0,$FD0,$FE0
Data $FF0,$EF0,$DF0,$CF0,$BF0,$AF0,$9F0,$8F0,$7F0,$6F0,$5F0,$4F0,$3F0,$2F0,$1F0
Data $F0,$F1,$F2,$F3,$F4,$F5,$F6,$F7,$F8,$F9,$FA,$FB,$FC,$FD,$FE
Data $FF,$EF,$DF,$CF,$BF,$AF,$9F,$8F,$7F,$6F,$5F,$4F,$3F,$2F,$1F
Data $F,$10F,$20F,$30F,$40F,$50F,$60F,$70F,$80F,$90F,$A0F,$B0F,$C0F,$D0F,$E0F
Data $F0F,$F0E,$F0D,$F0C,$F0B,$F0A,$F09,$F08,$F07,$F06,$F05,$F04,$F03,$F02,$F01
CAT:
Data 0,90,0,4,95,95
Data 225,315,0,0,75,75
Data 90,180,4,0,95,95
Data 315,45,0,0,75,75
Data 180,270,0,4,95,95
Data 45,135,0,0,75,75
Data 270,0,4,0,95,95
Data 135,225,0,0,75,75
'
Data 0,90,1,1,95,95
Data 45,135,355,355,55,55
Data 90,180,1,1,95,95
Data 135,225,355,355,55,55
Data 180,270,1,1,95,95
Data 225,315,355,355,55,55
Data 270,0,1,1,95,95
Data 315,45,355,355,55,55
Data 0,90,1,1,95,95
Data 45,135,4,4,95,95
Data 90,180,2,2,95,95
Data 135,225,3,3,95,95
Data 180,270,3,3,95,95
Data 225,315,2,2,95,95
Data 270,0,4,4,95,95
Data 315,45,1,1,95,95
Data 0,90,5,4,95,95
Data 225,315,5,4,45,45
Data 90,180,5,4,95,95
Data 315,45,5,4,45,45
Data 180,270,5,4,95,95
Data 45,135,5,4,45,45
Data 270,0,5,4,95,95
Data 135,225,5,4,45,45
' set ex_routine flag so the rainbow effect is turned off before next
' routine
EX_ROUTINE=4
End Proc
Procedure VEL_VS_PITCH_DISAPPEAR
' end the rainbow effect which slows down processing
Rainbow Del 0
' RESET EX_ROUTINE FLAG
EX_ROUTINE=0
End Proc
Procedure PIC_VIEWER_SETUP
Screen Open 5,320,256,2,Lowres : Flash Off : Curs Off : Cls 0 : Hide On
Double Buffer : Autoback 0
Palette $0,$FFF
End Proc
Procedure PIC_VIEWER
' quit this proc if note off message is recived(ie finger is lifting off the key)
If VEL=0 Then Pop Proc
' Change pitch (a value between about 1 and 70) to pressed
' (a value between 1 and 12)
PRESSED=PITCH
' Decrese pitch to a value between 1 and 12 (to select one of the 12 pics)
While PRESSED>12
Add PRESSED,-12
Wend
' load picture into the background (as long as it is a different one)
If PRESSED<>OLDPIC
Load Iff "ram:pics/"+Str$(PRESSED)-" "
OLDPIC=PRESSED
Palette Rnd(4096),Rnd(4096)
' R*256+G*16+B)4
' when picture has finished loading flip the logical & physical screens
' to show the new picture that has loaded into the background
Screen Swap
End If
End Proc
Procedure PIC_VIEWER_APPEAR
' hide old screen
S=Screen
Screen Hide S
' show screen for this routine
Screen Show 5
Screen To Front 5
Screen 5
' don't need to process clock pulses.
FILTER=True
End Proc
Procedure CIRC
S=Screen
Screen Hide S
Curs Off : Degree : Hide On
Screen Open 0,320,180,2,Lowres : Hide On : Curs Off : Cls 0
Screen Display 0,128,70,, : Palette 0,0
Unpack 6 To 6
Screen To Front 0 : Screen Hide 6
Screen Open 7,400,32,2,Lowres : Screen Hide 7 : Screen 0
Double Buffer : Bob Update Off : Autoback 0 : Curs Off
For F=1 To 360 : CX(F)=(Sin(F)*100)+128 : Next F
Y1=90 : Y2=90 : CH=0 : SCAR=7 : Def Scroll 1,0,0 To 390,32,-2,0
T$=" ALEXS MIDI MAGIX *"
Sprite Update Off
Do
Add X1,1,1 To 360
Add X2,2,1 To 359
Add Y1,3,1 To 358
Add Y2,1,1 To 360
XP1=CX(X1)+32
YP1=CX(Y1)
XP2=CX(X2)+32
YP2=CX(Y2)
Screen 7
Scroll 1
Add SCAR,1,0 To 15 : If SCAR=0 Then Gosub PCHAR
Screen Copy 6,XP1,YP1,XP1+319,YP1+180 To 0,0,0
Screen Copy 6,XP2,YP2,XP2+319,YP2+180 To 0,0,0,%1100000
Screen Copy 7,0,0,320,31 To 0,0,80,%1100000
Screen 0
Add T,1,0 To 89 : If T=0 Then Gosub CCOL : Rem change col
Screen Swap : Wait Vbl
' If ascii value of the text$ gives 42 ("*") then quit
If B=42 Then Goto CIRCLOSE
Loop
CCOL:
Add CT,1,0 To 5
If CT=0 Then Fade 3,$F00,$F0F
If CT=1 Then Fade 3,$0,$F
If CT=2 Then Fade 3,$FF0,$F0
If CT=3 Then Fade 3,$FF0,$0
If CT=4 Then Fade 3,$F0F,$FF
If CT=5 Then Fade 3,$F,$FF
Return
PCHAR:
Add CH,1,1 To Len(T$)
B=Asc(Mid$(T$,CH,1))
Paste Bob 354,0,B+3
Return
CIRCLOSE:
Screen 0 : Wait 45 : Fade 3 : Wait 45 : Screen Close 0
Screen Close 6 : Screen Close 7
If S<>0 Then Screen Show S
X=HORIS_SLIDERX(1) : Proc ROUTINE_SWAP
End Proc
Procedure PIANO_PLAYER_SETUP
End Proc
Procedure PIANO_PLAYER_APPEAR
' hide old screen
S=Screen
Screen Hide S
'make this screen and unpack the compressed screen in memory bank 3 into it
Screen Open 6,640,44,16,Hires
Hide On : Curs Off
Unpack 3 To 6
' Set the sprites' colours all to red (colour indexes 17 to 31)
For LOUP=17 To 31
Colour LOUP,$F00
Next LOUP
' don't need to process clock pulses.
FILTER=TURE
'set ex_routine flag so this routine will be "disapeared" properly
EX_ROUTINE=3
End Proc
Procedure PIANO_PLAYER_DISAPPEAR
For LOUP=0 To 7
Sprite Off LOUP
Next LOUP
EX_ROUTINE=0
End Proc
Procedure PIANO_PLAYER
' if Note off the make the sprite dissapear and leave procedure
If VEL=0
Sprite Off SPRYT(PITCH)
Pop Proc
End If
' Work out x,y co-ordinates for the new sprite taking into account
' the way a real keyboard is laid out with black notes halfway between
' some of the white notes.
' Change pitch (a value between about 1 and 70) to pressed
' (a value between 1 and 12)
PRESSED=PITCH+1
' Decrese pressed to a value between 1 and 12 (to select one of the 12 keys)
' but work out the octave the note was played in too
While PRESSED>12
Add PRESSED,-12
Add OCTAVE,1
Wend
Add OCTAVE,-2
' Use the ebony_n_ivory array (set up in initailisation proc) to check
' if the PRESSED key is a "#" sharp ie black key and take that into
' account when working out x,y co-ords
If EBONY_N_IVORY$(PRESSED)="#"
XKEY=(OCTAVE*91)+EBONY_N_IVORY(PRESSED)+50
YKEY=223
Else
XKEY=(OCTAVE*91)+EBONY_N_IVORY(PRESSED)+50
YKEY=238
End If
'Increment the Sprite_number counter so that different sprite is used
' each time.
Add SPRY_NUMBER,1,0 To 7
' Put sprite onto screen
Sprite SPRY_NUMBER,X Hard(XKEY),Y Hard(YKEY),4
' Put into sprite array at position according to pitch of the note
' the sprite number used so that when the pitch?? vel0 message is recived
' when the player lifts their finger off the procedure can work out from the
' pitch of the message which sprite to make dissapear.
SPRYT(PITCH)=SPRY_NUMBER
End Proc
Procedure VERTICAL_BARS_APPEAR
' hide old screen
S=Screen
Screen Hide S
' don't need to process clock pulses.
FILTER=TURE
WIDTH=352
HEIGHT=16*3
X=X Hard(-5)
Y=Y Hard(0)
' Create 5 screens and load in the stripes to each of them
' Use screens 0,4,5,6 and 7 which can be cleared (others in
' use from other routines eg. screen one reserved for cycle piano.)
' Use data statement (SCRDATA) to know which screens to use
Restore SCRDATAS
For LOUP=0 To 4
Read SCRDATA(LOUP)
Screen Open SCRDATA(LOUP),WIDTH,HEIGHT,16,Lowres
Flash Off : Curs Off
Load Iff "ram:pics/stripes2",SCRDATA(LOUP)
Next LOUP
'place the screens one below the other
For LOUP=0 To 4
Screen Display SCRDATA(LOUP),X,Y+(LOUP*HEIGHT),WIDTH,HEIGHT
Next LOUP
' reset all the screens' 16 colours to black ($0)
For LOUP=0 To 4
Screen SCRDATA(LOUP)
For L=0 To 16
Colour L,$0
Next L
Next LOUP
' read in the channel values
Restore CHANEL_COLOURS_DATA
For LOUP=0 To 15
Read CHANEL_COLOURS(LOUP)
Next LOUP
SCRDATAS:
Data 0,4,5,6,7
CHANEL_COLOURS_DATA:
Data $4,$F00,$F60,$FC0,$CF0,$6F0,$F0,$F5,$FA,$FF,$AF,$5F,$F,$CCC,$444,$777
' set ex_routine flag so that this routine will dissapear properly and
' release the screens back
EX_ROUTINE=-1
End Proc
Procedure VERTICAL_BARS_DISAPPEAR
' close the 5 screens that were used
' so they are free to be used again by the other procedures
For LOUP=0 To 4
Screen Close SCRDATA(LOUP)
Next LOUP
'reset ex_routine flag
EX_ROUTINE=0
End Proc
Procedure VERTICAL_BARS
' work out variables for screen and bar number
BRR=109-PITCH
'-24
BRR2=BRR
Add BRR2,-1
BRR2=BRR2/16
SCR=Int(BRR2)
If SCR>5 Then Pop Proc : Rem note is out of range
' bar is between 0 and 16
While BRR>16
Add BRR,-16
Wend
Add BRR,-1
'Screen 0
'Ink 1
'Colour 1,$FFF
'Locate 1,1 : Print "Pitch=";PITCH;" Bar=";BRR;" scr=";SCR;" "
' select screen and change the bar to red if note on or black if note off
Screen SCRDATA(SCR)
If NOE=0 Then Colour BRR,$0
If NOE=1 Then Colour BRR,CHANEL_COLOURS(CHANEL)
End Proc
Procedure SLIDERS_APPEAR
' hide old screen
S=Screen
Screen Hide S
Screen Open 0,360,256,4,Lowres
Cls 0 : Curs Off : Flash Off
Load Iff "ram:Pics/sliders_screen",0
Rem draw the sliders
Reserve Zone 16
Set Slider ,,11,,,,,
LISTEN_TO=1
For LOUP=1 To 8 : Rem 8 routines
Hslider 30,30*(LOUP) To 150,(30*LOUP)+10,116,HORIS_SLIDERX(LOUP),2
Set Zone LOUP,30,30*(LOUP) To 150,(30*LOUP)+10
Next LOUP
Rem set up text windows for channel data
For LOUP=1 To 8
Wind Open LOUP,170,30*(LOUP),4,1
Curs Off
Paper 0
Scroll Off
Next LOUP
Window 1 : Paper 0 : Clw
For LOUP=1 To 8
Window LOUP
Print HORIS_SLIDERX(LOUP)
Next LOUP
Rem *** set up LISTEN box and surround it with a mouse zone
Wind Open 9,255,230,11,3,2
Set Zone 9,255,230 To 334,253
Curs Off
Paper 4
Scroll Off
Clw
Print "" : Print "Listen";
End Proc
Procedure CHECK_HORIS_SLIDER[MZ]
Rem *** check horizontal slider and change pattern if left key is pressed
If Mouse Zone=MZ and Mouse Key=1
LOUP=MZ
Limit Mouse X Hard(30),Y Hard(30*(MZ)) To X Hard(145),Y Hard((30*MZ)+10)
Hslider 30,30*(LOUP) To 150,(30*LOUP)+10,116,1,2
HORIS_SLIDERX(MZ)=X Screen(X Mouse)-30
SLIDE[HORIS_SLIDERX(MZ),MZ]
Else
Limit Mouse
End If
End Proc
Procedure CHECK_LISTENING_BOX
If Mouse Zone=9 and Mouse Key=1
' keep the mouse in the listen box
Limit Mouse X Hard(255),Y Hard(230) To X Hard(334),Y Hard(253)
Window 9
Clw
Print "" : Print "Listenin";
Wait Vbl : Wait Vbl
' empty out the serial buffer of any left over midi data
While TRASH<>-1
TRASH=Serial Get(1)
Wend
' listen for intrument change messages an alter the horisontal sliders
' until the mouse button is pressed again
While Mouse Key<>1
Repeat
Proc FETCH_DATA[X]
Exit If Mouse Key=1
Until X<>$FE and X<>$F8
' check to see if the MIDI data is a system message and a channel message
If(X and $80) and X<$F0
'check to see if the channel message is a program change message (64)
If(X and $70)=64
' if PROGRAM CHANGE message occurs (64) then read the next byte of data which
'contains the instrument number
Proc FETCH_DATA[X]
HORIS_SLIDERX(LISTEN_TO)=X
Proc SLIDE[X,LISTEN_TO]
End If
End If
Wend
Limit Mouse
Window 9 : Clw
Print "" : Print "Listen";
Wait Vbl : Wait Vbl
End If
End Proc
Procedure SLIDER_PREFS
Show
Proc SLIDERS_APPEAR
Do
For LOUP=1 To 8
Proc CHECK_HORIS_SLIDER[LOUP]
Next LOUP
Proc CHECK_LISTENING_BOX
Rem *** quit if right mouse key is pressed
Exit If Mouse Key=2
Loop
Hide
Screen Close 0
End Proc
Procedure SLIDE[HORIS_SLIDERX,MZ]
If LISTEN_TO<>MZ
Set Slider ,,11,,,,,
Hslider 30,30*(LISTEN_TO) To 150,(30*LISTEN_TO)+10,116,HORIS_SLIDERX(LISTEN_TO),2
End If
Set Slider ,,2,,,,,
Hslider 30,30*(MZ) To 150,(30*MZ)+10,116,HORIS_SLIDERX(MZ),2
Window MZ
Ink 0 : Print HORIS_SLIDERX;" "
LISTEN_TO=MZ
Wait Vbl
End Proc
Procedure _NOTES_TO_READ
'
'
' WIPE GRAPH SCREEN AFTER DOING A VOICE 99. THIS IS DONE IN PICK_OUTPUT
' ROUTINE BUT DOESN'T RESET X COORDS.
'
' IF A NOTE OFF MESSAGE IS SENT BY SEQUENCER THEN THE PROGRAM MAY
'NOT WORK BECAUSE PROGRAMED TO RECOGNISE NOTE_ON_VEL=0 AS NOTE OFF
'
End Proc