Metronome: Difference between revisions

+C
m (minor rewording)
(+C)
Line 5:
 
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.
 
=={{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.
<lang c>#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;
}</lang>
Anonymous user