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> |