2016 Update

This commit is contained in:
Tina Müller 2016-12-05 22:15:40 +01:00
parent 948b86eafa
commit dcf5d15da3
7965 changed files with 139854 additions and 31002 deletions

View file

@ -1,6 +1,15 @@
<!--{{task|Temporal media}}-->
The task is to implement a metronome. The metronome should be capable of producing high and low audio beats, accompanied by a visual beat indicator, and the beat pattern and tempo should be configurable.
[[File:Metronome.jpg|420px||right]]
For the purpose of this task, it is acceptable to play sound files for production of the beat notes, and an external player may be used. However, the playing of the sounds should not interfere with the timing of the metronome.
The task is to implement a &nbsp; [https://en.wikipedia.org/wiki/Metronomemetronome metronome].
The visual indicator can simply be a blinking red or green area of the screen (depending on whether a high or low beat is being produced), and the metronome can be implemented using a terminal display, or optionally, a graphical display, depending on the language capabilities. If the language has no facility to output sound, then it is permissible for this to implemented using just the visual indicator.
The metronome should be capable of producing high and low audio beats, accompanied by a visual beat indicator, and the beat pattern and tempo should be configurable.
For the purpose of this task, it is acceptable to play sound files for production of the beat notes, and an external player may be used.
However, the playing of the sounds should not interfere with the timing of the metronome.
The visual indicator can simply be a blinking red or green area of the screen (depending on whether a high or low beat is being produced), and the metronome can be implemented using a terminal display, or optionally, a graphical display, depending on the language capabilities.
If the language has no facility to output sound, then it is permissible for this to implemented using just the visual indicator.
<br><br>

View file

@ -0,0 +1,40 @@
MET=: _ _&$: :(4 : 0)
'BEL BS LF CR'=. 7 8 10 13 { a.
'`print stime delay'=. 1!:2&4`(6!:1)`(6!:3)
ticker=. 2 2$'\ /'
'small large'=. (BEL,2#BS) ; 5#BS
clrln=. CR,(79#' '),CR
x=. 2 ({.,) x
y=. _1 |.&.> 2 ({.,) y
'i j'=. 0
print 'bpb \ bpm \ ' , 2#BS
delay 1
x=. ({. , ('ti t'=. stime'') + {:) x
while. x *./@:> i,t do.
'bpb bpm'=. {.@> y=. 1 |.&.> y
dl=. 60 % bpm
print clrln,(":bpb),' ',(ticker {~ 2 | i=. >: i),' ',(":bpm),' '
for. i. bpb do.
print small ,~ ticker {~ 2 | j=. >: j
delay 0 >. (t=. t + dl) - stime ''
end.
end.
print clrln
i , j , t - ti
)
NB. Basic tacit version; this is probably considered bad coding style. At least I removed the "magic constants". Sort of.
NB. The above version is by far superior.
'BEL BS LF'=: 7 8 10 { a.
'`print delay'=: 1!:2&4`(6!:3)
met=: _&$: :((] ({:@] [ LF print@[ (-.@{.@] [ delay@[ print@] (BEL,2#BS) , (2 2$'\ /') {~ {.@])^:({:@])) 1 , <.@%) 60&% [ print@('\ '"_))

View file

@ -0,0 +1,29 @@
class Metronome{
double bpm;
int measure, counter;
public Metronome(double bpm, int measure){
this.bpm = bpm;
this.measure = measure;
}
public void start(){
while(true){
try {
Thread.sleep((long)(1000*(60/bpm)));
}catch(InterruptedException e) {
e.printStackTrace();
}
counter++;
if (counter%measure==0){
System.out.println("TICK");
}else{
System.out.println("TOCK");
}
}
}
}
public class test {
public static void main(String[] args) {
Metronome metronome1 = new Metronome(120,4);
metronome1.start();
}
}

View file

@ -1,390 +1,320 @@
Structure METRONOMEs
string_mil.i
string_err.i
string_bmp.i
volumn.i
image_metronome.i
msPerBeat.i
BeatsPerMinute.i
BeatsPerCycle.i
volume.i
canvasGadget.i
w.i
h.i
originX.i
originY.i
radius.i
activityStatus.i
EndStructure
Enumeration
#STRING_MIL
#STRING_ERR
#STRING_BMP
#BUTTON_ERRM
#BUTTON_ERRP
#BUTTON_VOLM
#BUTTON_VOLP
#TEXT_TUNE
#TEXT_MIL
#TEXT_BMP
#BUTTON_START
#BUTTON_STOP
#WINDOW
#IMAGE_METRONOME
Enumeration ;gadgets
#TEXT_MSPB ;milliseconds per beat
#STRING_MSPB ;milliseconds per beat
#TEXT_BPM ;beats per minute
#STRING_BPM ;beats per minute
#TEXT_BPC ;beats per cycle
#STRING_BPC ;beats per cycle
#BUTTON_VOLM ;volume -
#BUTTON_VOLP ;volume +
#BUTTON_START ;start
#SPIN_BPM
#CANVAS_METRONOME
EndEnumeration
Enumeration ;sounds
#SOUND_LOW
#SOUND_HIGH
EndEnumeration
If Not InitSound()
MessageRequester("Error", "Sound system is not available", 0)
End
EndIf
#WINDOW = 0 ;window
; the wav file saved as raw data
; sClick: [?sClick < address of label sClick:]
; Data.a $52,$49,$46,... [?eClick-?sClick the # of bytes]
; eClick: [?eClick < address of label eClick:]
If Not CatchSound(0,?sClick,?eClick-?sClick)
MessageRequester("Error", "Could not CatchSound", 0)
End
EndIf
If LoadFont(0,"tahoma",9,#PB_Font_HighQuality|#PB_Font_Bold)
SetGadgetFont(#PB_Default, FontID(0))
EndIf
Procedure.i Metronome(*m.METRONOMEs)
Protected j
Protected iw =360
Protected ih =360
Protected radius =100
Protected originX =iw/2
Protected originY =ih/2
Protected BeatsPerMinute=*m\string_bmp.i
Protected msError.i =*m\string_err.i
Protected Milliseconds =int((60*1000)/BeatsPerMinute)
Protected msDword.i =Milliseconds*2/12
If CreateImage(*m\image_metronome.i,iw,ih)
Repeat
; [sAngleA: < prepare to read starting at address of label]
Restore sAngleA
st1=ElapsedMilliseconds()
; 1 | 90
; 2 6 | 75 75
; 3 5 | 60 60
; 4 | 45
; 90, 75, 60, 45, 60, 75 ; click
For j=1 to 6
st2=ElapsedMilliseconds()
Read.f Angle.f
If StartDrawing(ImageOutput(*m\image_metronome.i))
StartTime = ElapsedMilliseconds()
Box(0,0,iw,ih,RGB(0,0,0))
CircleX=int(radius*cos(Radian(Angle)))
CircleY=int(radius*sin(Radian(Angle)))
LineXY(originX,originY, originX+CircleX,originY-CircleY,RGB(255,255,0))
Circle(originX+CircleX,originY-CircleY,10,RGB(255,0,0))
StopDrawing() ; don't forget to: StopDrawing() !
SetGadgetState(*m\image_metronome.i,ImageID(*m\image_metronome.i))
Endif
Delay(msDword-msError)
Next
While ElapsedMilliseconds()-st1<Milliseconds-msError.i
Wend
SetGadgetText(*m\string_mil.i,str(ElapsedMilliseconds()-st1))
PlaySound(0) ; click
st3=ElapsedMilliseconds():err2=0
; 1 | 090
; 2 6 | 105 105
; 3 5 | 120 120
; 4 | 135
; 90,105,120,135,120,105 ; click
For j=1 to 6
st4=ElapsedMilliseconds()
Read.f Angle.f
If StartDrawing(ImageOutput(*m\image_metronome.i))
StartTime = ElapsedMilliseconds()
Box(0,0,iw,ih,RGB(0,0,0))
CircleX=int(radius*cos(Radian(Angle)))
CircleY=int(radius*sin(Radian(Angle)))
LineXY(originX,originY, originX+CircleX,originY-CircleY,RGB(255,255,0))
Circle(originX+CircleX,originY-CircleY,10,RGB(255,0,0))
StopDrawing() ; don't forget to: StopDrawing() !
SetGadgetState(*m\image_metronome.i,ImageID(*m\image_metronome.i))
Endif
Delay(msDword-msError)
Next
While ElapsedMilliseconds()-st3<Milliseconds-msError.i
Wend
SetGadgetText(*m\string_mil.i,str(ElapsedMilliseconds()-st3))
PlaySound(0) ; click
ForEver
Endif
ProcedureReturn i.i
Procedure handleError(Value, text.s)
If Not Value: MessageRequester("Error", text): End: EndIf
EndProcedure
; width of image
; height of image
; allocate memory for our structure
; the StringGadget number for milliseconds between clicks
; the ImageGadget number for the metronome
; intial value for the volumn [30 %]
; intial value adjustment for time accuracy adjustment
w =360
h =360
*m.METRONOMEs =Allocatememory(SizeOf(METRONOMEs))
*m\string_mil.i =#STRING_MIL
*m\image_metronome.i =#IMAGE_METRONOME
*m\volumn.i =30
DelayVal =5
Procedure drawMetronome(*m.METRONOMEs, Angle.f, cycleCount = 0)
Protected CircleX, CircleY, circleColor
If StartDrawing(CanvasOutput(*m\canvasGadget))
Box(0, 0, *m\w, *m\h, RGB(0, 0, 0))
CircleX = Int(*m\radius * Cos(Radian(Angle)))
CircleY = Int(*m\radius * Sin(Radian(Angle)))
If Angle = 90
If cycleCount: circleColor = RGB(255, 0, 0): Else: circleColor = RGB(0, 255, 0): EndIf
LineXY(*m\originX, *m\originY, *m\originX, *m\originY - CircleY, RGB(255, 255, 0))
Circle(*m\originX + CircleX, *m\originY - CircleY - *m\radius * 0.15, 10, circleColor)
Else
LineXY(*m\originX, *m\originY - *m\radius * 1.02, *m\originX, *m\originY - *m\radius, RGB(255, 255, 0))
LineXY(*m\originX, *m\originY, *m\originX + CircleX, *m\originY - CircleY, RGB(255, 255, 0))
EndIf
SoundVolume(0,*m\volumn.i)
StopDrawing()
radius =100
originX =w/2
originY =h/2
Angle.f =90
ProcedureReturn 1
EndIf
EndProcedure
; draw our initial metronome at 90 degrees
; *
; |
; |
; |
If CreateImage(#IMAGE_METRONOME,w,h)
If StartDrawing(ImageOutput(#IMAGE_METRONOME))
Box(0,0,w,h,RGB(0,0,0))
CircleX=int(radius*cos(Radian(Angle)))
CircleY=int(radius*sin(Radian(Angle)))
LineXY(originX,originY, originX+CircleX,originY-CircleY,RGB(255,255,0))
Circle(originX+CircleX,originY-CircleY,10,RGB(255,0,0))
StopDrawing() ; don't forget to: StopDrawing() it's time for dinner
Endif
Endif
Procedure.i Metronome(*m.METRONOMEs)
Protected milliseconds = Int((60 * 1000) / *m\BeatsPerMinute)
Protected msPerFrame, framesPerBeat
Protected i, j, cycleCount, startTime, frameEndTime, delayTime, delayError, h.f
; window style
WINDOW_STYLE=#PB_Window_SystemMenu
WINDOW_STYLE|#PB_Window_Screencentered
WINDOW_STYLE|#PB_Window_MinimizeGadget
;calculate metronome angles for each frame of animation
If *m\BeatsPerMinute < 60
framesPerBeat = Round(milliseconds / 150, #PB_Round_Nearest)
Else
framesPerBeat = Round((*m\BeatsPerMinute - 420) / -60, #PB_Round_Nearest)
EndIf
If Not OpenWindow(#WINDOW,0,0,w+200+12,h+4,"Metronome",WINDOW_STYLE)
MessageRequester("Error", "Not OpenWindow", 0)
End
If framesPerBeat < 1
framesPerBeat = 1
Dim metronomeFrameAngle.f(1, framesPerBeat)
metronomeFrameAngle(0, 1) = 90
metronomeFrameAngle(1, 1) = 90
Else
Dim metronomeFrameAngle.f(1, framesPerBeat * 2)
For j = 1 To framesPerBeat
h = 45 / framesPerBeat
metronomeFrameAngle(0, j) = 90 - h * (j - 1)
metronomeFrameAngle(0, framesPerBeat + j) = 45 + h * (j - 1)
metronomeFrameAngle(1, j) = 90 + h * (j - 1)
metronomeFrameAngle(1, framesPerBeat + j) = 135 - h * (j - 1)
Next
framesPerBeat * 2
EndIf
msPerFrame = milliseconds / framesPerBeat
PlaySound(#SOUND_HIGH)
startTime = ElapsedMilliseconds()
Repeat
For i = 0 To 1
frameEndTime = startTime + msPerFrame
For j = 1 To framesPerBeat
drawMetronome(*m, metronomeFrameAngle(i, j), cycleCount)
;check for thread exit
If *m\activityStatus < 0
*m\activityStatus = 0
ProcedureReturn
EndIf
delayTime = frameEndTime - ElapsedMilliseconds()
If (delayTime - delayError) >= 0
Delay(frameEndTime - ElapsedMilliseconds() - delayError) ;wait the remainder of frame
ElseIf delayTime < 0
delayError = - delayTime
EndIf
frameEndTime + msPerFrame
Next
;check for thread exit
If *m\activityStatus < 0
*m\activityStatus = 0
ProcedureReturn
EndIf
While (ElapsedMilliseconds() - startTime) < milliseconds: Wend
SetGadgetText(*m\msPerBeat, Str(ElapsedMilliseconds() - startTime))
cycleCount + 1: cycleCount % *m\BeatsPerCycle
If cycleCount = 0
PlaySound(#SOUND_HIGH)
Else
PlaySound(#SOUND_LOW)
EndIf
startTime + milliseconds
Next
ForEver
EndProcedure
Procedure startMetronome(*m.METRONOMEs, MetronomeThread) ;start up the thread with new values
*m\BeatsPerMinute = Val(GetGadgetText(#STRING_BPM))
*m\BeatsPerCycle = Val(GetGadgetText(#STRING_BPC))
*m\activityStatus = 1
If *m\BeatsPerMinute
MetronomeThread = CreateThread(@Metronome(), *m)
EndIf
ProcedureReturn MetronomeThread
EndProcedure
Procedure stopMetronome(*m.METRONOMEs, MetronomeThread) ;if the thread is running: stop it
If IsThread(MetronomeThread)
*m\activityStatus = -1 ;signal thread to stop
EndIf
drawMetronome(*m, 90)
EndProcedure
Define w = 360, h = 360, ourMetronome.METRONOMEs
;initialize the metronome
With ourMetronome
\msPerBeat = #STRING_MSPB
\canvasGadget = #CANVAS_METRONOME
\volume = 10
\w = w
\h = h
\originX = w / 2
\originY = h / 2
\radius = 100
EndWith
ourMetronome\canvasGadget = #CANVAS_METRONOME
;initialize sounds
handleError(InitSound(), "Sound system is Not available")
handleError(CatchSound(#SOUND_LOW, ?sClick, ?eClick - ?sClick), "Could Not CatchSound")
handleError(CatchSound(#SOUND_HIGH, ?sClick, ?eClick - ?sClick), "Could Not CatchSound")
SetSoundFrequency(#SOUND_HIGH, 50000)
SoundVolume(#SOUND_LOW, ourMetronome\volume)
SoundVolume(#SOUND_HIGH, ourMetronome\volume)
;setup window & GUI
Define Style, i, wp, gh
Style = #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_MinimizeGadget
handleError(OpenWindow(#WINDOW, 0, 0, w + 200 + 12, h + 4, "Metronome", Style), "Not OpenWindow")
SetWindowColor(#WINDOW, $505050)
If LoadFont(0, "tahoma", 9, #PB_Font_HighQuality | #PB_Font_Bold)
SetGadgetFont(#PB_Default, FontID(0))
EndIf
SetWindowColor(#Window,$505050)
TEXT_STYLE=#PB_Text_Center|#PB_Text_Border
i = 3: wp = 10: gh = 22
TextGadget(#TEXT_MSPB, w + wp, gh * i, 100, gh, "MilliSecs/Beat ", #PB_Text_Center)
StringGadget(#STRING_MSPB, w + wp + 108, gh * i, 90, gh, "0", #PB_String_ReadOnly): i + 2
TextGadget(#TEXT_BPM, w + wp, gh * i, 100, gh,"Beats/Min ", #PB_Text_Center)
StringGadget(#STRING_BPM, w + wp + 108, gh * i, 90, gh, "120", #PB_String_Numeric): i + 2
GadgetToolTip(#STRING_BPM, "Valid range is 20 -> 240")
TextGadget(#TEXT_BPC, w + wp, gh * i, 100, gh,"Beats/Cycle ", #PB_Text_Center)
StringGadget(#STRING_BPC, w + wp + 108, gh * i, 90, gh, "4", #PB_String_Numeric): i + 2
GadgetToolTip(#STRING_BPC, "Valid range is 1 -> BPM")
ButtonGadget(#BUTTON_START, w + wp, gh * i, 200, gh, "Start", #PB_Button_Toggle): i + 2
ButtonGadget(#BUTTON_VOLM, w + wp, gh * i, 100, gh, "-Volume")
ButtonGadget(#BUTTON_VOLP, w + wp + 100, gh * i, 100, gh, "+Volume")
CanvasGadget(ourMetronome\canvasGadget, 0, 0, ourMetronome\w, ourMetronome\h, #PB_Image_Border)
drawMetronome(ourMetronome, 90)
; data strings
i=2:wp=18:gh=24
i+1:TextGadget(#TEXT_TUNE ,w+wp-10 ,gh*(i-1),200,gh,"Fine tuning",TEXT_STYLE)
i+1
i+1:StringGadget(#STRING_ERR,w+wp+100,gh*(i-1),90,gh,"-5",#PB_String_ReadOnly)
i+1
i+1:StringGadget(#STRING_MIL,w+wp+100,gh*(i-1),90,gh,"0",#PB_String_ReadOnly)
i+1
i+1:StringGadget(#STRING_BMP,w+wp+100,gh*(i-1),90,gh,"120",#PB_String_Numeric)
Define msg, GID, MetronomeThread, Value
Repeat ;the control loop for our application
msg = WaitWindowEvent(1)
GID = EventGadget()
etp = EventType()
; control buttons
i=2:wp=10:gh=24
i+1
i+1
i+1:ButtonGadget(#BUTTON_ERRM ,w+wp,gh*(i-1),50,gh,"-")
i+0:ButtonGadget(#BUTTON_ERRP ,w+wp+50,gh*(i-1),50,gh,"+")
i+1
i+1:TextGadget(#TEXT_MIL ,w+wp,gh*(i-1),100,gh,"MilliSeconds ",TEXT_STYLE)
i+1
i+1:TextGadget(#TEXT_BMP ,w+wp,gh*(i-1),100,gh,"BeatsPerMin " ,TEXT_STYLE)
i+1
i+1:ButtonGadget(#BUTTON_START,w+wp,gh*(i-1),200,gh,"Start",#PB_Button_Toggle)
i+1
i+1:ButtonGadget(#BUTTON_VOLM ,w+wp ,gh*(i-1),100,gh,"-Volumn")
i+0:ButtonGadget(#BUTTON_VOLP ,w+wp+100,gh*(i-1),100,gh,"+Volumn")
If GetAsyncKeyState_(#VK_ESCAPE): End: EndIf ;remove when app is o.k.
; the metronome image
IMG_STYLE=#PB_Image_Border
ImageGadget(#IMAGE_METRONOME,0,0,360,360,ImageID(#IMAGE_METRONOME),IMG_STYLE)
SetGadgetState(#IMAGE_METRONOME,ImageID(#IMAGE_METRONOME))
Select msg
Repeat
Case #PB_Event_CloseWindow
End
; the control loop for our application [not all the values are used
; but this makes it easy to add further controls and functionality]
msg= WaitWindowEvent ()
wid= EventWindow ()
mid= EventMenu ()
gid= EventGadget ()
etp= EventType ()
ewp= EventwParam ()
elp= EventlParam () :If msg=#PB_Event_CloseWindow : End : EndIf
Case #PB_Event_Gadget
Select GID
; Esc kills application regardless of window focus
If GetAsyncKeyState_(#VK_ESCAPE) : End : EndIf
Case #STRING_BPM
If etp = #PB_EventType_LostFocus
Value = Val(GetGadgetText(#STRING_BPM))
If Value > 390
Value = 390
ElseIf Value < 20
Value = 20
EndIf
SetGadgetText(#STRING_BPM, Str(Value))
EndIf
Select msg
Case #STRING_BPC
If etp = #PB_EventType_LostFocus
Value = Val(GetGadgetText(#STRING_BPC))
If Value > Val(GetGadgetText(#STRING_BPM))
Value = Val(GetGadgetText(#STRING_BPM))
ElseIf Value < 1
Value = 1
EndIf
SetGadgetText(#STRING_BPC, Str(Value))
EndIf
case #PB_Event_Gadget
Case #BUTTON_VOLP, #BUTTON_VOLM ;change volume
If GID = #BUTTON_VOLP And ourMetronome\volume < 100
ourMetronome\volume + 10
ElseIf GID = #BUTTON_VOLM And ourMetronome\volume > 0
ourMetronome\volume - 10
EndIf
SoundVolume(#SOUND_LOW, ourMetronome\volume)
SoundVolume(#SOUND_HIGH, ourMetronome\volume)
Select gid
Case #BUTTON_START ;the toggle button for start/stop
Select GetGadgetState(#BUTTON_START)
Case 1
stopMetronome(ourMetronome, MetronomeThread)
MetronomeThread = startMetronome(ourMetronome, MetronomeThread)
SetGadgetText(#BUTTON_START,"Stop")
Case 0
stopMetronome(ourMetronome, MetronomeThread)
SetGadgetText(#BUTTON_START,"Start")
EndSelect
Case #BUTTON_VOLP ; +volumn
If *m\volumn.i<100:*m\volumn.i+10
SoundVolume(0,*m\volumn.i)
EndIf
Case #BUTTON_VOLM ; -volumn
If *m\volumn.i>0 :*m\volumn.i-10
SoundVolume(0,*m\volumn.i)
EndIf
Case #BUTTON_ERRP ; time accuracy adjustment [faster]
DelayVal-1
*m\string_err.i =DelayVal
SetGadgetText(#STRING_ERR,str(0-DelayVal))
If GetGadgetState(#BUTTON_START)=1
GoSub Stop
GoSub Start
EndIf
Case #BUTTON_ERRM ; time accuracy adjustment [slower]
DelayVal+1
*m\string_err.i =DelayVal
SetGadgetText(#STRING_ERR,str(0-DelayVal))
If GetGadgetState(#BUTTON_START)=1
GoSub Stop
GoSub Start
EndIf
Case #BUTTON_START ; the toggle button for start/stop
Select GetGadgetState(#BUTTON_START)
Case 1 :GoSub Stop : GoSub Start :SetGadgetText(#BUTTON_START,"Stop")
Case 0 :GoSub Stop :SetGadgetText(#BUTTON_START,"Start")
EndSelect
EndSelect
EndSelect
EndSelect
ForEver
End
Start: ; start up the thread with new values
*m\string_err.i =DelayVal
*m\string_bmp.i =Val(GetGadgetText(#STRING_BMP))
If *m\string_bmp.i
MetronomeThread=CreateThread(@Metronome(),*m)
EndIf
Return
Stop: ; if the thread is running: stop it
If IsThread(MetronomeThread)
KillThread(MetronomeThread)
EndIf
Return
DataSection ; an array of angles to be read by: MetronomeThread
sAngleA:
Data.f 90, 75, 60, 45, 60, 75 ; click
Data.f 90,105,120,135,120,105 ; click
eAngleA:
EndDataSection
DataSection ; a small wav file saved as raw data
sClick:
Data.a $52,$49,$46,$46,$2E,$08,$00,$00,$57,$41,$56,$45,$66,$6D,$74,$20
Data.a $10,$00,$00,$00,$01,$00,$01,$00,$44,$AC,$00,$00,$44,$AC,$00,$00
Data.a $01,$00,$08,$00,$64,$61,$74,$61,$02,$06,$00,$00,$83,$84,$84,$84
Data.a $85,$85,$86,$86,$88,$89,$8A,$8B,$8E,$91,$95,$9C,$A2,$A9,$B3,$C0
Data.a $CF,$CF,$D0,$CE,$D3,$9B,$47,$31,$31,$33,$32,$32,$32,$32,$33,$32
Data.a $33,$31,$42,$A1,$C9,$C4,$AE,$BD,$D4,$CD,$D1,$CF,$D0,$CF,$CF,$D0
Data.a $CB,$A9,$70,$37,$33,$32,$32,$32,$32,$32,$33,$32,$33,$31,$34,$2E
Data.a $53,$AF,$CF,$CF,$CA,$CF,$D0,$CF,$D0,$CF,$D0,$CE,$D3,$AA,$83,$97
Data.a $A1,$8A,$44,$32,$33,$31,$33,$32,$33,$32,$32,$33,$32,$33,$30,$44
Data.a $83,$94,$7E,$7D,$AE,$CF,$D0,$CF,$D0,$CE,$D1,$BF,$B8,$C3,$B9,$B7
Data.a $98,$68,$47,$37,$30,$31,$33,$32,$33,$32,$33,$32,$3D,$49,$48,$3E
Data.a $38,$43,$5C,$77,$87,$91,$95,$85,$78,$79,$7A,$80,$8D,$8F,$8A,$89
Data.a $8D,$8D,$88,$81,$83,$89,$7F,$73,$77,$7A,$71,$64,$55,$43,$31,$31
Data.a $34,$32,$34,$3A,$41,$36,$2F,$33,$37,$4D,$5C,$69,$73,$78,$7B,$82
Data.a $8A,$8F,$90,$91,$91,$94,$9B,$9C,$94,$86,$75,$67,$5A,$51,$50,$4D
Data.a $45,$42,$41,$41,$43,$48,$51,$54,$59,$65,$75,$82,$87,$86,$83,$7B
Data.a $6E,$67,$65,$63,$61,$5F,$5D,$56,$4E,$4B,$50,$57,$5F,$67,$71,$78
Data.a $7B,$7C,$7E,$82,$83,$80,$7C,$79,$76,$71,$6D,$6C,$68,$5E,$52,$4D
Data.a $4A,$46,$43,$43,$47,$4B,$4B,$4D,$53,$59,$5D,$65,$6F,$79,$82,$8B
Data.a $92,$93,$90,$8B,$88,$83,$7C,$7B,$7B,$76,$6F,$66,$5E,$59,$53,$51
Data.a $53,$55,$57,$59,$5B,$5B,$5A,$5A,$5B,$5E,$61,$67,$6D,$6E,$6C,$69
Data.a $6B,$6F,$72,$73,$75,$77,$79,$78,$79,$7B,$7C,$79,$76,$73,$72,$71
Data.a $6C,$64,$59,$51,$50,$52,$53,$50,$4A,$41,$3B,$3C,$46,$53,$61,$6B
Data.a $6E,$6D,$70,$79,$83,$90,$9B,$A0,$9C,$94,$8C,$85,$7E,$7A,$76,$6F
Data.a $62,$56,$4E,$48,$45,$48,$4D,$4D,$4C,$4E,$54,$5B,$64,$6F,$79,$80
Data.a $83,$82,$82,$85,$88,$88,$87,$84,$7D,$73,$69,$63,$60,$5D,$5A,$55
Data.a $51,$4E,$4E,$52,$58,$5F,$66,$6A,$6D,$73,$7D,$86,$8B,$8F,$8E,$87
Data.a $81,$80,$7F,$79,$72,$6B,$60,$54,$4D,$4C,$4E,$4E,$4F,$50,$52,$58
Data.a $5F,$67,$6F,$75,$79,$7A,$7B,$7E,$82,$81,$7F,$7C,$75,$6F,$6C,$6B
Data.a $6C,$6E,$6F,$6C,$67,$65,$68,$6D,$73,$77,$77,$74,$70,$6C,$6B,$6E
Data.a $72,$73,$6F,$67,$60,$5D,$5E,$61,$63,$64,$63,$61,$60,$63,$69,$70
Data.a $76,$79,$79,$7A,$7C,$7F,$81,$81,$80,$7E,$79,$72,$6E,$6B,$67,$65
Data.a $62,$5F,$5D,$5D,$5E,$5F,$62,$65,$6A,$6E,$71,$75,$78,$7B,$7C,$7D
Data.a $7E,$7F,$7F,$7E,$7B,$77,$74,$6F,$6A,$67,$63,$5D,$56,$50,$49,$45
Data.a $43,$43,$46,$4B,$50,$55,$5A,$60,$69,$74,$81,$8E,$97,$9D,$9F,$9E
Data.a $9C,$9B,$9A,$98,$93,$8A,$7D,$6E,$61,$58,$50,$4C,$49,$46,$45,$44
Data.a $46,$4C,$53,$5C,$66,$6F,$75,$7B,$80,$85,$88,$88,$87,$85,$82,$7E
Data.a $7A,$75,$70,$6B,$66,$61,$5D,$5C,$5E,$61,$65,$69,$6B,$6B,$6B,$6A
Data.a $6B,$6F,$73,$76,$76,$71,$6B,$64,$61,$62,$67,$6D,$71,$72,$72,$72
Data.a $74,$7A,$81,$85,$88,$87,$85,$82,$80,$7D,$79,$72,$6A,$63,$5F,$5F
Data.a $60,$60,$5E,$5A,$58,$58,$5D,$64,$6D,$74,$77,$78,$77,$79,$7D,$82
Data.a $85,$86,$84,$80,$7C,$79,$78,$78,$75,$70,$6B,$66,$64,$66,$68,$6A
Data.a $6B,$68,$64,$63,$66,$6C,$72,$76,$78,$78,$78,$78,$78,$7B,$7E,$80
Data.a $7F,$7D,$7B,$79,$74,$6F,$6A,$65,$63,$61,$5F,$5D,$5C,$5A,$58,$59
Data.a $5E,$66,$6D,$74,$79,$7C,$80,$84,$89,$8B,$8C,$8B,$87,$81,$7C,$77
Data.a $72,$6B,$63,$5B,$55,$52,$53,$55,$57,$59,$59,$5C,$62,$6B,$77,$82
Data.a $8B,$91,$93,$94,$97,$9A,$9B,$98,$92,$8A,$81,$77,$72,$6E,$6A,$65
Data.a $5E,$58,$56,$56,$57,$57,$54,$53,$53,$57,$5E,$67,$6D,$6F,$6E,$6E
Data.a $74,$7F,$8D,$96,$98,$93,$8C,$89,$8B,$91,$97,$96,$8C,$7E,$71,$69
Data.a $67,$67,$65,$5D,$4F,$41,$39,$3B,$45,$51,$59,$5A,$56,$56,$5B,$69
Data.a $7B,$89,$90,$8F,$8A,$87,$86,$89,$8C,$8A,$84,$7B,$75,$75,$78,$7A
Data.a $76,$6D,$63,$5E,$60,$68,$71,$74,$6F,$63,$57,$52,$58,$65,$73,$7B
Data.a $7C,$77,$72,$72,$77,$81,$89,$8C,$88,$81,$7A,$76,$76,$76,$75,$70
Data.a $69,$62,$5F,$62,$68,$6D,$6D,$6A,$68,$68,$6C,$74,$7D,$84,$87,$86
Data.a $84,$84,$86,$89,$8A,$88,$85,$84,$83,$80,$7B,$74,$6B,$61,$5A,$58
Data.a $5A,$5C,$5C,$59,$55,$53,$55,$5B,$65,$72,$7D,$84,$86,$87,$89,$8C
Data.a $92,$98,$9A,$99,$96,$90,$8C,$88,$83,$7F,$79,$72,$6C,$66,$63,$61
Data.a $5E,$59,$52,$4C,$4B,$4E,$55,$5E,$63,$66,$67,$69,$71,$7C,$88,$91
Data.a $93,$91,$8C,$88,$88,$8A,$8E,$8E,$88,$7E,$73,$6A,$67,$66,$66,$65
Data.a $62,$5B,$55,$52,$53,$58,$5F,$65,$69,$6B,$6F,$75,$7C,$83,$88,$8B
Data.a $8B,$89,$8B,$8E,$8E,$8B,$85,$7E,$74,$6E,$6C,$6D,$6D,$6B,$67,$62
Data.a $5F,$60,$64,$67,$6A,$6B,$6C,$6C,$6F,$73,$75,$77,$78,$78,$79,$7C
Data.a $82,$89,$8D,$8D,$8C,$8C,$8C,$8E,$91,$90,$8C,$85,$7C,$74,$6D,$68
Data.a $65,$62,$5E,$5B,$58,$58,$5C,$62,$68,$6C,$70,$75,$7C,$83,$8A,$90
Data.a $96,$98,$98,$96,$93,$8E,$8A,$84,$7F,$7A,$75,$6E,$67,$60,$59,$54
Data.a $52,$53,$57,$5B,$5D,$5E,$60,$65,$6C,$74,$7C,$87,$90,$98,$9D,$A1
Data.a $A2,$A1,$9F,$9C,$9A,$97,$92,$89,$7E,$70,$64,$5C,$57,$55,$53,$52
Data.a $50,$4F,$51,$56,$5D,$66,$6D,$73,$79,$7E,$82,$86,$89,$8B,$8D,$8D
Data.a $8C,$89,$84,$7F,$7B,$79,$77,$77,$76,$73,$6E,$6A,$6A,$6F,$74,$78
Data.a $79,$78,$74,$72,$73,$76,$79,$7B,$7A,$75,$6F,$6A,$68,$69,$6B,$6C
Data.a $6D,$6C,$6C,$6D,$6F,$74,$78,$7C,$80,$82,$85,$88,$8B,$8C,$8B,$88
Data.a $84,$81,$7F,$7D,$7B,$79,$75,$6F,$6A,$67,$65,$65,$68,$6B,$6D,$6F
Data.a $70,$72,$74,$79,$7D,$81,$85,$87,$88,$89,$8A,$8C,$8D,$8D,$8B,$86
Data.a $82,$7F,$7D,$7C,$7A,$77,$73,$6F,$6A,$66,$65,$64,$65,$68,$6B,$6F
Data.a $72,$74,$75,$76,$79,$7D,$83,$8A,$8D,$8C,$88,$82,$7D,$7A,$78,$76
Data.a $73,$6F,$69,$64,$60,$60,$62,$65,$68,$6B,$6F,$75,$7C,$84,$8A,$8E
Data.a $90,$91,$92,$94,$94,$93,$90,$8D,$88,$80,$78,$6F,$68,$64,$62,$60
Data.a $5F,$5D,$5A,$58,$58,$5D,$68,$73,$7D,$83,$87,$89,$8C,$91,$96,$9B
Data.a $9D,$9B,$95,$8C,$83,$7B,$76,$71,$6D,$68,$63,$5D,$58,$56,$57,$5B
Data.a $62,$69,$6F,$75,$7B,$81,$86,$8C,$91,$95,$97,$97,$95,$93,$8F,$88
Data.a $80,$77,$6F,$69,$66,$63,$60,$5C,$58,$54,$53,$59,$62,$6D,$75,$7A
Data.a $7C,$7E,$83,$8D,$98,$A0,$A2,$9E,$97,$90,$8E,$8F,$8F,$8D,$85,$79
Data.a $6E,$66,$65,$68,$6D,$6E,$6B,$65,$60,$60,$65,$6C,$74,$79,$7A,$79
Data.a $78,$79,$7C,$7E,$7F,$7F,$7F,$7F,$80,$82,$84,$84,$83,$82,$81,$83
Data.a $88,$8D,$91,$92,$8E,$88,$82,$7F,$7F,$7F,$7F,$7C,$75,$6A,$60,$59
Data.a $56,$56,$58,$59,$5A,$5A,$5E,$65,$6E,$79,$82,$8A,$91,$97,$9F,$A5
Data.a $AA,$AB,$A6,$9C,$93,$8A,$84,$7E,$76,$6B,$5E,$51,$48,$45,$45,$48
Data.a $4B,$4E,$51,$57,$60,$6E,$7C,$8A,$94,$9B,$A0,$A4,$A8,$AB,$AC,$A9
Data.a $A3,$98,$8C,$7F,$73,$6A,$62,$5A,$54,$4E,$4A,$48,$49,$4D,$55,$60
Data.a $6B,$77,$81,$8A,$92,$9A,$A1,$A9,$AD,$AF,$AD,$A7,$9F,$96,$8C,$84
Data.a $7B,$71,$67,$5C,$52,$4C,$49,$4B,$4F,$54,$5A,$60,$67,$71,$7D,$8A
Data.a $96,$9F,$A4,$A6,$A6,$A5,$A4,$A2,$9C,$94,$89,$7F,$77,$70,$69,$62
Data.a $5A,$54,$4F,$50,$56,$5E,$65,$6B,$6E,$73,$79,$83,$8F,$98,$9F,$A1
Data.a $9F,$9C,$9A,$98,$96,$92,$8C,$84,$7A,$71,$6B,$67,$65,$64,$62,$61
Data.a $61,$62,$67,$6D,$73,$79,$7E,$80,$83,$85,$88,$8A,$8C,$8B,$89,$86
Data.a $84,$84,$84,$84,$82,$7E,$7A,$79,$7A,$7C,$7E,$7E,$7C,$7A,$77,$77
Data.a $79,$7C,$7E,$7D,$7B,$79,$79,$79,$7A,$7B,$7C,$7C,$7B,$7B,$7C,$7D
Data.a $7D,$7C,$7B,$7A,$7B,$7C,$7D,$7D,$7B,$79,$77,$76,$77,$78,$79,$79
Data.a $78,$76,$75,$76,$79,$7A,$7A,$78,$76,$75,$77,$7C,$81,$80,$53,$41
Data.a $55,$52,$00,$02,$00,$00,$31,$2C,$20,$30,$2C,$20,$36,$2C,$20,$30
eClick:
DataSection
;a small wav file saved as raw data
sClick:
Data.q $0000082E46464952,$20746D6645564157,$0001000100000010,$0000AC440000AC44
Data.q $6174616400080001,$8484848300000602,$8B8A898886868585,$C0B3A9A29C95918E
Data.q $31479BD3CED0CFCF,$3233323232323331,$BDAEC4C9A1423133,$D0CFCFD0CFD1CDD4
Data.q $323232333770A9CB,$2E34313332333232,$CFD0CFCACFCFAF53,$9783AAD3CED0CFD0
Data.q $3233313332448AA1,$4430333233323233,$CFD0CFAE7D7E9483,$B7B9C3B8BFD1CED0
Data.q $3233313037476898,$3E48493D32333233,$85959187775C4338,$898A8F8D807A7978
Data.q $737F898381888D8D,$3131435564717A77,$332F36413A343234,$827B7873695C4D37
Data.q $9C9B949191908F8A,$4D50515A67758694,$5451484341414245,$7B83868782756559
Data.q $565D5F616365676E,$7871675F57504B4E,$797C8083827E7C7B,$4D525E686C6D7176
Data.q $4D4B4B474343464A,$8B82796F655D5953,$7B7C83888B909392,$5153595E666F767B
Data.q $5A5A5B5B59575553,$696C6E6D67615E5B,$7879777573726F6B,$71727376797C7B79
Data.q $505352505159646C,$6B6153463C3B414A,$A09B908379706D6E,$6F767A7E858C949C
Data.q $4D4D4845484E5662,$80796F645B544E4C,$8487888885828283,$555A5D606369737D
Data.q $6A665F58524E4E51,$878E8F8B867D736D,$54606B72797F8081,$5852504F4E4E4C4D
Data.q $7E7B7A79756F675F,$6B6C6F757C7F8182,$6D6865676C6F6E6C,$6E6B6C7074777773
Data.q $615E5D60676F7372,$7069636061636463,$81817F7C7A797976,$65676B6E72797E80
Data.q $65625F5E5D5D5F62,$7D7C7B7875716E6A,$6F74777B7E7F7F7E,$454950565D63676A
Data.q $605A55504B464343,$9E9F9D978E817469,$6E7D8A93989A9B9C,$444546494C505861
Data.q $7B756F665C534C46,$7E82858788888580,$5C5D61666B70757A,$6A6B6B6B6965615E
Data.q $646B717676736F6B,$727272716D676261,$8285878885817A74,$5F5F636A72797D80
Data.q $645D58585A5E6060,$827D79777877746D,$7878797C80848685,$6A686664666B7075
Data.q $76726C666364686B,$807E7B7878787878,$656A6F74797B7D7F,$59585A5C5D5F6163
Data.q $84807C79746D665E,$777C81878B8C8B89,$555352555B636B72,$82776B625C595957
Data.q $989B9A979493918B,$656A6E7277818A92,$535457575656585E,$6E6E6F6D675E5753
Data.q $898C9398968D7F74,$69717E8C9697918B,$3B39414F5D656767,$695B56565A595145
Data.q $8986878A8F90897B,$7A7875757B848A8C,$747168605E636D76,$7B7365585257636F
Data.q $8C8981777272777C,$70757676767A8188,$6A6D6D68625F6269,$8687847D746C6868
Data.q $8485888A89868484,$585A616B747B8083,$5B555355595C5C5A,$8C898786847D7265
Data.q $888C9096999A9892,$6163666C72797F83,$5E554E4B4C52595E,$91887C7169676663
Data.q $8E8E8A88888C9193,$656666676A737E88,$655F585352555B62,$8B88837C756F6B69
Data.q $7E858B8E8E8B898B,$62676B6D6D6C6E74,$6C6C6B6A6764605F,$7C7978787775736F
Data.q $8E8C8C8C8D8D8982,$686D747C858C9091,$625C58585B5E6265,$908A837C75706C68
Data.q $848A8E9396989896,$545960676E757A7F,$65605E5D5B575352,$A19D9890877C746C
Data.q $8992979A9C9FA1A2,$525355575C64707E,$736D665D56514F50,$8D8D8B8986827E79
Data.q $7777797B7F84898C,$78746F6A6A6E7376,$7B79767372747879,$6C6B69686A6F757A
Data.q $7C78746F6D6C6C6D,$888B8C8B88858280,$6F75797B7D7F8184,$6F6D6B686565676A
Data.q $8785817D79747270,$868B8D8D8C8A8988,$6F73777A7C7D7F82,$6F6B68656465666A
Data.q $8A837D7976757472,$76787A7D82888C8D,$6562606064696F73,$8E8A847C756F6B68
Data.q $8D90939494929190,$606264686F788088,$73685D58585A5D5F,$9B96918C8987837D
Data.q $71767B838C959B9D,$5B5756585D63686D,$8C86817B756F6962,$888F939597979591
Data.q $5C606366696F7780,$7A756D6259535458,$9EA2A0988D837E7C,$79858D8F8F8E9097
Data.q $656B6E6D6865666E,$797A79746C656060,$7F7F7F7F7E7C7978,$8381828384848280
Data.q $7F82888E92918D88,$59606A757C7F7F7F,$655E5A5A59585656,$A59F97918A82796E
Data.q $7E848A939CA6ABAA,$48454548515E6B76,$8A7C6E6057514E4B,$A9ACABA8A4A09B94
Data.q $5A626A737F8C98A3,$60554D49484A4E54,$A9A19A928A81776B,$848C969FA7ADAFAD
Data.q $4B494C525C67717B,$8A7D7167605A544F,$A2A4A5A6A6A49F96,$626970777F89949C
Data.q $6B655E56504F545A,$A19F988F8379736E,$848C9296989A9C9F,$61626465676B717A
Data.q $807E79736D676261,$86898B8C8A888583,$797A7E8284848484,$77777A7C7E7E7C7A
Data.q $7979797B7D7E7C79,$7D7C7B7B7C7C7B7A,$7D7D7C7B7A7B7C7D,$797978777677797B
Data.q $787A7A7976757678,$415380817C777576,$2C31000002005255,$30202C36202C3020
eClick:
EndDataSection

View file

@ -1,18 +1,19 @@
/*REXX program simulates a visual (textual) metronome (with no sound).*/
parse arg bpm bpb dur .
if bpm=='' | bpm==',' then bpm=72 /*number of beats per minute. */
if bpb=='' | bpb==',' then bpb= 4 /*number of beats per bar. */
if dur=='' | dur==',' then dur= 5 /*duration of run in seconds. */
call time 'R' /*reset the REXX elapsed timer. */
bt=1/bpb /*calculate a tock-time interval.*/
/*REXX program simulates a visual (textual) metronome (with no sound). */
parse arg bpm bpb dur . /*obtain optional arguments from the CL*/
if bpm=='' | bpm=="," then bpm=72 /*the number of beats per minute. */
if bpb=='' | bpb=="," then bpb= 4 /* " " " " " bar. */
if dur=='' | dur=="," then dur= 5 /*duration of the run in seconds. */
call time 'Reset' /*reset the REXX elapsed timer. */
bt=1/bpb /*calculate a tock-time interval. */
do until et>=dur; et=time('E') /*process tick-tocks for duration*/
say; call charout ,'TICK' /*show the first tick for period.*/
es=et+1 /*bump the elapsed time limiter. */
ee=et+bt
do until time('E')>=es; e=time('E')
if e<ee then iterate /*time for tock?*/
call charout ,' tock' /*show a "tock".*/
ee=ee+bt /*bump tock time*/
end /*until time('E')≥es*/
do until et>=dur; et=time('Elasped') /*process tick-tocks for the duration*/
say; call charout ,'TICK' /*show the first tick for the period. */
es=et+1 /*bump the elapsed time "limiter". */
$t=et+bt
do until e>=es; e=time('Elapsed')
if e<$t then iterate /*time for tock? */
call charout , ' tock' /*show a "tock". */
$t=$t+bt /*bump the TOCK time.*/
end /*until e≥es*/
end /*until et≥dur*/
/*stick a fork in it, we're all done. */

View file

@ -1,22 +1,23 @@
/*REXX program simulates a metronome (with sound), Regina REXX only. */
parse arg bpm bpb dur tockf tockd tickf tickd .
if bpm=='' | bpm==',' then bpm=72 /*number of beats per minute. */
if bpb=='' | bpb==',' then bpb= 4 /*number of beats per bar. */
if dur=='' | dur==',' then dur= 5 /*duration of run in seconds. */
if tockf==''|tockf==',' then tockf=400 /*frequency of tock sound in HZ. */
if tockd==''|tockd==',' then tockd= 20 /*duration of tock sound in msec*/
if tickf==''|tickf==',' then tickf=600 /*frequency of tick sound in HZ. */
if tickd==''|tickd==',' then tickd= 10 /*duration of tick sound in msec*/
call time 'R' /*reset the REXX elapsed timer. */
bt=1/bpb /*calculate a tock-time interval.*/
/*REXX program simulates a metronome (with sound). Regina REXX only. */
parse arg bpm bpb dur tockf tockd tickf tickd . /*obtain optional arguments from the CL*/
if bpm=='' | bpm=="," then bpm= 72 /*the number of beats per minute. */
if bpb=='' | bpb=="," then bpb= 4 /* " " " " " bar. */
if dur=='' | dur=="," then dur= 5 /*duration of the run in secs*/
if tockf=='' | tockf=="," then tockf=400 /*frequency " " tock sound " HZ. */
if tockd=='' | tockd=="," then tockd= 20 /*duration " " " " " msec*/
if tickf=='' | tickf=="," then tickf=600 /*frequency " " tick " " HZ. */
if tickd=='' | tickd=="," then tickd= 10 /*duration " " " " " msec*/
call time 'Reset' /*reset the REXX elapsed timer. */
bt=1/bpb /*calculate a tock─time interval. */
do until et>=dur; et=time('E') /*process tick-tocks for duration*/
call beep tockf,tockd /*sound a beep for the "TOCK". */
es=et+1 /*bump the elapsed time limiter. */
ee=et+bt
do until time('E')>=es; e=time('E')
if e<ee then iterate /*time for tock?*/
call beep tickf,tickd /*sound a tick.*/
ee=ee+bt /*bump tock time*/
end /*until time('E')≥es*/
do until et>=dur; et=time('Elasped') /*process tick-tocks for the duration*/
call beep tockf, tockd /*sound a beep for the "TOCK". */
es=et+1 /*bump the elapsed time "limiter". */
$t=et+bt
do until e>=es; e=time('Elapsed')
if e<$t then iterate /*time for tock? */
call beep tickf, tickd /*sound a "tick". */
$t=$t+bt /*bump the TOCK time.*/
end /*until e≥es*/
end /*until et≥dur*/
/*stick a fork in it, we're all done. */

View file

@ -1,22 +1,23 @@
/*REXX program simulates a metronome (with sound), PC/REXX only. */
parse arg bpm bpb dur tockf tockd tickf tickd .
if bpm=='' | bpm==',' then bpm=72 /*number of beats per minute. */
if bpb=='' | bpb==',' then bpb= 4 /*number of beats per bar. */
if dur=='' | dur==',' then dur= 5 /*duration of run in seconds. */
if tockf==''|tockf==',' then tockf=400 /*frequency of tock sound in HZ. */
if tockd==''|tockd==',' then tockd=.02 /*duration of tock sound in secs*/
if tickf==''|tickf==',' then tickf=600 /*frequency of tick sound in HZ. */
if tickd==''|tickd==',' then tickd=.01 /*duration of tick sound in secs*/
call time 'R' /*reset the REXX elapsed timer. */
bt=1/bpb /*calculate a tock-time interval.*/
/*REXX program simulates a metronome (with sound). PC/REXX or Personal REXX only.*/
parse arg bpm bpb dur tockf tockd tickf tickd . /*obtain optional arguments from the CL*/
if bpm=='' | bpm=="," then bpm= 72 /*the number of beats per minute. */
if bpb=='' | bpb=="," then bpb= 4 /* " " " " " bar. */
if dur=='' | dur=="," then dur= 5 /*duration of the run in secs*/
if tockf=='' | tockf=="," then tockf=400 /*frequency " " tock sound " HZ. */
if tockd=='' | tockd=="," then tockd= .02 /*duration " " " " " sec.*/
if tickf=='' | tickf=="," then tickf=600 /*frequency " " tick " " HZ. */
if tickd=='' | tickd=="," then tickd= .01 /*duration " " " " " sec.*/
call time 'Reset' /*reset the REXX elapsed timer. */
bt=1/bpb /*calculate a tock─time interval. */
do until et>=dur; et=time('E') /*process tick-tocks for duration*/
call sound tockf,tockd /*sound a beep for the "TOCK". */
es=et+1 /*bump the elapsed time limiter. */
ee=et+bt
do until time('E')>=es; e=time('E')
if e<ee then iterate /*time for tock?*/
call sound tickf,tickd /*sound a tick.*/
ee=ee+bt /*bump tock time*/
end /*until time('E')≥es*/
do until et>=dur; et=time('Elasped') /*process tick-tocks for the duration*/
call sound tockf, tockd /*sound a beep for the "TOCK". */
es=et+1 /*bump the elapsed time "limiter". */
$t=et+bt
do until e>=es; e=time('Elapsed')
if e<$t then iterate /*time for tock? */
call sound tickf, tickd /*sound a tick. */
$t=$t+bt /*bump the TOCK time.*/
end /*until e≥es*/
end /*until et≥dur*/
/*stick a fork in it, we're all done. */