Metronome: Difference between revisions

Content added Content deleted
m (minor rewording)
(+C)
Line 5: 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.
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>