A-M baby
This commit is contained in:
parent
764da6cbbb
commit
db842d013d
19005 changed files with 197040 additions and 7 deletions
6
Task/Metronome/0DESCRIPTION
Normal file
6
Task/Metronome/0DESCRIPTION
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
<!--{{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.
|
||||
|
||||
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.
|
||||
31
Task/Metronome/AutoHotkey/metronome.ahk
Normal file
31
Task/Metronome/AutoHotkey/metronome.ahk
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
bpm = 120 ; Beats per minute
|
||||
pattern = 4/4 ;
|
||||
duration = 100 ; Milliseconds
|
||||
beats = 0 ; internal counter
|
||||
|
||||
Gui -Caption
|
||||
|
||||
StringSplit, p, pattern, /
|
||||
|
||||
Start := A_TickCount
|
||||
|
||||
Loop
|
||||
{
|
||||
Gui Color, 0xFF0000
|
||||
Gui Show, w200 h200 Na
|
||||
SoundBeep 750, duration
|
||||
beats++
|
||||
Sleep 1000 * 60 / bpm - duration
|
||||
Loop % p1 -1
|
||||
{
|
||||
Gui Color, 0x00FF00
|
||||
Gui Show, w200 h200 Na
|
||||
SoundBeep, , duration
|
||||
beats++
|
||||
Sleep 1000 * 60 / bpm - duration
|
||||
}
|
||||
}
|
||||
|
||||
Esc::
|
||||
MsgBox % "Metronome beeped " beats " beats, over " (A_TickCount-Start)/1000 " seconds. "
|
||||
ExitApp
|
||||
21
Task/Metronome/BBC-BASIC/metronome.bbc
Normal file
21
Task/Metronome/BBC-BASIC/metronome.bbc
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
BeatPattern$ = "HLLL"
|
||||
Tempo% = 100
|
||||
|
||||
*font Arial,36
|
||||
REPEAT
|
||||
FOR beat% = 1 TO LEN(BeatPattern$)
|
||||
IF MID$(BeatPattern$, beat%, 1) = "H" THEN
|
||||
SOUND 1,-15,148,1
|
||||
ELSE
|
||||
SOUND 1,-15,100,1
|
||||
ENDIF
|
||||
VDU 30
|
||||
COLOUR 2
|
||||
PRINT LEFT$(BeatPattern$,beat%-1);
|
||||
COLOUR 9
|
||||
PRINT MID$(BeatPattern$,beat%,1);
|
||||
COLOUR 2
|
||||
PRINT MID$(BeatPattern$,beat%+1);
|
||||
WAIT 6000/Tempo%
|
||||
NEXT
|
||||
UNTIL FALSE
|
||||
86
Task/Metronome/C/metronome.c
Normal file
86
Task/Metronome/C/metronome.c
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <stdint.h>
|
||||
#include <signal.h>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
struct timeval start, last;
|
||||
|
||||
inline int64_t tv_to_u(struct timeval s)
|
||||
{
|
||||
return s.tv_sec * 1000000 + s.tv_usec;
|
||||
}
|
||||
|
||||
inline struct timeval u_to_tv(int64_t x)
|
||||
{
|
||||
struct timeval s;
|
||||
s.tv_sec = x / 1000000;
|
||||
s.tv_usec = x % 1000000;
|
||||
return s;
|
||||
}
|
||||
|
||||
void draw(int dir, int64_t period, int64_t cur, int64_t next)
|
||||
{
|
||||
int len = 40 * (next - cur) / period;
|
||||
int s, i;
|
||||
|
||||
if (len > 20) len = 40 - len;
|
||||
s = 20 + (dir ? len : -len);
|
||||
|
||||
printf("\033[H");
|
||||
for (i = 0; i <= 40; i++) putchar(i == 20 ? '|': i == s ? '#' : '-');
|
||||
}
|
||||
|
||||
void beat(int delay)
|
||||
{
|
||||
struct timeval tv = start;
|
||||
int dir = 0;
|
||||
int64_t d = 0, corr = 0, slp, cur, next = tv_to_u(start) + delay;
|
||||
int64_t draw_interval = 20000;
|
||||
printf("\033[H\033[J");
|
||||
while (1) {
|
||||
gettimeofday(&tv, 0);
|
||||
slp = next - tv_to_u(tv) - corr;
|
||||
usleep(slp);
|
||||
gettimeofday(&tv, 0);
|
||||
|
||||
putchar(7); /* bell */
|
||||
fflush(stdout);
|
||||
|
||||
printf("\033[5;1Hdrift: %d compensate: %d (usec) ",
|
||||
(int)d, (int)corr);
|
||||
dir = !dir;
|
||||
|
||||
cur = tv_to_u(tv);
|
||||
d = cur - next;
|
||||
corr = (corr + d) / 2;
|
||||
next += delay;
|
||||
|
||||
while (cur + d + draw_interval < next) {
|
||||
usleep(draw_interval);
|
||||
gettimeofday(&tv, 0);
|
||||
cur = tv_to_u(tv);
|
||||
draw(dir, delay, cur, next);
|
||||
fflush(stdout);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(int c, char**v)
|
||||
{
|
||||
int bpm;
|
||||
|
||||
if (c < 2 || (bpm = atoi(v[1])) <= 0) bpm = 60;
|
||||
if (bpm > 600) {
|
||||
fprintf(stderr, "frequency %d too high\n", bpm);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
gettimeofday(&start, 0);
|
||||
last = start;
|
||||
beat(60 * 1000000 / bpm);
|
||||
|
||||
return 0;
|
||||
}
|
||||
52
Task/Metronome/Haskell/metronome.hs
Normal file
52
Task/Metronome/Haskell/metronome.hs
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
import Control.Concurrent
|
||||
import Control.Concurrent.MVar
|
||||
import System.Process (runCommand)
|
||||
|
||||
-- This program works only on the GHC compiler because of the use of
|
||||
-- threadDelay
|
||||
|
||||
data Beep = Stop | Hi | Low
|
||||
|
||||
type Pattern = [Beep]
|
||||
|
||||
type BeatsPerMinute = Int
|
||||
|
||||
minute = 60000000 -- 1 minute = 60,000,000 microseconds
|
||||
|
||||
-- give one of the following example patterns to the metronome function
|
||||
|
||||
pattern4_4 = [Hi, Low, Low, Low]
|
||||
pattern2_4 = [Hi, Low]
|
||||
pattern3_4 = [Hi, Low, Low]
|
||||
pattern6_8 = [Hi, Low, Low, Low, Low, Low]
|
||||
|
||||
-- use this version if you can't play audio, use Windows or don't
|
||||
-- have audio files to play
|
||||
-- beep :: Beep -> IO ()
|
||||
-- beep Stop = return ()
|
||||
-- beep Hi = putChar 'H'
|
||||
-- beep Low = putChar 'L'
|
||||
|
||||
-- use this version if you can and want to play audio on Linux using
|
||||
-- Alsa. Change the name of the files to those of your choice
|
||||
|
||||
beep Stop = return ()
|
||||
beep Hi = putChar 'H' >> runCommand "aplay hi.wav &> /dev/null" >> return ()
|
||||
beep Low = putChar 'L' >> runCommand "aplay low.wav &> /dev/null" >> return ()
|
||||
|
||||
tick :: MVar Pattern -> BeatsPerMinute -> IO ()
|
||||
tick b i = do
|
||||
t <- readMVar b
|
||||
case t of
|
||||
[Stop] -> return ()
|
||||
x -> do
|
||||
mapM_ (\v -> forkIO (beep v) >> threadDelay (minute `div` i)) t
|
||||
tick b i
|
||||
|
||||
metronome :: Pattern -> BeatsPerMinute -> IO ()
|
||||
metronome p i = do
|
||||
putStrLn "Press any key to stop the metronome."
|
||||
b <- newMVar p
|
||||
_ <- forkIO $ tick b i
|
||||
_ <- getChar
|
||||
putMVar b [Stop]
|
||||
85
Task/Metronome/Liberty-BASIC/metronome.liberty
Normal file
85
Task/Metronome/Liberty-BASIC/metronome.liberty
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
WindowWidth =230
|
||||
WindowHeight =220
|
||||
|
||||
button #w.b1 "Start", [start], LR, 110, 90, 55, 20
|
||||
button #w.b2 "Tempo", [tempo], LR, 180, 90, 55, 20
|
||||
button #w.b3 "Pattern", [pattern], LR, 40, 90, 55, 20
|
||||
|
||||
open "Metronome" for graphics_nsb_nf as #w
|
||||
|
||||
#w "trapclose quit"
|
||||
#w "down"
|
||||
#w "fill darkblue ; backcolor darkblue ; color white"
|
||||
|
||||
tempo = 60 ' per minute
|
||||
interval =1000 /(tempo /60) ' timer works in ms
|
||||
tickCount = 0 ' cycle counter
|
||||
running = 1 ' flag for state
|
||||
bar$ = "HLLL" ' initially strong-weak-weak-weak
|
||||
count = len( bar$)
|
||||
|
||||
wait
|
||||
|
||||
sub quit w$
|
||||
close #w$
|
||||
end
|
||||
end sub
|
||||
|
||||
[start]
|
||||
if running =1 then
|
||||
running =0
|
||||
#w.b1 "Stop"
|
||||
#w.b2 "!disable"
|
||||
#w.b3 "!disable"
|
||||
else
|
||||
running =1
|
||||
#w.b1 "Start"
|
||||
#w.b2 "!enable"
|
||||
#w.b3 "!enable"
|
||||
end if
|
||||
if running =0 then timer interval, [tick] else timer 0
|
||||
wait
|
||||
|
||||
[tempo]
|
||||
prompt "New tempo 30...360"; tempo$
|
||||
tempo =val( tempo$)
|
||||
tempo =min( tempo, 360)
|
||||
tempo =max( tempo, 30)
|
||||
interval =int( 1000 /(tempo /60))
|
||||
wait
|
||||
|
||||
[pattern]
|
||||
prompt "New Pattern, eg 'HLLL' "; bar$
|
||||
count =len( bar$)
|
||||
if count <2 or count >8 then goto [pattern]
|
||||
|
||||
wait
|
||||
|
||||
[tick]
|
||||
'beep and flash
|
||||
#w "place 115 40"
|
||||
|
||||
if mid$( bar$, tickCount +1, 1) ="H" then
|
||||
playwave "mHi.wav", async
|
||||
#w "backcolor blue ; color white ; circlefilled "; 20 -tickCount *2
|
||||
else
|
||||
playwave "mLo.wav", async
|
||||
#w "backcolor cyan ; circlefilled "; 20 -tickCount *2
|
||||
end if
|
||||
|
||||
#w "place 50 140 ; backcolor darkblue ; color white"
|
||||
#w "\ "; tempo; " beats /min."
|
||||
#w "place 85 160"
|
||||
#w "\"; bar$
|
||||
|
||||
#w "place 85 120"
|
||||
#w "\Beat # "; tickCount +1
|
||||
|
||||
#w "place 115 40"
|
||||
#w "color darkblue"
|
||||
|
||||
tickCount =( tickCount +1) mod count
|
||||
|
||||
#w "flush"
|
||||
|
||||
wait
|
||||
9
Task/Metronome/PicoLisp/metronome-1.l
Normal file
9
Task/Metronome/PicoLisp/metronome-1.l
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
(de metronome (Bpm)
|
||||
(if (fork)
|
||||
(let Pid @
|
||||
(for Pendulum '(" /" . ("^H^H\\ " "^H^H /" .))
|
||||
(tell Pid 'call "/usr/bin/beep" "-f" 440 "-l" 40)
|
||||
(prin Pendulum)
|
||||
(T (key (*/ 30000 Bpm)) (tell Pid 'bye)) )
|
||||
(prinl) )
|
||||
(wait) ) )
|
||||
3
Task/Metronome/PicoLisp/metronome-2.l
Normal file
3
Task/Metronome/PicoLisp/metronome-2.l
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
: (metronome 60)
|
||||
/
|
||||
-> NIL # A key was hit
|
||||
18
Task/Metronome/REXX/metronome-1.rexx
Normal file
18
Task/Metronome/REXX/metronome-1.rexx
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
/*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.*/
|
||||
|
||||
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*/
|
||||
end /*until et≥dur*/
|
||||
22
Task/Metronome/REXX/metronome-2.rexx
Normal file
22
Task/Metronome/REXX/metronome-2.rexx
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
/*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.*/
|
||||
|
||||
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*/
|
||||
end /*until et≥dur*/
|
||||
22
Task/Metronome/REXX/metronome-3.rexx
Normal file
22
Task/Metronome/REXX/metronome-3.rexx
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
/*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.*/
|
||||
|
||||
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*/
|
||||
end /*until et≥dur*/
|
||||
26
Task/Metronome/Tcl/metronome-1.tcl
Normal file
26
Task/Metronome/Tcl/metronome-1.tcl
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
package require Tcl 8.5
|
||||
|
||||
lassign $argv bpm bpb
|
||||
if {$argc < 2} {set bpb 4}
|
||||
if {$argc < 1} {set bpm 60}
|
||||
|
||||
fconfigure stdout -buffering none
|
||||
set intervalMS [expr {round(60000.0 / $bpm)}]
|
||||
set ctr 0
|
||||
|
||||
proc beat {} {
|
||||
global intervalMS ctr bpb
|
||||
after $intervalMS beat ;# Reschedule first, to encourage minimal drift
|
||||
if {[incr ctr] == 1} {
|
||||
puts -nonewline "\r\a[string repeat { } [expr {$bpb+4}]]\rTICK"
|
||||
} else {
|
||||
puts -nonewline "\rtick[string repeat . [expr {$ctr-1}]]"
|
||||
}
|
||||
if {$ctr >= $bpb} {
|
||||
set ctr 0
|
||||
}
|
||||
}
|
||||
|
||||
# Run the metronome until the user uses Ctrl+C...
|
||||
beat
|
||||
vwait forever
|
||||
1
Task/Metronome/Tcl/metronome-2.tcl
Normal file
1
Task/Metronome/Tcl/metronome-2.tcl
Normal file
|
|
@ -0,0 +1 @@
|
|||
tclsh8.5 metronome.tcl 90 4
|
||||
Loading…
Add table
Add a link
Reference in a new issue