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