REM Metronome
REM Version 1.0 // 6-Jan-2015
REM May not be not accurate (irregular intervals between beats)
*ESC OFF
ON CLOSE PROCClose : QUIT
ON ERROR PROCError(REPORT$ + " at line " + STR$ERL)
Tempo% = 90 : REM BPM (Beats Per Minute)
ScrW% = 480
ScrH% = 512
PROCFixWndSz
VDU 23,22,ScrW%;ScrH%;8,16,16,0 : OFF
GetTickCount% = FNSYS_NameToAddress("GetTickCount")
Sleep% = FNSYS_NameToAddress("Sleep")
PlaySound% = FNSYS_NameToAddress("PlaySound")
SetWindowText% = FNSYS_NameToAddress("SetWindowText")
READ wavSz%, nLines%
DIM wav% wavSz%-1
O% = 0
FOR I% = 0 TO nLines%-1
READ s$
FOR J% = 0 TO (LEN(s$) DIV 2)-1
wav%?O% = EVAL("&" + MID$(s$, 1+2*J%, 2))
O% += 1
NEXT J%
NEXT I%
COLOUR 9, 80, 0, 0
COLOUR 10, 240, 240, 200
COLOUR 11, 240, 240, 100
MinTempo% = 60
MaxTempo% = 180
IF Tempo% < MinTempo% THEN Tempo% = MinTempo%
IF Tempo% > MaxTempo% THEN Tempo% = MaxTempo%
PendulumLength% = 300
PendulumX0% = ScrW%/2
PendulumY0% = ScrH%/4
BobDist = 0.1 + 0.8*(1.0 - (Tempo% - MinTempo%)/(MaxTempo% - MinTempo%))
MetronomeHeight% = 400
bpms = Tempo% / (60 * 1000) : REM Beats per millisecond
sgn% = 1 : REM Direction sign of pendulum
clicks% = 0
bar% = 1
beat% = 0
updateWindowText% = TRUE
SYS "timeBeginPeriod", 1
SYS "GetCurrentProcess" TO hprocess%
SYS "SetPriorityClass", hprocess%, &80
*REFRESH OFF
SYS "GetTickCount" TO time0%
REPEAT
IF updateWindowText% THEN
SYS SetWindowText%, @hwnd%, "Tempo: " + STR$Tempo% + " BPM | " + \
\ "4/4 Bar: " + STR$bar% + " | Clicks: " + STR$clicks%
updateWindowText% = FALSE
ENDIF
SYS GetTickCount% TO time1%
T% = time1% - time0%
angle% = 45 * COS(PI*T% * bpms)
IF (angle% < 0 AND sgn% = 1) OR (angle% >= 0 AND sgn% = -1) THEN
sgn% *= -1
SYS PlaySound%, wav%, 0, 5
clicks% += 1
beat% += 1
IF beat% > 4 THEN
beat% = 1
bar% += 1
ENDIF
updateWindowText% = TRUE
ENDIF
CLS
PROCDrawMetronomeBody
pendX% = PendulumX0% + PendulumLength%*SINRAD(angle%)
pendY% = PendulumY0% + PendulumLength%*COSRAD(angle%)
bobX% = PendulumX0% + BobDist*PendulumLength%*SINRAD(angle%)
bobY% = PendulumY0% + BobDist*PendulumLength%*COSRAD(angle%)
@vdu%!248=12
GCOL 0 : LINE 2*PendulumX0%, 2*PendulumY0%, 2*pendX%, 2*pendY%
@vdu%!248=8
GCOL 10 : LINE 2*PendulumX0%, 2*PendulumY0%, 2*pendX%, 2*pendY%
@vdu%!248=1
GCOL 0 : CIRCLE FILL 2*bobX%, 2*bobY%, 36
GCOL 11 : CIRCLE FILL 2*bobX%, 2*bobY%, 32
GCOL 9
MOVE 216, 120
MOVE 744, 120
PLOT 85, 252, 258
PLOT 85, 706, 258
CIRCLE FILL 2*PendulumX0%, 2*PendulumY0%, 32
*REFRESH
SYS Sleep%, 1
UNTIL FALSE
END
DEF PROCDrawMetronomeBody
GCOL 1
MOVE 192, 96
MOVE 480, 96
PLOT 85, 416, 896
PLOT 85, 480, 896
MOVE 768, 96
MOVE 480, 96
PLOT 85, 544, 896
PLOT 85, 480, 896
MOVE 416, 896
MOVE 544, 896
PLOT 85, 480, 928
RECTANGLE FILL 2*110, 2*43,2*16, 2*4
RECTANGLE FILL 2*356, 2*43,2*16, 2*4
GCOL 0
LINE 480, 192, 480, 896
ENDPROC
DEF FNSYS_NameToAddress(f$)
LOCALP%:DIMP%LOCAL5:[OPT 0:call f$:]:=P%!-4+P%
DEF PROCFixWndSz
LOCAL W%
SYS"GetWindowLong",@hwnd%,-16 TO W%
SYS"SetWindowLong",@hwnd%,-16,W% ANDNOT&40000 ANDNOT&10000
ENDPROC
DEF PROCError(s$)
LOCAL H%
SYS "GetCurrentProcess" TO H%
SYS "SetPriorityClass", H%, &20
OSCLI "REFRESH ON"
CLS : ON : VDU 7
PRINT '" " + s$;
REPEAT UNTIL INKEY(1)=0
ENDPROC
DEF PROCClose
LOCAL H%
SYS "GetCurrentProcess" TO H%
SYS "SetPriorityClass", H%, &20
ENDPROC
DATA 950, 30
DATA "52494646AE03000057415645666D74201000000001000100112B0000112B0000"
DATA "01000800646174618903000080888479817D5A6F9A8966A6A57A996CA15D8E4E"
DATA "5D6D7B878891A498907E896C6D7A6A83778A80A26F7B837F767D7C79808E9186"
DATA "9F877976826A6A7F78777B8F80928B8783817B7A807F7B7C7E84827B817D807E"
DATA "7E828C89807F80847A7E79807D7C7E8683807E837D807F8181827B8088817D82"
DATA "80787F83817F81867E807E827C7E7A817F808289837C7F827F7B827E807C8481"
DATA "827E8380807F8381807F7E8180817D7F80807B8281837F7F817F7D81807E8280"
DATA "80808182817E7E8281817E80828080818181817F807F7D7C7F827F7F82827F81"
DATA "817F7F7E7E7F7F8282828183807F807F7C808080808682808382807E7F7E7E80"
DATA "807F8283818183817F7F80807D7F7F817E817E817F7F808280828182807F8080"
DATA "807F817F7F81818082837F8081817F8280817E82808082817E7E808080818182"
DATA "828280807E7F7F7D7F7E7F8180818282808281807F7F7E7E807F808182808083"
DATA "827F7F807F7F7E808182817F81817F7E807F7E7F7F8081808381828081807F7F"
DATA "7F80807F81808081807F81807F8080807F81818080807E7F807F808181808081"
DATA "81818081807F7F7E7F7E80808080817F818280807F807F7F7E7F7E807F818180"
DATA "8081807F80807E7F80807F80818080807F8081807F7F807F8081818080818080"
DATA "8080807F8080817F8181818080807F7F7E7F818180808280807F7F807E7F8180"
DATA "7F808181818080807F8080808181828180807F807F7F8080818081828080807F"
DATA "7F7F807F807F818181808180807F807F8080808081818080807F7F807F808081"
DATA "8080818181818080807F7F808080808180808080807F807F7F80808081828080"
DATA "80807F7F807F80808080808080818080807F8080808080808080808080808181"
DATA "808080808080807F8080808081807F80807F80807F8080808080807F7F7F7F80"
DATA "80808080808080807F7F80807F80818080818080808080807F808080807F8080"
DATA "808180808081818080807F7F7F8080808080808180808080807F808180808080"
DATA "80808181808080807F8180818080808080807F80808080808080808080808080"
DATA "8080808080807F808080808080808081808080807F8080808080808080808180"
DATA "808080818080808080808081807F80808080807F808080808080808080807F80"
DATA "8080808080808080808080808080808080808080808080808080808080808080"
DATA "8080808080808080808080808080808080808080808080808080808080808080"
DATA "80808080808080808080808080808080808080808000"