Metronome: Difference between revisions

7,973 bytes added ,  3 months ago
added RPL
(added RPL)
 
(9 intermediate revisions by 6 users not shown)
Line 18:
{{trans|Python}}
 
<langsyntaxhighlight lang="11l">F main(bpm = 72, bpb = 4)
V t = 60.0 / bpm
V counter = 0
Line 29:
sleep(t)
 
main()</langsyntaxhighlight>
 
=={{header|Ada}}==
{{This metronome only does 60 bpm with 1 Measure length.}}
<langsyntaxhighlight Adalang="ada">
with Ada.Text_IO; use Ada.Text_IO;
 
Line 55:
end loop;
 
end Main;</langsyntaxhighlight>
 
=={{header|AppleScript}}==
<langsyntaxhighlight lang="applescript">set bpm to the text returned of (display dialog "How many beats per minute?" default answer 60)
set pauseBetweenBeeps to (60 / bpm)
repeat
beep
delay pauseBetweenBeeps
end repeat</langsyntaxhighlight>
 
=={{header|Arturo}}==
<langsyntaxhighlight lang="rebol">startMetronome: function [bpm,msr][
freq: 60000/bpm
i: 0
Line 83:
beats: to :integer arg\1
 
startMetronome tempo beats</langsyntaxhighlight>
 
=={{header|AutoHotkey}}==
Rather basic implementation, but meets the requirements and is reasonably accurate.
<langsyntaxhighlight AHKlang="ahk">bpm = 120 ; Beats per minute
pattern = 4/4 ;
duration = 100 ; Milliseconds
Line 117:
Esc::
MsgBox % "Metronome beeped " beats " beats, over " (A_TickCount-Start)/1000 " seconds. "
ExitApp</langsyntaxhighlight>
 
=={{header|AWK}}==
<syntaxhighlight lang="awk">
<lang AWK>
# syntax: GAWK -f METRONOME.AWK
@load "time"
Line 141:
}
}
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 155:
=={{header|BBC BASIC}}==
{{works with|BBC BASIC for Windows}}
<langsyntaxhighlight lang="bbcbasic"> BeatPattern$ = "HLLL"
Tempo% = 100
Line 175:
WAIT 6000/Tempo%
NEXT
UNTIL FALSE</langsyntaxhighlight>
 
=={{header|C}}==
Using <code>usleep</code> with self correcting delays. Audio is the bell character, which will definitely drive one insane (but I'm ok: my computer doesn't have the bell device). Invoke with <code>./a.out [beats_per_minute]</code>, default to 60.
<langsyntaxhighlight lang="c">#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
Line 264:
 
return 0;
}</langsyntaxhighlight>
 
 
=={{header|C#}}==
{{trans|Java}}
<syntaxhighlight lang="C#">
using System;
using System.Threading;
 
public class Program
{
public static void Main(string[] args)
{
Metronome metronome1 = new Metronome(120, 4);
metronome1.Start();
}
}
 
public class Metronome
{
private double bpm;
private int measure;
private int counter;
 
public Metronome(double bpm, int measure)
{
this.bpm = bpm;
this.measure = measure;
}
 
public void Start()
{
Thread thread = new Thread(() =>
{
while (true)
{
try
{
Thread.Sleep((int)(1000 * (60.0 / bpm)));
}
catch (ThreadInterruptedException e)
{
Console.WriteLine(e.StackTrace);
}
counter++;
if (counter % measure == 0)
{
Console.WriteLine("TICK");
}
else
{
Console.WriteLine("TOCK");
}
}
});
 
thread.Start();
}
}
</syntaxhighlight>
 
 
=={{header|C++}}==
This example has a timing loop to ensure that its timing is reliable in the long term.
<syntaxhighlight lang="c++">
#include <chrono>
#include <cstdint>
#include <iostream>
#include <thread>
 
class Metronome {
public:
Metronome(const int32_t& aBeats_per_minute, const int32_t& aMeasure, const int32_t& aDuration_in_minutes)
: beats_per_minute(aBeats_per_minute), measure(aMeasure), duration_in_minutes(aDuration_in_minutes) {
counter = 0;
}
 
void start() {
while ( counter < duration_in_minutes * beats_per_minute ) {
start_time = std::chrono::system_clock::now();
 
std::this_thread::sleep_until(time_to_awake());
counter++;
if ( counter % measure != 0 ) {
std::cout << "Tick " << std::flush;
} else {
std::cout << "Tock" << std::endl;
}
}
}
 
private:
std::chrono::system_clock::time_point time_to_awake() const {
return start_time + std::chrono::seconds(1);
}
 
std::chrono::system_clock::time_point start_time;
int32_t counter;
 
const int32_t beats_per_minute, measure, duration_in_minutes;
};
 
int main() {
Metronome metronome(60, 4, 1);
metronome.start();
}
</syntaxhighlight>
{{ out }}
<pre>
Tick Tick Tick Tock
Tick Tick Tick Tock
Tick Tick
// continues for the requested duration
</pre>
 
=={{header|Common Lisp}}==
Depends on quicklisp and OpenAL.
<langsyntaxhighlight lang="lisp">(ql:quickload '(cl-openal cl-alc))
 
(defparameter *short-max* (- (expt 2 15) 1))
Line 331 ⟶ 444:
(h (play-it high-buffer)))
(princ symbol))
(terpri)))))))))))</langsyntaxhighlight>
<pre>CL-USER> (metronome 100 '(h l l l))
HLLL
Line 339 ⟶ 452:
{{libheader| System.SysUtils}}
{{Trans|Java}}
<syntaxhighlight lang="delphi">
<lang Delphi>
program Metronome;
 
Line 366 ⟶ 479:
begin
StartMetronome(120, 4);
end.</langsyntaxhighlight>
{{out}}
<pre>TOCK
Line 383 ⟶ 496:
 
=={{header|EchoLisp}}==
<langsyntaxhighlight lang="scheme">
;; available preloaded sounds are : ok, ko, tick, tack, woosh, beep, digit .
(lib 'timer)
Line 390 ⟶ 503:
(at-every 1000 'metronome) ;; every 1000 msec
;; CTRL-C to stop
</syntaxhighlight>
</lang>
 
=={{header|F Sharp|F#}}==
<langsyntaxhighlight lang="fsharp">open System
open System.Threading
// You can use .wav files for your clicks.
Line 427 ⟶ 540:
Seq.initInfinite (fun i -> i + 1)
|> Seq.iter (fun _ -> tempo |> play beats 1 |> ignore)
0 </langsyntaxhighlight>
Sample run:
<pre>$ metronome 120 6
Line 439 ⟶ 552:
 
=={{header|Factor}}==
<langsyntaxhighlight lang="factor">USING: accessors calendar circular colors.constants colors.hsv
command-line continuations io kernel math math.parser namespaces
openal.example sequences system timers ui ui.gadgets
Line 506 ⟶ 619:
[ [ metronome-cmdline metronome-ui ] [ drop metronome-usage 1 exit ] recover ] with-ui ;
 
MAIN: metronome-main</langsyntaxhighlight>
 
 
=={{header|FreeBASIC}}==
<langsyntaxhighlight lang="freebasic">REM FreeBASIC no tiene la capacidad de emitir sonido de forma nativa.
REM La función Sound no es mía, incluyo los créditos correspondientes.
' Sound Function v0.3 For DOS/Linux/Win by yetifoot
Line 591 ⟶ 704:
Sleep(retardo)
Loop
End Sub</langsyntaxhighlight>
 
=={{header|FutureBasic}}==
An Apple Mac application that, when compiled with FB, produces a packaged, stand-alone 64-bit application that will run on either Intel or the newer M-series Macs. It's GUI includes a slider control to adjust speed, as well as blinking indicator and a sound, to indicate tempo. The code has been tested on Catalina (10.15.x) to Monterey (12.4.x) with Ventura still in beta at the time of this post. The free FB compiler is available on the
[http://www.brilorsoftware.com/fb/pages/home.html FutureBasic] home page.
<langsyntaxhighlight lang="futurebasic">
/*
Basic Tempo Markings from slowest to fastest:
Line 776 ⟶ 889:
 
HandleEvents
</syntaxhighlight>
</lang>
{{output}}
<pre>
[Since this code generates a standalone 64-bit Macintosh application with its own window and controls, it has to be compiled with FB to see the GUI and test the output.]
</pre>
 
Line 793 ⟶ 906:
So, as long as the output or sound production finishes before the next tick,
the timing will be reliable and will not drift which is the gist of this task.
<langsyntaxhighlight lang="go">package main
 
import (
Line 817 ⟶ 930:
}
}
}</langsyntaxhighlight>
{{out}}
<pre>
Line 831 ⟶ 944:
{{works with|GHC|7.4.2}}
 
<langsyntaxhighlight Haskelllang="haskell">import Control.Concurrent
import Control.Concurrent.MVar
import System.Process (runCommand)
Line 882 ⟶ 995:
_ <- forkIO $ tick b i
_ <- getChar
putMVar b [Stop]</langsyntaxhighlight>
 
=={{header|J}}==
Line 889 ⟶ 1,002:
MET returns the total number of measures, beats, and elapsed time.<br>
If you leave out the left arguments, it will set them to infinity, so you can go insane without worrying about the metronome ever stopping.
<syntaxhighlight lang="j">
<lang j>
MET=: _ _&$: :(4 : 0)
 
Line 930 ⟶ 1,043:
'`print delay'=: 1!:2&4`(6!:3)
met=: _&$: :((] ({:@] [ LF print@[ (-.@{.@] [ delay@[ print@] (BEL,2#BS) , (2 2$'\ /') {~ {.@])^:({:@])) 1 , <.@%) 60&% [ print@('\ '"_))
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 946 ⟶ 1,059:
 
=={{header|Java}}==
<langsyntaxhighlight lang="java">
class Metronome{
double bpm;
Line 976 ⟶ 1,089:
}
}
</syntaxhighlight>
</lang>
 
===AudioVisual===
This example provides an audible and visual indications of the metronome timing.
 
It uses a timing loop to ensure that its timing is reliable in the long term.
<syntaxhighlight lang="java">
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.io.IOException;
import java.net.URL;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
 
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JPanel;
 
public final class MetronomeTask {
 
public static void main(String[] aArgs) {
EventQueue.invokeLater( () -> { new Metronome(60, 4, 1).start(); } );
}
 
}
 
final class Metronome extends JPanel {
public Metronome(int aBeatsPerMinute, int aMeasure, int aDurationInMinutes) {
beatsPerMinute = aBeatsPerMinute; measure = aMeasure; durationInMinutes = aDurationInMinutes;
SoundEffect.initialise();
createAndShowGUI();
}
public void start() {
executorService = Executors.newSingleThreadScheduledExecutor();
executorService.scheduleAtFixedRate(provideService, 1, 1, TimeUnit.SECONDS);
}
private void createAndShowGUI() {
JFrame.setDefaultLookAndFeelDecorated(true);
frame = new JFrame("Metronome");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setIconImage( new ImageIcon("./metronomeJava.png").getImage() );
frame.add(createPanel());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setResizable(false);
frame.setVisible(true);
}
private JPanel createPanel() {
setPreferredSize( new Dimension(800, 600) );
setBackground(Color.CYAN);
return this;
}
private JFrame frame;
private ScheduledExecutorService executorService;
private int beatsPerMinute, measure, durationInMinutes, counter;
private Runnable provideService = () -> {
if ( counter < durationInMinutes * beatsPerMinute ) {
counter++;
if ( counter % measure != 0 ) {
SoundEffect.Tick.play();
if ( getBackground() != Color.PINK ) {
setBackground(Color.PINK);
} else {
setBackground(Color.CYAN);
}
} else {
SoundEffect.Tock.play();
setBackground(Color.ORANGE);
}
} else {
executorService.shutdown();
frame.dispose();
Runtime.getRuntime().exit(0);
}
};
}
 
enum SoundEffect {
Tick("./metronomeTickJava.wav"), Tock("./metronomeTockJava.wav");
public static void initialise() {
values();
}
public void play() {
if ( clip.isRunning() ) {
clip.stop();
}
clip.setFramePosition(0);
clip.start();
}
private SoundEffect(String soundFileName) {
URL url = getClass().getClassLoader().getResource(soundFileName);
try ( AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(url) ) {
clip = AudioSystem.getClip();
clip.open(audioInputStream);
} catch (IOException | LineUnavailableException | UnsupportedAudioFileException ex) {
ex.printStackTrace();
}
}
private Clip clip;
}
</syntaxhighlight>
 
=={{header|Julia}}==
{{works with|Julia|0.6}}
 
<langsyntaxhighlight lang="julia">function metronome(bpm::Real=72, bpb::Int=4)
s = 60.0 / bpm
counter = 0
Line 993 ⟶ 1,226:
sleep(s)
end
end</langsyntaxhighlight>
 
=={{header|Kotlin}}==
<langsyntaxhighlight lang="scala">// version 1.1.2
 
fun metronome(bpm: Int, bpb: Int, maxBeats: Int = Int.MAX_VALUE) {
Line 1,011 ⟶ 1,244:
}
 
fun main(args: Array<String>) = metronome(120, 4, 20) // limit to 20 beats </langsyntaxhighlight>
 
{{out}}
Line 1,024 ⟶ 1,257:
=={{header|Liberty BASIC}}==
Requires two supplied wav files for accentuated & standard sounds.
<langsyntaxhighlight lang="lb"> WindowWidth =230
WindowHeight =220
 
Line 1,108 ⟶ 1,341:
#w "flush"
 
wait</langsyntaxhighlight>
 
=={{header|Locomotive Basic}}==
{{trans|Python}}
<langsyntaxhighlight lang="locobasic">10 bpm=120:bpb=4
20 sleep=50*60/bpm
30 counter=0
Line 1,121 ⟶ 1,354:
120 counter=counter+1
130 if counter=bpb then counter=0
140 return</langsyntaxhighlight>
 
=={{header|Mathematica}}/{{header|Wolfram Language}}==
Shows/plays a visual and auditory metronome:
<langsyntaxhighlight Mathematicalang="mathematica">s = Sound[Play[Sin[1000 t], {t, 0, 0.05}]];
ss = Sound[Play[Sin[2000 t], {t, 0, 0.05}]];
bpm = 180;
Line 1,141 ⟶ 1,374:
];
Pause[slp];
]</langsyntaxhighlight>
 
=={{header|Nim}}==
Textual version only.
<langsyntaxhighlight Nimlang="nim">import os
 
proc metronome(tempo, pattern: Positive) =
Line 1,156 ⟶ 1,389:
sleep(delay)
 
metronome(72, 4)</langsyntaxhighlight>
 
=={{header|Perl}}==
The module <code>Time::HiRes</code> provides sub-second <tt>sleep</tt>. Text output only.
<langsyntaxhighlight lang="perl">use Time::HiRes qw(sleep gettimeofday);
 
local $| = 1; # autoflush
Line 1,179 ⟶ 1,412:
}
sleep($next_time - gettimeofday());
}</langsyntaxhighlight>
Sample run
{{out}}
Line 1,191 ⟶ 1,424:
===Graphical version===
Visual only, unless you want to uncomment the bell call.
<langsyntaxhighlight lang="perl">#!/usr/bin/perl
 
use strict;
Line 1,225 ⟶ 1,458:
-width => 5);
$mw->after( 60_000 / $bpm / 2 => \&tick );
}</langsyntaxhighlight>
 
=={{header|Phix}}==
Line 1,231 ⟶ 1,464:
{{libheader|Phix/online}}
You can run this online [http://phix.x10.mx/p2js/virtunome.htm here], with a few sizing/layout issues I could use a little help with, ideally w/o breaking anything else.
<!--<langsyntaxhighlight Phixlang="phix">(phixonline)-->
<span style="color: #000080;font-style:italic;">--
-- demo\rosetta\virtunome.exw
Line 1,519 ⟶ 1,752:
<span style="color: #7060A8;">IupClose</span><span style="color: #0000FF;">()</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<!--</langsyntaxhighlight>-->
 
=={{header|PicoLisp}}==
A short beep (440 Hz, 40 msec) is produced in a child process, while a "pendulum" is swinging left and right. Hitting any key will stop it.
<langsyntaxhighlight PicoLisplang="picolisp">(de metronome (Bpm)
(if (fork)
(let Pid @
Line 1,531 ⟶ 1,764:
(T (key (*/ 30000 Bpm)) (tell Pid 'bye)) )
(prinl) )
(wait) ) )</langsyntaxhighlight>
Test:
<langsyntaxhighlight PicoLisplang="picolisp">: (metronome 60)
/
-> NIL # A key was hit</langsyntaxhighlight>
 
=={{header|Pure Data}}==
Line 1,626 ⟶ 1,859:
</ul>
[[file:MetronomeScreenShot.png|PureBasic output|thumb|200px]]
<langsyntaxhighlight PureBasiclang="purebasic">Structure METRONOMEs
msPerBeat.i
BeatsPerMinute.i
Line 1,945 ⟶ 2,178:
Data.q $787A7A7976757678,$415380817C777576,$2C31000002005255,$30202C36202C3020
eClick:
EndDataSection</langsyntaxhighlight>
 
=={{header|Python}}==
<syntaxhighlight lang="python">
<lang Python>
#lang Python
import time
Line 1,967 ⟶ 2,200:
main()
 
</syntaxhighlight>
</lang>
 
=={{header|Racket}}==
<syntaxhighlight lang="racket">
<lang Racket>
#lang racket
 
Line 2,012 ⟶ 2,245:
(send* f (center) (show #t))
(void (thread flip))
</syntaxhighlight>
</lang>
 
=={{header|Raku}}==
Line 2,018 ⟶ 2,251:
 
This code only uses textual output, but any noise-generating commands may be substituted; as long as they are executed synchronously, and do not run longer than the specified duration, the timing loop will compensate, since the sequence operator is determining a list of absolute times for each <tt>sleep</tt> to target.
<syntaxhighlight lang="raku" perl6line>sub MAIN ($beats-per-minute = 72, $beats-per-bar = 4) {
my $duration = 60 / $beats-per-minute;
my $base-time = now + $duration;
Line 2,032 ⟶ 2,265:
sleep $next-time - now;
}
}</langsyntaxhighlight>
Sample run:
<pre>$ metronome 120 6
Line 2,046 ⟶ 2,279:
These REXX program examples are modeled after the Raku example.
===textual visual, no sound===
<langsyntaxhighlight lang="rexx">/*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. */
Line 2,064 ⟶ 2,297:
end /*until e≥es*/
end /*until et≥dur*/
/*stick a fork in it, we're all done. */</langsyntaxhighlight>
'''output''' &nbsp; when using the default inputs:
<per>
Line 2,077 ⟶ 2,310:
===with sound, REGINA only===
This REXX version &nbsp; ''only'' &nbsp; executes when using the Regina REXX interpreter.
<langsyntaxhighlight lang="rexx">/*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. */
Line 2,099 ⟶ 2,332:
end /*until e≥es*/
end /*until et≥dur*/
/*stick a fork in it, we're all done. */</langsyntaxhighlight>
 
===with sound, PC/REXX only===
<langsyntaxhighlight lang="rexx">/*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. */
Line 2,124 ⟶ 2,357:
end /*until e≥es*/
end /*until et≥dur*/
/*stick a fork in it, we're all done. */</langsyntaxhighlight>
 
=={{header|RPL}}==
« .02 0 → pattern duration beat
« -56 CF <span style="color:grey">''@ sound ON'' </span>
60 SWAP / duration - →NUM
'''DO''' "Beat!" 1 DISP
440 'beat' INCR pattern MOD 1 2 IFTE * duration BEEP
CLLCD DUP WAIT
'''UNTIL''' KEY '''END''' DROP2
» » '<span style="color:blue">METRO</span>' STO <span style="color:grey">''@ ( bpm pattern → )'' </span>
 
=={{header|Ruby}}==
This code rings the audible bell on every beat and write "And n" to stdout where n is the bar number that was just finished
<langsyntaxhighlight lang="ruby">
#!/usr/bin/ruby
 
Line 2,143 ⟶ 2,386:
sleep(60.0/bpm)
end
</syntaxhighlight>
</lang>
 
=={{header|Scala}}==
<langsyntaxhighlight Scalalang="scala">def metronome(bpm: Int, bpb: Int, maxBeats: Int = Int.MaxValue) {
val delay = 60000L / bpm
var beats = 0
Line 2,159 ⟶ 2,402:
}
 
metronome(120, 4, 20) // limit to 20</langsyntaxhighlight>
{{Out}} See it running in your browser by [https://scastie.scala-lang.org/7iejBcWqQISAIGtBCG6BNQ Scastie (JVM)].
 
=={{header|Sidef}}==
<langsyntaxhighlight lang="ruby">func metronome (beats_per_minute = 72, beats_per_bar = 4) {
 
var counter = 0
Line 2,182 ⟶ 2,425:
}
 
say metronome(ARGV.map{ Num(_) }...)</langsyntaxhighlight>
{{out}}
<pre>
Line 2,198 ⟶ 2,441:
=={{header|Tcl}}==
This code only rings the bell on the high beat, which occurs at the start of the bar.
<langsyntaxhighlight lang="tcl">package require Tcl 8.5
 
lassign $argv bpm bpb
Line 2,223 ⟶ 2,466:
# Run the metronome until the user uses Ctrl+C...
beat
vwait forever</langsyntaxhighlight>
It might be executed like this:
<langsyntaxhighlight lang="bash">tclsh8.5 metronome.tcl 90 4</langsyntaxhighlight>
 
=={{header|Wren}}==
{{trans|Kotlin}}
Modified to ring the bell on each beat.
<langsyntaxhighlight ecmascriptlang="wren">import "timer" for Timer
import "io" for Stdout
 
Line 2,246 ⟶ 2,489:
}
 
metronome.call(120, 4, 20) // limit to 20 beats</langsyntaxhighlight>
 
{{out}}
Line 2,256 ⟶ 2,499:
TICK tick tick tick
</pre>
 
=={{header|XPL0}}==
<syntaxhighlight lang "XPL0">int BPM, Odd, Time0, Delay;
[Text(0, "Beats per minute: ");
BPM:= IntIn(0);
Odd:= true;
Delay:= 60_000_000/BPM; \microseconds per beat
repeat Time0:= GetTime;
repeat until GetTime-Time0 >= Delay;
Text(0, if Odd then "tick" else " TOCK^m^j");
Odd:= not Odd;
until KeyHit;
]</syntaxhighlight>
{{out}}
<pre>
Beats per minute: 120
tick TOCK
tick TOCK
tick TOCK
tick TOCK
tick</pre>
 
{{omit from|GUISS}}
1,151

edits